<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>hocgin (๑`灬´๑)</title>
  <icon>https://www.gravatar.com/avatar/c00cd16720e00537b9bbb0f8b46e39fe</icon>
  <subtitle>Great minds have purpose, others have wishes.</subtitle>
  <link href="https://hocg.in/atom.xml" rel="self"/>
  
  <link href="https://hocg.in/"/>
  <updated>2023-07-02T05:18:54.912Z</updated>
  <id>https://hocg.in/</id>
  
  <author>
    <name>hocgin</name>
    <email>hocgin@gamil.com</email>
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>让你3步搞定单点登陆</title>
    <link href="https://hocg.in/2020/12/10/%E8%AE%A9%E4%BD%A03%E6%AD%A5%E6%90%9E%E5%AE%9A%E5%8D%95%E7%82%B9%E7%99%BB%E9%99%86/"/>
    <id>https://hocg.in/2020/12/10/%E8%AE%A9%E4%BD%A03%E6%AD%A5%E6%90%9E%E5%AE%9A%E5%8D%95%E7%82%B9%E7%99%BB%E9%99%86/</id>
    <published>2020-12-10T10:28:29.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>用超级少的代码来实现单点登陆和社交登陆。</p><span id="more"></span><h3 id="目录"><a href="#目录" class="headerlink" title="目录"></a>目录</h3><ul><li>第一步，改一下本地 host</li><li>第二步，构建单点服务端(SsoServer)</li><li>第三步，构建单点客户端(Servlet - Spring Boot)</li><li>第四步，构建单点客户端(WebFlux - Spring Gateway)</li><li>扩展: 集成社交登陆(GitHub)</li><li>项目源码</li></ul><h3 id="第一步，改一下本地-host"><a href="#第一步，改一下本地-host" class="headerlink" title="第一步，改一下本地 host"></a>第一步，改一下本地 host</h3><blockquote><p>这边交代一下，我们的 host 配置</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1 example.hocgin.local</span><br><span class="line">127.0.0.1 example2.hocgin.local</span><br><span class="line">127.0.0.1 sso.hocgin.local</span><br></pre></td></tr></table></figure><h3 id="第二步，构建单点服务机-SsoServer"><a href="#第二步，构建单点服务机-SsoServer" class="headerlink" title="第二步，构建单点服务机(SsoServer)"></a>第二步，构建单点服务机(SsoServer)</h3><ol><li>引入基础依赖<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">xml</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-oauth2-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-oauth2<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">xml</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li>在 Spring Security 进行配置<br>2.1 配置 Web Security<blockquote><p>这个主要是对登陆的方式和URI进行配置，如果使用默认的话只要开启 OAuth2.0 的配置即可。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Created by hocgin on 2020/1/6.</span></span><br><span class="line"><span class="comment"> * email: hocgin@gmail.com</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> hocgin</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@EnableWebSecurity</span></span><br><span class="line"><span class="meta">@RequiredArgsConstructor(onConstructor = @__(@Lazy))</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WebSecurityConfigurer</span> <span class="keyword">extends</span> <span class="title class_">WebSecurityConfigurerAdapter</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> AuthenticationConfigs authenticationConfigs;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> UserDetailsService userDetailsService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 基础信息配置</span></span><br><span class="line">        http.csrf().disable()</span><br><span class="line">            .cors().disable()</span><br><span class="line">            .authorizeRequests()</span><br><span class="line">            <span class="comment">// 使用 GitHub 进行社交登陆</span></span><br><span class="line">            .antMatchers(<span class="string">&quot;/login/oauth2/code/github&quot;</span>).permitAll()</span><br><span class="line">            .anyRequest().authenticated().and()</span><br><span class="line">        ;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 异常处理配置(这边针对AJAX进行不同处理，如果不需要可以忽略)</span></span><br><span class="line">        http.exceptionHandling()</span><br><span class="line">            .defaultAuthenticationEntryPointFor(<span class="keyword">new</span> <span class="title class_">AjaxAuthenticationEntryPoint</span>(), <span class="keyword">new</span> <span class="title class_">IsAjaxRequestMatcher</span>())</span><br><span class="line">            .defaultAccessDeniedHandlerFor(<span class="keyword">new</span> <span class="title class_">AjaxAccessDeniedHandler</span>(), <span class="keyword">new</span> <span class="title class_">IsAjaxRequestMatcher</span>());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 登陆相关配置</span></span><br><span class="line">        authenticationConfigs.configure(http, authenticationManagerBean());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 这边省略了大量非重代码..</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AuthenticationConfigs</span> &#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">LOGIN_SUCCESS_PAGE</span> <span class="operator">=</span> <span class="string">&quot;/index&quot;</span>;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">LOGIN_PAGE</span> <span class="operator">=</span> <span class="string">&quot;/login&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(HttpSecurity http, AuthenticationManager authenticationManager)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="keyword">final</span> <span class="type">AuthorizedSuccessHandle</span> <span class="variable">successHandler</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AuthorizedSuccessHandle</span>(LOGIN_SUCCESS_PAGE);</span><br><span class="line">        <span class="keyword">final</span> <span class="type">AuthorizedFailureHandle</span> <span class="variable">failureHandle</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AuthorizedFailureHandle</span>(LOGIN_PAGE);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ==== OAuth2.0 ====</span></span><br><span class="line">        http.oauth2Client();</span><br><span class="line">        http.oauth2Login().loginPage(LOGIN_PAGE);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ==== Form 表单 ====</span></span><br><span class="line">        &#123;</span><br><span class="line">            http.formLogin().loginPage(LOGIN_PAGE)</span><br><span class="line">                .successHandler(successHandler)</span><br><span class="line">                .failureHandler(failureHandle)</span><br><span class="line">                .permitAll();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>2.2 资源服务配置<blockquote><p>主要是配置资源的访问权限，可以理解为配置单点客户机的用户名和密码</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@EnableAuthorizationServer</span></span><br><span class="line"><span class="meta">@RequiredArgsConstructor(onConstructor = @__(@Lazy))</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AuthorizationServerConfig</span> <span class="keyword">extends</span> <span class="title class_">AuthorizationServerConfigurerAdapter</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> AuthenticationManager authenticationManager;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> PasswordEncoder passwordEncoder;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> SsoProperties properties;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(ClientDetailsServiceConfigurer clients)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 这边使用内存的方式来存储，单点客户端信息</span></span><br><span class="line">        <span class="type">InMemoryClientDetailsServiceBuilder</span> <span class="variable">builder</span> <span class="operator">=</span> clients.inMemory();</span><br><span class="line">        <span class="keyword">for</span> (SsoProperties.Client client : properties.getClients()) &#123;</span><br><span class="line">            builder.withClient(client.getClientId())</span><br><span class="line">                .secret(passwordEncoder.encode(client.getClientSecret()))</span><br><span class="line">                .authorizedGrantTypes(<span class="string">&quot;client_credentials&quot;</span>, <span class="string">&quot;authorization_code&quot;</span>, <span class="string">&quot;refresh_token&quot;</span>, <span class="string">&quot;password&quot;</span>)</span><br><span class="line">                .scopes(<span class="string">&quot;user_info&quot;</span>)</span><br><span class="line">                .redirectUris(client.getRedirectUris())</span><br><span class="line">                .autoApprove(<span class="literal">true</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(AuthorizationServerSecurityConfigurer oauthServer)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        oauthServer.allowFormAuthenticationForClients()</span><br><span class="line">            .tokenKeyAccess(<span class="string">&quot;permitAll()&quot;</span>)</span><br><span class="line">            .checkTokenAccess(<span class="string">&quot;isAuthenticated()&quot;</span>)</span><br><span class="line">        ;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">configure</span><span class="params">(AuthorizationServerEndpointsConfigurer endpoints)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        endpoints.authenticationManager(authenticationManager);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>2.3 配置允许的单点客户端账户<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">20000</span></span><br><span class="line"><span class="attr">sso:</span></span><br><span class="line">  <span class="attr">oauth:</span></span><br><span class="line">    <span class="attr">clients:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">client-id:</span> <span class="string">client_example</span></span><br><span class="line">        <span class="attr">client-secret:</span> <span class="string">hocgin</span></span><br><span class="line">        <span class="attr">redirect-uris:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="string">http://example.hocgin.local:20001/login/oauth2/code/custom</span></span><br><span class="line">          <span class="bullet">-</span> <span class="string">http://example2.hocgin.local:20002/login/oauth2/code/custom</span></span><br></pre></td></tr></table></figure></li></ol><p>⚠️ 注意哦，这边只是说明了单点服务端的一些重点配置，如果需要完整的配置可以参考文章末尾的源码哈。当然这边已经是最最复杂的部分了。如果你已经看到这边了，恭喜你！后面啥代码都不用写啦。</p><h3 id="第三步，构建单点客户机-Servlet-Spring-Boot"><a href="#第三步，构建单点客户机-Servlet-Spring-Boot" class="headerlink" title="第三步，构建单点客户机(Servlet) - Spring Boot"></a>第三步，构建单点客户机(Servlet) - Spring Boot</h3><ol><li>引入依赖<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>in.hocg.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>sso-client-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li>进行项目配置<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">20002</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">security:</span></span><br><span class="line">    <span class="attr">oauth2:</span></span><br><span class="line">      <span class="attr">shostname:</span> <span class="string">http://sso.hocgin.local:20000</span></span><br><span class="line">      <span class="attr">client:</span></span><br><span class="line">        <span class="attr">registration:</span></span><br><span class="line">          <span class="attr">custom:</span></span><br><span class="line">            <span class="attr">client-id:</span> <span class="string">client_example</span></span><br><span class="line">            <span class="attr">client-secret:</span> <span class="string">hocgin</span></span><br><span class="line">            <span class="attr">redirect-uri:</span> <span class="string">&#x27;&#123;baseUrl&#125;/&#123;action&#125;/oauth2/code/&#123;registrationId&#125;&#x27;</span></span><br><span class="line">            <span class="attr">authorization-grant-type:</span> <span class="string">authorization_code</span></span><br><span class="line">        <span class="attr">provider:</span></span><br><span class="line">          <span class="attr">custom:</span></span><br><span class="line">            <span class="attr">user-info-uri:</span> <span class="string">$&#123;spring.security.oauth2.shostname&#125;/oauth/user</span></span><br><span class="line">            <span class="attr">authorization-uri:</span> <span class="string">$&#123;spring.security.oauth2.shostname&#125;/oauth/authorize</span></span><br><span class="line">            <span class="attr">token-uri:</span> <span class="string">$&#123;spring.security.oauth2.shostname&#125;/oauth/token</span></span><br><span class="line">            <span class="attr">user-name-attribute:</span> <span class="string">name</span></span><br><span class="line"><span class="attr">boot:</span></span><br><span class="line">  <span class="attr">sso:</span></span><br><span class="line">    <span class="attr">client:</span></span><br><span class="line">      <span class="attr">ignore-urls:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">&#x27;/ignore&#x27;</span></span><br></pre></td></tr></table></figure></li></ol><h3 id="第四步，构建单点客户机-WebFlux-Spring-Gateway"><a href="#第四步，构建单点客户机-WebFlux-Spring-Gateway" class="headerlink" title="第四步，构建单点客户机(WebFlux) - Spring Gateway"></a>第四步，构建单点客户机(WebFlux) - Spring Gateway</h3><ol><li>引入依赖<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>in.hocg.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>sso-client-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li>进行项目配置<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">security:</span></span><br><span class="line">    <span class="attr">oauth2:</span></span><br><span class="line">      <span class="attr">shostname:</span> <span class="string">http://sso.hocgin.local:20000</span></span><br><span class="line">      <span class="attr">client:</span></span><br><span class="line">        <span class="attr">registration:</span></span><br><span class="line">          <span class="attr">custom:</span></span><br><span class="line">            <span class="attr">client-id:</span> <span class="string">client_example</span></span><br><span class="line">            <span class="attr">client-secret:</span> <span class="string">hocgin</span></span><br><span class="line">            <span class="attr">redirect-uri:</span> <span class="string">&#x27;&#123;baseUrl&#125;/&#123;action&#125;/oauth2/code/&#123;registrationId&#125;&#x27;</span></span><br><span class="line">            <span class="attr">authorization-grant-type:</span> <span class="string">authorization_code</span></span><br><span class="line">        <span class="attr">provider:</span></span><br><span class="line">          <span class="attr">custom:</span></span><br><span class="line">            <span class="attr">user-info-uri:</span> <span class="string">$&#123;spring.security.oauth2.shostname&#125;/oauth/user</span></span><br><span class="line">            <span class="attr">authorization-uri:</span> <span class="string">$&#123;spring.security.oauth2.shostname&#125;/oauth/authorize</span></span><br><span class="line">            <span class="attr">token-uri:</span> <span class="string">$&#123;spring.security.oauth2.shostname&#125;/oauth/token</span></span><br><span class="line">            <span class="attr">user-name-attribute:</span> <span class="string">name</span></span><br><span class="line"></span><br><span class="line"><span class="attr">boot:</span></span><br><span class="line">  <span class="attr">sso:</span></span><br><span class="line">    <span class="attr">client:</span></span><br><span class="line">      <span class="attr">ignore-urls:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">&#x27;/ignore&#x27;</span></span><br></pre></td></tr></table></figure>嘿嘿，其实第三步和第四步是完完全全一样的啦！已经在 Servlet 和 Webflux 上做兼容了啦。当然以上的代码完全适用于任何 Spring Boot 项目，例如: Spring Boot Admin。</li></ol><h3 id="扩展-集成社交登陆-GitHub"><a href="#扩展-集成社交登陆-GitHub" class="headerlink" title="扩展: 集成社交登陆(GitHub)"></a>扩展: 集成社交登陆(GitHub)</h3><blockquote><p>如果我们需要集成一些标准的 OAuth2.0 只需要在 SSO-Server 上做集成就可以了。以下配置可以配置在 SSO-Server 上。</p></blockquote><ol><li>配置yml文件<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">security:</span></span><br><span class="line">    <span class="attr">oauth2:</span></span><br><span class="line">      <span class="attr">client:</span></span><br><span class="line">        <span class="attr">registration:</span></span><br><span class="line">          <span class="attr">github:</span></span><br><span class="line">            <span class="attr">client-id:</span> <span class="string">(填写你自己的)</span></span><br><span class="line">            <span class="attr">client-secret:</span> <span class="string">(填写你自己的)</span></span><br><span class="line">            <span class="attr">client-name:</span> <span class="string">Github</span> <span class="string">Login</span></span><br><span class="line">            <span class="attr">redirect-uri:</span> <span class="string">&#x27;&#123;baseUrl&#125;/&#123;action&#125;/oauth2/code/&#123;registrationId&#125;&#x27;</span></span><br></pre></td></tr></table></figure></li><li>在html代码里面使用<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">th:action</span>=<span class="string">&quot;@&#123;/oauth2/authorization/github&#125;&quot;</span> <span class="attr">method</span>=<span class="string">&quot;GET&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;hidden&quot;</span> <span class="attr">name</span>=<span class="string">&quot;scope&quot;</span> <span class="attr">value</span>=<span class="string">&quot;read_stream,user_posts,user_photos&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>&gt;</span>github<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>OK! 你已经简单的集成了GitHub的社交登陆了。没办法在水一篇了很遗憾..</li></ol><h3 id="运行演示"><a href="#运行演示" class="headerlink" title="运行演示"></a>运行演示</h3><p>流程: </p><ol><li>访问 example2.hocgin.local:20002&#x2F;user</li><li>登陆后跳转 example2.hocgin.local:20002&#x2F;user </li><li>查看 example.hocgin.local:20001&#x2F;user 登陆信息</li><li>查看 sso.hocgin.local:20000&#x2F;user 登陆信息</li></ol><p><img src="https://imgkr2.cn-bj.ufileos.com/785ff27a-a24e-4315-b10d-058d851ef3a2.gif?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=Wn%252BXztpizuc3cCuG2z1SdYqvf6o%253D&Expires=1608035391"></p><h3 id="项目源码"><a href="#项目源码" class="headerlink" title="项目源码"></a>项目源码</h3><ul><li><a href="https://github.com/hocgin/spring-boot-starters-project/tree/master/spring-boot-samples/sso-server-spring-boot-sample">SSO-Server</a></li><li><a href="https://github.com/hocgin/spring-boot-starters-project/tree/master/spring-boot-samples/sso-client-spring-boot-sample">SSO-Client(Spring Boot)</a></li><li><a href="https://github.com/hocgin/spring-boot-starters-project/tree/master/spring-boot-samples/sso-client-gateway-sample">SSO-Client(Spring Gateway)</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;用超级少的代码来实现单点登陆和社交登陆。&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="Spring" scheme="https://hocg.in/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>Java 命令工具</title>
    <link href="https://hocg.in/2019/05/12/Java%20%E5%91%BD%E4%BB%A4%E5%B7%A5%E5%85%B7/"/>
    <id>https://hocg.in/2019/05/12/Java%20%E5%91%BD%E4%BB%A4%E5%B7%A5%E5%85%B7/</id>
    <published>2019-05-12T19:37:49.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<h2 id="jps"><a href="#jps" class="headerlink" title="jps"></a>jps</h2><blockquote><p>显示当前用户的 Java 进程<br>jps [options] [hostid]</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 常用, 查看传入参数和main函数位置</span></span><br><span class="line">jps -lm</span><br><span class="line"><span class="comment"># 查看传入的jvm参数</span></span><br><span class="line">jps -v</span><br></pre></td></tr></table></figure><h2 id="jstat"><a href="#jstat" class="headerlink" title="jstat"></a>jstat</h2><blockquote><p>JVM 状态监控工具</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 最后一次 gc 调用情况</span></span><br><span class="line">jstat -gc [<span class="built_in">hostid</span>]</span><br><span class="line"><span class="comment"># 类加载情况</span></span><br><span class="line">jstat -class [<span class="built_in">hostid</span>]</span><br><span class="line"><span class="comment"># 实时编译情况</span></span><br><span class="line">jstat -compiler [<span class="built_in">hostid</span>]</span><br><span class="line"><span class="comment"># 虚拟机 三代(young,old,perm) 占用情况</span></span><br><span class="line">jstat -gccapacity [<span class="built_in">hostid</span>]</span><br><span class="line"><span class="comment"># GC 调用情况统计</span></span><br><span class="line">jstat -gcutil [<span class="built_in">hostid</span>]</span><br><span class="line"><span class="comment"># 年轻代对象</span></span><br><span class="line">jstat -gcnew [<span class="built_in">hostid</span>]</span><br><span class="line">jstat -gcnewcapacity [<span class="built_in">hostid</span>]</span><br><span class="line"><span class="comment"># old</span></span><br><span class="line">jstat -gcold [<span class="built_in">hostid</span>]</span><br><span class="line">jstat -gcoldcapacity [<span class="built_in">hostid</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 打印当前虚拟机执行信息</span></span><br><span class="line">jstat -printcompilation [<span class="built_in">hostid</span>]</span><br></pre></td></tr></table></figure><h2 id="jmap"><a href="#jmap" class="headerlink" title="jmap"></a>jmap</h2><blockquote><p>内存映射</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 查看堆内存 对象数量 和 占用</span></span><br><span class="line">jstat -histo:live [<span class="built_in">hostid</span>]</span><br></pre></td></tr></table></figure><h2 id="jstack"><a href="#jstack" class="headerlink" title="jstack"></a>jstack</h2><blockquote><p>栈快照</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jstack [<span class="built_in">hostid</span>]</span><br></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://juejin.im/post/5ac442946fb9a028d700cfdf">参考</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;jps&quot;&gt;&lt;a href=&quot;#jps&quot; class=&quot;headerlink&quot; title=&quot;jps&quot;&gt;&lt;/a&gt;jps&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;显示当前用户的 Java 进程&lt;br&gt;jps [options] [hostid]&lt;/p&gt;
&lt;/block</summary>
      
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="JVM" scheme="https://hocg.in/tags/JVM/"/>
    
  </entry>
  
  <entry>
    <title>关于网约车核心业务-推单相关设计整理</title>
    <link href="https://hocg.in/2019/04/18/%E5%85%B3%E4%BA%8E%E7%BD%91%E7%BA%A6%E8%BD%A6%E6%A0%B8%E5%BF%83%E4%B8%9A%E5%8A%A1-%E6%8E%A8%E5%8D%95%E7%9B%B8%E5%85%B3%E6%95%B4%E7%90%86/"/>
    <id>https://hocg.in/2019/04/18/%E5%85%B3%E4%BA%8E%E7%BD%91%E7%BA%A6%E8%BD%A6%E6%A0%B8%E5%BF%83%E4%B8%9A%E5%8A%A1-%E6%8E%A8%E5%8D%95%E7%9B%B8%E5%85%B3%E6%95%B4%E7%90%86/</id>
    <published>2019-04-18T18:20:20.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>网约车核心业务推单相关设计和整理。</p><span id="more"></span><h2 id="图"><a href="#图" class="headerlink" title="图"></a>图</h2><h3 id="抢单模式"><a href="#抢单模式" class="headerlink" title="抢单模式"></a>抢单模式</h3><p><img src="http://cdn.hocgin.top/%E6%8A%A2%E5%8D%95%E6%8E%A8%E5%8D%95.png" alt="抢单推单.png"><br><img src="http://cdn.hocgin.top/%E6%8A%A2%E5%8D%95%E6%8A%A2%E5%8D%95.png" alt="抢单抢单.png"></p><h3 id="自动派单模式"><a href="#自动派单模式" class="headerlink" title="自动派单模式"></a>自动派单模式</h3><p><img src="http://cdn.hocgin.top/%E8%87%AA%E5%8A%A8%E6%B4%BE%E5%8D%95.png" alt="自动派单.png"></p><h3 id="手动派单模式"><a href="#手动派单模式" class="headerlink" title="手动派单模式"></a>手动派单模式</h3><p><img src="http://cdn.hocgin.top/%E6%89%8B%E5%8A%A8%E6%B4%BE%E5%8D%95.png" alt="手动派单.png"></p><h2 id="一些说明"><a href="#一些说明" class="headerlink" title="一些说明"></a>一些说明</h2><h3 id="订单推送给司机-直接获取订单-x2F-手动派单-x2F-司机点击接受订单"><a href="#订单推送给司机-直接获取订单-x2F-手动派单-x2F-司机点击接受订单" class="headerlink" title="订单推送给司机(直接获取订单)&#x2F;手动派单&#x2F;司机点击接受订单"></a>订单推送给司机(直接获取订单)&#x2F;手动派单&#x2F;司机点击接受订单</h3><blockquote><p>绑定司机</p></blockquote><p>此处需要获取分布式锁，锁的资源为司机，因此可以用 司机ID 为锁的标识，绑定订单的司机时需使用 乐观锁方式 进行更新。</p><h3 id="检查是否中止推单"><a href="#检查是否中止推单" class="headerlink" title="检查是否中止推单"></a>检查是否中止推单</h3><ul><li>推荐使用 redis 进行标识是否终止订单推送，需要使用原子+过期特性。</li></ul><h3 id="用户下单"><a href="#用户下单" class="headerlink" title="用户下单"></a>用户下单</h3><blockquote><p>用户下单会发送多个消息</p></blockquote><h4 id="情况一-自动派单模式"><a href="#情况一-自动派单模式" class="headerlink" title="情况一: 自动派单模式"></a>情况一: 自动派单模式</h4><ul><li>发送自动派单消息</li><li>发送取消订单消息(延迟消息)</li></ul><h4 id="情况二-抢单模式"><a href="#情况二-抢单模式" class="headerlink" title="情况二: 抢单模式"></a>情况二: 抢单模式</h4><ul><li>发送抢单派单消息</li><li>发送抢单启动消息(延迟消息)</li><li>发送取消订单消息(延迟消息)</li></ul><h3 id="关于服务重启解决方案"><a href="#关于服务重启解决方案" class="headerlink" title="关于服务重启解决方案"></a>关于服务重启解决方案</h3><ul><li>重启后进行订单扫描处理(分批次拉取模式)</li><li>定时器核对订单状态，进行状态处理</li><li>消息进行合法校验(超时丢弃，记录日志)</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;网约车核心业务推单相关设计和整理。&lt;/p&gt;</summary>
    
    
    
    <category term="Web" scheme="https://hocg.in/categories/Web/"/>
    
    
    <category term="设计思路" scheme="https://hocg.in/tags/%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF/"/>
    
  </entry>
  
  <entry>
    <title>Linux 下网络相关的命令</title>
    <link href="https://hocg.in/2019/04/01/Linux%20%E4%B8%8B%E7%BD%91%E7%BB%9C%E7%9B%B8%E5%85%B3%E7%9A%84%E5%91%BD%E4%BB%A4/"/>
    <id>https://hocg.in/2019/04/01/Linux%20%E4%B8%8B%E7%BD%91%E7%BB%9C%E7%9B%B8%E5%85%B3%E7%9A%84%E5%91%BD%E4%BB%A4/</id>
    <published>2019-04-01T08:07:00.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>Linux 下网络相关的命令</p><span id="more"></span><h2 id="🔗"><a href="#🔗" class="headerlink" title="🔗"></a>🔗</h2><p><a href="https://linoxide.com/linux-command/use-ip-command-linux/">Linux-Nettools vs Iproute2</a></p><h2 id="net-tools"><a href="#net-tools" class="headerlink" title="net-tools"></a>net-tools</h2><h3 id="ifconfig"><a href="#ifconfig" class="headerlink" title="ifconfig"></a><code>ifconfig</code></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">enp2s0: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500</span><br><span class="line">        inet 192.168.8.23  netmask 255.255.255.0  broadcast 192.168.8.255</span><br><span class="line">        inet6 fe80::794c:57e0:a7ca:518e  prefixlen 64  scopeid 0x20&lt;link&gt;</span><br><span class="line">        ether 50:9a:4c:17:e9:da  txqueuelen 1000  (Ethernet)</span><br><span class="line">        RX packets 4412700  bytes 3603093632 (3.3 GiB)</span><br><span class="line">        RX errors 0  dropped 20  overruns 0  frame 0</span><br><span class="line">        TX packets 1877167  bytes 507480177 (483.9 MiB)</span><br><span class="line">        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0</span><br><span class="line"></span><br><span class="line">lo: flags=73&lt;UP,LOOPBACK,RUNNING&gt;  mtu 65536</span><br><span class="line">        inet 127.0.0.1  netmask 255.0.0.0</span><br><span class="line">        inet6 ::1  prefixlen 128  scopeid 0x10&lt;host&gt;</span><br><span class="line">        loop  txqueuelen 1000  (Local Loopback)</span><br><span class="line">        RX packets 14009901  bytes 2441347518 (2.2 GiB)</span><br><span class="line">        RX errors 0  dropped 0  overruns 0  frame 0</span><br><span class="line">        TX packets 14009901  bytes 2441347518 (2.2 GiB)</span><br><span class="line">        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0</span><br><span class="line"></span><br><span class="line">wlp3s0: flags=4099&lt;UP,BROADCAST,MULTICAST&gt;  mtu 1500</span><br><span class="line">        ether 54:13:79:5b:c3:29  txqueuelen 1000  (Ethernet)</span><br><span class="line">        RX packets 6  bytes 1296 (1.2 KiB)</span><br><span class="line">        RX errors 0  dropped 0  overruns 0  frame 0</span><br><span class="line">        TX packets 34  bytes 5037 (4.9 KiB)</span><br><span class="line">        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0</span><br></pre></td></tr></table></figure><ul><li>enp2s0: 网络设备号</li><li>flags&#x3D;4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;: 网络设备状态标识</li><li>mtu 1500: mtu</li><li>inet 192.168.8.23  netmask 255.255.255.0  broadcast 192.168.8.255: IPv4 协议</li><li>inet6 fe80::794c:57e0:a7ca:518e: IPv6 协议</li><li>ether 50:9a:4c:17:e9:da </li><li>TX: 发送&#x2F;上行  </li><li>RX: 接收&#x2F;下行 <ul><li>packets 4412700: 包总数量</li><li>bytes 2441347518 (2.2 GiB): 流量大小</li><li>errors 0: 错误包数量</li><li>dropped 0: 丢包数量</li><li>overruns 0: 超时包数量</li><li>collisions 0: 冲突包数量</li><li>frame 0: 帧数量</li></ul></li><li>txqueuelen 1000  (Ethernet): 存储传输数据缓存的大小</li><li>prefixlen 64</li><li>scopeid 0x20<link></li></ul><h3 id="route"><a href="#route" class="headerlink" title="route"></a><code>route</code></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Kernel IP routing table</span><br><span class="line">Destination     Gateway         Genmask         Flags Metric Ref    Use Iface</span><br><span class="line">default         192.168.8.1     0.0.0.0         UG    100    0        0 enp2s0</span><br><span class="line">192.168.8.0     0.0.0.0         255.255.255.0   U     100    0        0 enp2s0</span><br></pre></td></tr></table></figure><ul><li>Genmask: 子网掩码</li><li>Destination: 目的地  <code>Destination/Genmask 组成局域网</code><ul><li>default &#x3D; 0.0.0.0&#x2F;0.0.0.0</li></ul></li><li>Gateway: 网关</li><li>Flags: 网络标识<ul><li>U (route is up): 路由启动状态</li><li>H (target is a host): 目标是主机</li><li>G (use gateway): 需要使用网关来传输</li><li>R (reinstate route for dynamic routing): </li><li>D (dynamically installed by daemon or redirect): </li><li>M (modified from routing daemon or redirect): </li><li>! (reject route): 拒绝&#x2F;黑名单</li></ul></li><li>Metric: 目标的距离</li><li>Ref: </li><li>Use: 路线查找计数</li><li>Iface: 接收数据的网络接口 <code>网络出口网卡</code></li></ul><h2 id="iproute2"><a href="#iproute2" class="headerlink" title="iproute2"></a>iproute2</h2><h3 id="ip-link"><a href="#ip-link" class="headerlink" title="ip link"></a><code>ip link</code></h3><blockquote><p>配置网络设备参数<br>OSI 七层协议中, 二层相关信息<br>eg. MTU, MAC, 开关…</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">ip link show</span><br><span class="line">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000</span><br><span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br><span class="line">2: enp2s0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000</span><br><span class="line">    link/ether 50:9a:4c:17:e9:da brd ff:ff:ff:ff:ff:ff</span><br><span class="line">3: wlp3s0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN mode DORMANT group default qlen 1000</span><br><span class="line">    link/ether 54:13:79:5b:c3:29 brd ff:ff:ff:ff:ff:ff</span><br><span class="line"></span><br><span class="line"># 显示状态详情</span><br><span class="line">ip -s link show</span><br><span class="line">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000</span><br><span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br><span class="line">    RX: bytes  packets  errors  dropped overrun mcast   </span><br><span class="line">    2507975007 14838472 0       0       0       0       </span><br><span class="line">    TX: bytes  packets  errors  dropped carrier collsns </span><br><span class="line">    2507975007 14838472 0       0       0       0       </span><br><span class="line">2: enp2s0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000</span><br><span class="line">    link/ether 50:9a:4c:17:e9:da brd ff:ff:ff:ff:ff:ff</span><br><span class="line">    RX: bytes  packets  errors  dropped overrun mcast   </span><br><span class="line">    3657508487 4607298  0       23      0       154201  </span><br><span class="line">    TX: bytes  packets  errors  dropped carrier collsns </span><br><span class="line">    536627449  1943192  0       0       0       0       </span><br><span class="line">3: wlp3s0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN mode DORMANT group default qlen 1000</span><br><span class="line">    link/ether 54:13:79:5b:c3:29 brd ff:ff:ff:ff:ff:ff</span><br><span class="line">    RX: bytes  packets  errors  dropped overrun mcast   </span><br><span class="line">    1296       6        0       0       0       0       </span><br><span class="line">    TX: bytes  packets  errors  dropped carrier collsns </span><br><span class="line">    5037       34       0       0       0       0</span><br><span class="line">    </span><br><span class="line"># 操作特定网卡 eg. ip link set eth0 up</span><br><span class="line">ip link set &#123;网络设备&#125; &#123;操作&#125;</span><br><span class="line">- 网络设备: eg. enp2s0</span><br><span class="line">    - 操作</span><br><span class="line">        - up: 开启</span><br><span class="line">        - down: 关闭</span><br><span class="line">        - address: Mac 地址`ff:ff:ff:ff:ff:ff`</span><br><span class="line">        - name: 网络设备名称</span><br><span class="line">        - mtu: mtu值`1500`</span><br></pre></td></tr></table></figure><h3 id="ip-addr"><a href="#ip-addr" class="headerlink" title="ip addr"></a><code>ip addr</code></h3><blockquote><p>配置网络相关信息<br>OSI 七层协议中, 三层相关信息<br>eg. 网关, 子网掩码..</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000</span><br><span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br><span class="line">    inet 127.0.0.1/8 scope host lo</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 ::1/128 scope host </span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">2: enp2s0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000</span><br><span class="line">    link/ether 50:9a:4c:17:e9:da brd ff:ff:ff:ff:ff:ff</span><br><span class="line">    inet 192.168.8.23/24 brd 192.168.8.255 scope global noprefixroute enp2s0</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 fe80::794c:57e0:a7ca:518e/64 scope link noprefixroute </span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">3: wlp3s0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000</span><br><span class="line">    link/ether 54:13:79:5b:c3:29 brd ff:ff:ff:ff:ff:ff</span><br><span class="line"></span><br><span class="line"># 设定IP相关参数</span><br><span class="line">ip address &#123;add|del&#125; &#123;IP相关配置&#125; &#123;网络设备&#125; &#123;相关参数&#125;</span><br><span class="line">- add|del: 新增或删除</span><br><span class="line">- IP相关配置: eg. 192.168.8.23/24</span><br><span class="line">- 网络设备: eg. enp2s0</span><br><span class="line">- 相关参数:</span><br><span class="line">    - broadcast: 广播地址, &quot;+&quot;为自动计算</span><br><span class="line">    - label: 別名别名</span><br><span class="line">    - scope: 作用域</span><br><span class="line">        - global</span><br><span class="line">        - site  </span><br><span class="line">        - link</span><br><span class="line">        - host</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li><p>lo: 网卡label. </p></li><li><p>&lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt;: 网络设备状态标识 </p><ul><li>BROADCAST, MULTICAST: 可以发送广播, 可以发送多播包<ul><li>LOOPBACK: 本地环回</li></ul></li><li>UP: 网络设备状态</li><li>LOWER_UP: 已连线</li></ul></li><li><p>mtu 65536:  最大传输单元</p></li><li><p>qdisc pfifo_fast: 排队规则. </p><ul><li>noqueue</li><li>pfifo_fast</li></ul></li><li><p>group default: 所在组. </p></li><li><p>inet 127.0.0.1&#x2F;8: IPv4 地址及子网掩码</p></li><li><p>inet6 fe80::794c:57e0:a7ca:518e&#x2F;64: IPv6 地址及子网掩码</p></li><li><p>brd ff:ff:ff:ff:ff:ff: 广播地址</p></li><li><p>scope global: 作用域. </p><ul><li>global: 允许所有来源</li><li>site: 仅IPv6, 允许仅本机连接 </li><li>link: 仅允许自我连接</li><li>host: 仅允许本主机内部连接</li></ul></li><li><p>noprefixroute enp2s0</p></li><li><p>preferred_lft forever: </p></li><li><p>valid_lft forever: 有效期限</p></li><li><p>qlen 1000</p></li></ul><h3 id="ip-route"><a href="#ip-route" class="headerlink" title="ip route"></a><code>ip route</code></h3><blockquote><p>路由相关设置</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">ip route</span><br><span class="line">default via 192.168.8.1 dev enp2s0 proto static metric 100 </span><br><span class="line">192.168.8.0/24 dev enp2s0 proto kernel scope link src 192.168.8.23 metric 100</span><br><span class="line"></span><br><span class="line"># 设定route相关参数</span><br><span class="line">ip route &#123;add|del&#125; &#123;IP|网络&#125; &#123;via 网关&#125; &#123;网络设备&#125;</span><br><span class="line">- add|del: 新增或删除</span><br><span class="line">- IP|网络: eg. IP 或 192.168.8.23/24</span><br><span class="line">- 网关: 指定出口网关(可选)</span><br><span class="line">- 网络设备: 指定出口网络设备 eg. enp2s0</span><br><span class="line">- mtu: 配置mtu参数</span><br></pre></td></tr></table></figure><ul><li>192.168.8.0&#x2F;24: 网络</li><li>dev enp2s0: 网络设备</li><li>proto kernel: 路由协议 [redirect, kernel, boot, static, ra]</li><li>scope link: 作用域</li></ul><h2 id="网络侦查"><a href="#网络侦查" class="headerlink" title="网络侦查"></a>网络侦查</h2><h3 id="ping"><a href="#ping" class="headerlink" title="ping"></a>ping</h3><blockquote><p>网络状态</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">➜  ~ ping www.baidu.com -c 5</span><br><span class="line">PING www.a.shifen.com (14.215.177.39) 56(84) bytes of data.</span><br><span class="line">64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=1 ttl=54 time=20.6 ms</span><br><span class="line">64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=2 ttl=54 time=20.5 ms</span><br><span class="line">64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=3 ttl=54 time=20.4 ms</span><br></pre></td></tr></table></figure><ul><li>64 bytes: ICMP封包大小</li><li>icmp_seq&#x3D;3: 侦测序号</li><li>ttl&#x3D;54: 默认255, 每经过一个含MAC地址时-1</li><li>time&#x3D;20.5 ms: 耗时</li></ul><h3 id="traceroute"><a href="#traceroute" class="headerlink" title="traceroute"></a>traceroute</h3><blockquote><p>网路状态</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">➜  ~  traceroute www.baidu.com </span><br><span class="line">traceroute to www.baidu.com (14.215.177.39), 30 hops max, 60 byte packets</span><br><span class="line"> 1  192.168.8.1 (192.168.8.1)  0.784 ms  1.348 ms  1.866 ms</span><br><span class="line"> 2  192.168.5.1 (192.168.5.1)  0.138 ms  0.174 ms  0.217 ms</span><br><span class="line"> 3  1.224.77.125.broad.xm.fj.dynamic.163data.com.cn (125.77.224.1)  1.458 ms  1.486 ms  1.694 ms</span><br><span class="line"> 4  61.154.238.229 (61.154.238.229)  4.692 ms  4.704 ms 61.154.238.225 (61.154.238.225)  2.400 ms</span><br><span class="line"> 5  61.154.238.77 (61.154.238.77)  5.834 ms 117.30.27.185 (117.30.27.185)  1.948 ms 61.154.238.77 (61.154.238.77)  6.106 ms</span><br><span class="line"> 6  * 202.97.40.169 (202.97.40.169)  19.847 ms 202.97.78.37 (202.97.78.37)  19.233 ms</span><br><span class="line"> 7  113.96.4.90 (113.96.4.90)  32.771 ms  28.773 ms 113.96.4.106 (113.96.4.106)  42.485 ms</span><br><span class="line"> 8  * * *</span><br><span class="line"> 9  14.29.117.234 (14.29.117.234)  19.359 ms 14.29.121.182 (14.29.121.182)  17.646 ms 14.29.121.190 (14.29.121.190)  28.106 ms</span><br><span class="line">10  * * *</span><br><span class="line">11  * * * </span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>每个序号都是同一层进行三次连接的耗时</li><li><code>* * *</code>: 可能是防火墙问题或路由问题</li></ul><h3 id="netstat"><a href="#netstat" class="headerlink" title="netstat"></a>netstat</h3><blockquote><p>查看本机的网络连接</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 目前所有的网络线路状态</span><br><span class="line"># netstat -tulnp</span><br><span class="line">Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    </span><br><span class="line">tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      10247/node </span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>Proto: 网络协议</li><li>Recv-Q: 未使用字节</li><li>Send-Q: 没有确认的字节</li><li>Local Address: 本地地址+端口</li><li>Foreign Address: 目标地址+端口</li><li>stat: 状态<ul><li>ESTABLISED: 已连线</li><li>SYN_SENT: 发送连线确认包</li><li>SYN_RECV: 接收连线确认包</li><li>FIN_WAIT1: 正在断线中-第一步</li><li>FIN_WAIT2: 正在断线中(等待对方确认)-第二步</li><li>TIME_WAIT: 已断线(等待关闭)-第三步</li><li>LISTEN: 正在监听</li></ul></li><li>PID&#x2F;Program name: 进程和PID</li></ul><h2 id="host-nslookup-dig"><a href="#host-nslookup-dig" class="headerlink" title="host, nslookup, dig"></a>host, nslookup, dig</h2><blockquote><p>域名转IP</p></blockquote><h3 id="host"><a href="#host" class="headerlink" title="host"></a>host</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">➜  ~ host www.baidu.com 114.114.114.114</span><br><span class="line">Using domain server:</span><br><span class="line">Name: 114.114.114.114</span><br><span class="line">Address: 114.114.114.114#53</span><br><span class="line">Aliases: </span><br><span class="line"></span><br><span class="line">www.baidu.com is an alias for www.a.shifen.com.</span><br><span class="line">www.a.shifen.com has address 14.215.177.39</span><br><span class="line">www.a.shifen.com has address 14.215.177.38</span><br></pre></td></tr></table></figure><h3 id="nslookup"><a href="#nslookup" class="headerlink" title="nslookup"></a>nslookup</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">➜  ~ nslookup www.google.com</span><br><span class="line">Server:218.85.152.99</span><br><span class="line">Address:218.85.152.99#53</span><br><span class="line"></span><br><span class="line">Non-authoritative answer:</span><br><span class="line">Name:www.google.com</span><br><span class="line">Address: 75.126.150.210</span><br><span class="line">Name:www.google.com</span><br><span class="line">Address: 2400:cb00:2048:1::6814:224e</span><br></pre></td></tr></table></figure><h3 id="dig"><a href="#dig" class="headerlink" title="dig"></a>dig</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><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">➜  ~ dig www.google.com</span><br><span class="line"></span><br><span class="line">; &lt;&lt;&gt;&gt; DiG 9.11.3-1-Debian &lt;&lt;&gt;&gt; www.google.com</span><br><span class="line">;; global options: +cmd</span><br><span class="line">;; Got answer:</span><br><span class="line">;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 26052</span><br><span class="line">;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 8</span><br><span class="line"></span><br><span class="line">;; QUESTION SECTION:</span><br><span class="line">;www.google.com.INA</span><br><span class="line"></span><br><span class="line">;; ANSWER SECTION:</span><br><span class="line">www.google.com.600INA75.126.150.210</span><br><span class="line"></span><br><span class="line">;; AUTHORITY SECTION:</span><br><span class="line">google.com.153873INNSns2.google.com.</span><br><span class="line">google.com.153873INNSns1.google.com.</span><br><span class="line">google.com.153873INNSns3.google.com.</span><br><span class="line">google.com.153873INNSns4.google.com.</span><br><span class="line"></span><br><span class="line">;; ADDITIONAL SECTION:</span><br><span class="line">ns1.google.com.340640INA216.239.32.10</span><br><span class="line">ns1.google.com.160867INAAAA2001:4860:4802:32::a</span><br><span class="line">ns2.google.com.147310INA216.239.34.10</span><br><span class="line">ns2.google.com.167153INAAAA2001:4860:4802:34::a</span><br><span class="line">ns3.google.com.170088INA216.239.36.10</span><br><span class="line">ns3.google.com.343381INAAAA2001:4860:4802:36::a</span><br><span class="line">ns4.google.com.342199INA216.239.38.10</span><br><span class="line">ns4.google.com.340238INAAAA2001:4860:4802:38::a</span><br><span class="line"></span><br><span class="line">;; Query time: 3 msec</span><br><span class="line">;; SERVER: 218.85.152.99#53(218.85.152.99)</span><br><span class="line">;; WHEN: Tue Apr 02 11:54:08 CST 2019</span><br><span class="line">;; MSG SIZE  rcvd: 296</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="Hook"><a href="#Hook" class="headerlink" title="Hook"></a>Hook</h2><ul><li>tcpdump<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><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">➜  ~ sudo tcpdump -i enp2s0</span><br><span class="line">tcpdump: verbose output suppressed, use -v or -vv for full protocol decode</span><br><span class="line">listening on enp2s0, link-type EN10MB (Ethernet), capture size 262144 bytes</span><br><span class="line">16:03:36.920320 IP 192.168.8.23.32842 &gt; 106.37.75.114.80: Flags [.], ack 1334, win 1134, options [nop,nop,TS val 2465645746 ecr 4170196622], length 0</span><br><span class="line">16:07:25.848706 IP 192.168.8.23.45512 &gt; 203.107.41.32.9015: Flags [P.], seq 858:897, ack 771, win 37440, length 39</span><br><span class="line">15:23:53.248962 IP6 fe80::485c:9c0f:61ce:2886 &gt; ff02::1:ffb6:3f84: ICMP6, neighbor solicitation, who has fe80::32e1:71ff:feb6:3f84, length 32</span><br><span class="line">15:23:53.249199 IP 192.168.8.23.55804 &gt; FJ-DNS.xm.fj.cn.domain: 41679+ PTR? 4.8.f.3.6.b.f.f.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.f.f.ip6.arpa. (90)</span><br><span class="line">15:23:53.251749 IP FJ-DNS.xm.fj.cn.domain &gt; 192.168.8.23.55804: 41679 NXDomain* 0/1/0 (154)</span><br><span class="line">15:23:53.251809 IP 192.168.8.23.57994 &gt; FJ-DNS.xm.fj.cn.domain: 8140+ PTR? 6.8.8.2.e.c.1.6.f.0.c.9.c.5.8.4.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa. (90)</span><br><span class="line">15:23:53.254241 ARP, Request who-has 192.168.8.250 tell 192.168.8.134, length 46</span><br><span class="line">15:23:53.255081 IP FJ-DNS.xm.fj.cn.domain &gt; 192.168.8.23.57994: 8140 NXDomain* 0/1/0 (139)</span><br><span class="line"></span><br><span class="line"># 指令</span><br><span class="line">tcpdump [-AennqX] [-i 网络接口] [-w 导出文件] [-c 次数] \</span><br><span class="line">                      [-r 导入文件] [过滤规则]</span><br><span class="line">-A： 显示为ASCII码</span><br><span class="line">-e: OSI 二层显示MAC封包</span><br><span class="line">-nn: 解析地址(显示为ip和端口)</span><br><span class="line">-q: 打印简短的信息</span><br><span class="line">-X: 显示16进制及ASCII码</span><br><span class="line">-i: 需要监听的网络接口</span><br><span class="line">-w: 写出存储文件</span><br><span class="line">-r: 读取存储文件</span><br><span class="line">-c: 监听数量</span><br><span class="line">过滤规则: 可以使用 and 和 or 进行组合</span><br><span class="line">    - &#x27;host foo&#x27;, &#x27;host 127.0.0.1&#x27; ：监听特定的主机</span><br><span class="line">    - &#x27;net 192.168&#x27; ：监听特定的网段</span><br><span class="line">    - &#x27;src host 127.0.0.1&#x27; &#x27;dst net 192.168&#x27;： 监听特定的来源(src)或目的地(dst)</span><br><span class="line">    - &#x27;tcp port 21&#x27;：监听特定的协议，如 tcp, udp, arp, ether..</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li>15:23:53.248962: 时:分:秒.毫秒</li><li>IP: 使用的协议</li><li>192.168.8.23.32842 &gt;: 发起端</li><li>106.37.75.114.80: 接收端</li><li>Flags [.]: 传输标识<ul><li>[.P]: 推送<code>PUSH</code></li></ul></li><li>ack 1334: ack 号</li><li>seq 858:897: 传输资料 858~897 byte</li></ul><h3 id="iptables"><a href="#iptables" class="headerlink" title="iptables"></a>iptables</h3><blockquote><p>访问控制</p></blockquote><h3 id="tc"><a href="#tc" class="headerlink" title="tc"></a>tc</h3><blockquote><p>流量控制  </p></blockquote><h3 id="mtr"><a href="#mtr" class="headerlink" title="mtr"></a>mtr</h3><blockquote><p>显示网络路径的状况</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;Linux 下网络相关的命令&lt;/p&gt;</summary>
    
    
    
    <category term="Linux" scheme="https://hocg.in/categories/Linux/"/>
    
    
    <category term="Linux" scheme="https://hocg.in/tags/Linux/"/>
    
    <category term="TCP/IP" scheme="https://hocg.in/tags/TCP-IP/"/>
    
  </entry>
  
  <entry>
    <title>Elasticsearch 随手记</title>
    <link href="https://hocg.in/2019/03/23/Elasticsearch%20%E9%9A%8F%E6%89%8B%E8%AE%B0/"/>
    <id>https://hocg.in/2019/03/23/Elasticsearch%20%E9%9A%8F%E6%89%8B%E8%AE%B0/</id>
    <published>2019-03-23T13:53:00.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>Elasticsearch 随手记 😋</p><span id="more"></span><h2 id="ElasticSearch-对比-MySQL"><a href="#ElasticSearch-对比-MySQL" class="headerlink" title="ElasticSearch 对比 MySQL"></a>ElasticSearch 对比 MySQL</h2><ul><li>Index -&gt; Database</li><li>Type -&gt; Table</li><li>Document -&gt; Row</li></ul><hr><h2 id="索引模版数据类型"><a href="#索引模版数据类型" class="headerlink" title="索引模版数据类型"></a>索引模版数据类型</h2><ul><li>字符串类型 <del>string</del>,text,keyword </li><li>整数类型 integer,long,short,byte </li><li>浮点类型 double,float,half_float,scaled_float </li><li>逻辑类型 boolean </li><li>日期类型 date </li><li>范围类型 range </li><li>二进制类型 binary </li><li>复合类型 数组类型 array </li><li>对象类型 object </li><li>嵌套类型 nested </li><li>地理类型 地理坐标类型 geo_point </li><li>地理地图 geo_shape </li><li>特殊类型 IP类型 ip </li><li>范围类型 completion </li><li>令牌计数类型 token_count </li><li>附件类型 attachment </li><li>抽取类型 percolator</li></ul><hr><h2 id="API-接口"><a href="#API-接口" class="headerlink" title="API 接口"></a>API 接口</h2><blockquote><p>pretty 格式化<br>explain&#x3D;true 分析</p><ul><li>通配符</li></ul></blockquote><h3 id="监控操作"><a href="#监控操作" class="headerlink" title="监控操作"></a>监控操作</h3><ul><li>监控<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 查询所有监控指令</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XGET http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/_cat</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="节点操作"><a href="#节点操作" class="headerlink" title="节点操作"></a>节点操作</h3><ul><li>查看节点状态<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 查看设置</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XGET http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/_cluster/settings?pretty</span></span><br></pre></td></tr></table></figure></li><li>实时更改配置<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># 永久生效</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XPUT http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/_cluster/settings -H &quot;Content-type: application/json&quot; -d &#x27;&#123;</span></span><br><span class="line">    <span class="attr">&quot;persistent&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span>&#x27;</span><br><span class="line"># 暂时生效</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XPUT http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/_cluster/settings -H &quot;Content-type: application/json&quot; -d &#x27;&#123;</span></span><br><span class="line">    <span class="attr">&quot;transient&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span>&#x27;</span><br></pre></td></tr></table></figure></li></ul><h3 id="数据操作"><a href="#数据操作" class="headerlink" title="数据操作"></a>数据操作</h3><ul><li>创建索引模版<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XPUT http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/db_test2 -H &quot;Content-type: application/json&quot; -d &#x27;&#123;</span></span><br><span class="line">    <span class="attr">&quot;settings&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span></span><br><span class="line">        # 节点数量</span><br><span class="line">        <span class="attr">&quot;number_of_replicas&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line">        # 分片数量</span><br><span class="line">        # <span class="attr">&quot;number_of_shards&quot;</span><span class="punctuation">:</span> <span class="number">5</span><span class="punctuation">,</span></span><br><span class="line">        # 索引存储类型</span><br><span class="line">        # <span class="attr">&quot;index.store.type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;niofs&quot;</span><span class="punctuation">,</span></span><br><span class="line">        # 默认检索字段</span><br><span class="line">        # <span class="attr">&quot;index.query.default_field&quot;</span><span class="punctuation">:</span> <span class="string">&quot;title&quot;</span></span><br><span class="line">        # <span class="attr">&quot;index.unassigned.node_left.delayed_timeout&quot;</span><span class="punctuation">:</span> <span class="string">&quot;5m&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;mappings&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;example&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            # 动态变更</span><br><span class="line">            <span class="attr">&quot;dynamic&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">            # <span class="number">5.</span>x 以上废除</span><br><span class="line">            <span class="attr">&quot;_all&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;enabled&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;properties&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;example_id&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;long&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;text&quot;</span><span class="punctuation">,</span></span><br><span class="line">                    # 指定分词器</span><br><span class="line">                    <span class="attr">&quot;analyzer&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ik_max_word&quot;</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;search_analyzer&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ik_max_word&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;text&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;keyword&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;title&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;text&quot;</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;createdAt&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;date&quot;</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;format&quot;</span><span class="punctuation">:</span> <span class="string">&quot;strict_date_optional_time||epoch_millis&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;age&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;integer&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;location&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    # es 中存储结构为<span class="punctuation">:</span> <span class="punctuation">&#123;</span>lon<span class="punctuation">:</span> <span class="number">0.000</span><span class="punctuation">,</span> lat<span class="punctuation">:</span> <span class="number">0.000</span><span class="punctuation">&#125;</span></span><br><span class="line">                    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;geo_point&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;suggest&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;completion&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span>&#x27;</span><br></pre></td></tr></table></figure></li><li>删除索引模版<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XDELETE http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/db_test</span></span><br></pre></td></tr></table></figure></li><li>查询索引模版<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XGET http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/db_test\?pretty</span></span><br></pre></td></tr></table></figure></li><li>插入数据<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XPOST http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/db_test/example -H &quot;Content-type: application/json&quot; -d &#x27;&#123;</span></span><br><span class="line">    <span class="attr">&quot;example_id&quot;</span><span class="punctuation">:</span> <span class="number">666</span></span><br><span class="line"><span class="punctuation">&#125;</span>&#x27;</span><br></pre></td></tr></table></figure></li><li>查询数据<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"># 查询所有</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XPOST http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/db_test/example/_search?pretty</span></span><br><span class="line"># 按条件查询</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XPOST http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/db_test/example/_search?pretty&amp;explain=true -H &quot;Content-type: application/json&quot; -d &#x27;&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;match&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;example_id&quot;</span><span class="punctuation">:</span> <span class="number">666</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span>&#x27;</span><br><span class="line"></span><br><span class="line"># 查询指定</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XGET http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/db_test/example/PiAmoGkBJAdUJ3wD4CMC?pretty=true</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="分析操作"><a href="#分析操作" class="headerlink" title="分析操作"></a>分析操作</h3><ul><li>分词器接口<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># 使用默认分词器</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XPOST http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/_analyze?pretty -H &#x27;Content-Type:application/json&#x27; -d&#x27;&#123; </span></span><br><span class="line">    <span class="attr">&quot;text&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Hello World&quot;</span> </span><br><span class="line"><span class="punctuation">&#125;</span>&#x27;</span><br><span class="line"># 使用指定分词器</span><br><span class="line">curl --user elastic<span class="punctuation">:</span>changeme -XPOST http<span class="punctuation">:</span><span class="comment">//127.0.0.1:9200/_analyze?pretty -H &#x27;Content-Type:application/json&#x27; -d&#x27;&#123;</span></span><br><span class="line">    <span class="attr">&quot;analyzer&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ik_max_word&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;text&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Hello World&quot;</span> </span><br><span class="line"><span class="punctuation">&#125;</span>&#x27;</span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="Java-调用"><a href="#Java-调用" class="headerlink" title="Java 调用"></a>Java 调用</h2><ul><li>创建索引<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">createOrUpdateIndex</span><span class="params">(Long id)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (house == <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="type">ExampleIndexTemplate</span> <span class="variable">template</span> <span class="operator">=</span> <span class="comment">// .. 通过构建得出</span></span><br><span class="line"></span><br><span class="line">        <span class="type">SearchRequestBuilder</span> <span class="variable">requestBuilder</span> <span class="operator">=</span> <span class="built_in">this</span>.esClient.prepareSearch(INDEX_NAME)</span><br><span class="line">                .setTypes(INDEX_TYPE)</span><br><span class="line">                .setQuery(QueryBuilders.termQuery(<span class="string">&quot;example_id&quot;</span>, id));</span><br><span class="line"></span><br><span class="line">        logger.debug(requestBuilder.toString());</span><br><span class="line">        <span class="type">SearchResponse</span> <span class="variable">searchResponse</span> <span class="operator">=</span> requestBuilder.get();</span><br><span class="line"></span><br><span class="line">        <span class="type">boolean</span> success;</span><br><span class="line">        <span class="type">long</span> <span class="variable">totalHit</span> <span class="operator">=</span> searchResponse.getHits().getTotalHits();</span><br><span class="line">        <span class="keyword">if</span> (totalHit == <span class="number">0</span>) &#123;</span><br><span class="line">            success = create(template);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (totalHit == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">esId</span> <span class="operator">=</span> searchResponse.getHits().getAt(<span class="number">0</span>).getId();</span><br><span class="line">            success = update(id, template);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            success = deleteAndCreate(totalHit, template);</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// --</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">create</span><span class="params">(ExampleIndexTemplate indexTemplate)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">IndexResponse</span> <span class="variable">response</span> <span class="operator">=</span> <span class="built_in">this</span>.esClient.prepareIndex(INDEX_NAME, INDEX_TYPE)</span><br><span class="line">                    .setSource(objectMapper.writeValueAsBytes(indexTemplate), XContentType.JSON).get();</span><br><span class="line">            <span class="keyword">if</span> (response.status() == RestStatus.CREATED) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (JsonProcessingException e) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">update</span><span class="params">(Long id, ExampleIndexTemplate indexTemplate)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">UpdateResponse</span> <span class="variable">response</span> <span class="operator">=</span> <span class="built_in">this</span>.esClient.prepareUpdate(INDEX_NAME, INDEX_TYPE, id).setDoc(objectMapper.writeValueAsBytes(indexTemplate), XContentType.JSON).get();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (response.status() == RestStatus.OK) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (JsonProcessingException e) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">deleteAndCreate</span><span class="params">(<span class="type">long</span> totalHit, ExampleIndexTemplate indexTemplate)</span> &#123;</span><br><span class="line">        <span class="type">DeleteByQueryRequestBuilder</span> <span class="variable">builder</span> <span class="operator">=</span> DeleteByQueryAction.INSTANCE</span><br><span class="line">                .newRequestBuilder(esClient)</span><br><span class="line">                .filter(QueryBuilders.termQuery(<span class="string">&quot;example_id&quot;</span>, indexTemplate.getId()))</span><br><span class="line">                .source(INDEX_NAME);</span><br><span class="line"></span><br><span class="line">        <span class="type">BulkByScrollResponse</span> <span class="variable">response</span> <span class="operator">=</span> builder.get();</span><br><span class="line">        <span class="type">long</span> <span class="variable">deleted</span> <span class="operator">=</span> response.getDeleted();</span><br><span class="line">        <span class="keyword">if</span> (deleted != totalHit) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> create(indexTemplate);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></li><li>移除索引模版<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(Long id)</span> &#123;</span><br><span class="line">    <span class="type">DeleteByQueryRequestBuilder</span> <span class="variable">builder</span> <span class="operator">=</span> DeleteByQueryAction.INSTANCE</span><br><span class="line">            .newRequestBuilder(esClient)</span><br><span class="line">            .filter(QueryBuilders.termQuery(<span class="string">&quot;example_id&quot;</span>, id))</span><br><span class="line">            .source(INDEX_NAME);</span><br><span class="line">    <span class="type">BulkByScrollResponse</span> <span class="variable">response</span> <span class="operator">=</span> builder.get();</span><br><span class="line">    <span class="type">long</span> <span class="variable">deleted</span> <span class="operator">=</span> response.getDeleted();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>简单搜索<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 通过搜索查询出id， 然后于 mysql 之类数据库进行聚合</span></span><br><span class="line">List&lt;Serializable&gt; <span class="title function_">search</span><span class="params">(SearchBody body)</span>&#123;</span><br><span class="line">        <span class="type">BoolQueryBuilder</span> <span class="variable">boolQuery</span> <span class="operator">=</span> QueryBuilders.boolQuery();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 满足filter子句的条件。但是不会像Must一样，参与计算分值</span></span><br><span class="line">        boolQuery.filter(</span><br><span class="line">            <span class="comment">// QueryBuilders.termQuery</span></span><br><span class="line">            <span class="comment">// QueryBuilders.rangeQuery</span></span><br><span class="line">            <span class="comment">//..</span></span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line"><span class="comment">//        提高权重, 如果需要的话</span></span><br><span class="line"><span class="comment">//        boolQuery.must(</span></span><br><span class="line"><span class="comment">//                QueryBuilders.matchQuery(&quot;title&quot;, body.getKeywords())</span></span><br><span class="line"><span class="comment">//                        .boost(2.0f)</span></span><br><span class="line"><span class="comment">//        );</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// [必须满足的意思] 满足must子句的条件，并且参与计算分值</span></span><br><span class="line">        boolQuery.must(</span><br><span class="line">            <span class="comment">// QueryBuilders.multiMatchQuery  关键词匹配多个字段</span></span><br><span class="line">            <span class="comment">//..</span></span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 满足should子句的条件。在一个Bool查询中，如果没有must或者filter，有一个或者多个should子句，那么只要满足一个就可以返回</span></span><br><span class="line">        boolQuery.should(</span><br><span class="line">            <span class="comment">//..</span></span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 不满足must_not定义的条件</span></span><br><span class="line">        boolQuery.should(</span><br><span class="line">            <span class="comment">//..</span></span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="type">SearchRequestBuilder</span> <span class="variable">requestBuilder</span> <span class="operator">=</span> <span class="built_in">this</span>.esClient.prepareSearch(INDEX_NAME)</span><br><span class="line">                .setTypes(INDEX_TYPE)</span><br><span class="line">                <span class="comment">// 查询条件</span></span><br><span class="line">                .setQuery(boolQuery)</span><br><span class="line">                <span class="comment">// 排序</span></span><br><span class="line">                .addSort(</span><br><span class="line">                        <span class="string">&quot;createdAt&quot;</span>, <span class="string">&quot;DESC&quot;</span></span><br><span class="line">                )</span><br><span class="line">                <span class="comment">// 开始位置</span></span><br><span class="line">                .setFrom(<span class="number">0</span>)</span><br><span class="line">                .setSize(<span class="number">100</span>)</span><br><span class="line">                <span class="comment">// 设置该字段可以有效减少返回数据量</span></span><br><span class="line">                .setFetchSource(<span class="string">&quot;id&quot;</span>, <span class="literal">null</span>);</span><br><span class="line">        <span class="type">SearchResponse</span> <span class="variable">response</span> <span class="operator">=</span> requestBuilder.get();</span><br><span class="line"></span><br><span class="line">        List&lt;Long&gt; ids = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        <span class="keyword">for</span> (SearchHit hit : response.getHits()) &#123;</span><br><span class="line">            System.out.println(hit.getSource());</span><br><span class="line">            ids.add(Longs.tryParse(String.valueOf(hit.getSource().get(<span class="string">&quot;example_id&quot;</span>))));</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> ids;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>自动补全<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><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 class="comment">// 匹配</span></span><br><span class="line">Collection&lt;String&gt; <span class="title function_">suggest</span><span class="params">(String prefix)</span>&#123;</span><br><span class="line">    <span class="type">CompletionSuggestionBuilder</span> <span class="variable">suggestion</span> <span class="operator">=</span> SuggestBuilders.completionSuggestion(<span class="string">&quot;suggest&quot;</span>).prefix(prefix).size(<span class="number">5</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">SuggestBuilder</span> <span class="variable">suggestBuilder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SuggestBuilder</span>();</span><br><span class="line">        suggestBuilder.addSuggestion(<span class="string">&quot;autocomplete&quot;</span>, suggestion);</span><br><span class="line"></span><br><span class="line">        <span class="type">SearchRequestBuilder</span> <span class="variable">requestBuilder</span> <span class="operator">=</span> <span class="built_in">this</span>.esClient.prepareSearch(INDEX_NAME)</span><br><span class="line">                .setTypes(INDEX_TYPE)</span><br><span class="line">                .suggest(suggestBuilder);</span><br><span class="line"></span><br><span class="line">        <span class="type">SearchResponse</span> <span class="variable">response</span> <span class="operator">=</span> requestBuilder.get();</span><br><span class="line">        <span class="type">Suggest</span> <span class="variable">suggest</span> <span class="operator">=</span> response.getSuggest();</span><br><span class="line">        <span class="keyword">if</span> (suggest == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> ServiceResult.of(<span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;());</span><br><span class="line">        &#125;</span><br><span class="line">        Suggest.<span class="type">Suggestion</span> <span class="variable">result</span> <span class="operator">=</span> suggest.getSuggestion(<span class="string">&quot;autocomplete&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">int</span> <span class="variable">maxSuggest</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        Set&lt;String&gt; suggestSet = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (Object term : result.getEntries()) &#123;</span><br><span class="line">            <span class="keyword">if</span> (term <span class="keyword">instanceof</span> CompletionSuggestion.Entry) &#123;</span><br><span class="line">                CompletionSuggestion.<span class="type">Entry</span> <span class="variable">item</span> <span class="operator">=</span> (CompletionSuggestion.Entry) term;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> (item.getOptions().isEmpty()) &#123;</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">for</span> (CompletionSuggestion.Entry.Option option : item.getOptions()) &#123;</span><br><span class="line">                    <span class="type">String</span> <span class="variable">tip</span> <span class="operator">=</span> option.getText().string();</span><br><span class="line">                    <span class="keyword">if</span> (suggestSet.contains(tip)) &#123;</span><br><span class="line">                        <span class="keyword">continue</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                    suggestSet.add(tip);</span><br><span class="line">                    maxSuggest++;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (maxSuggest &gt; <span class="number">5</span>) &#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> suggestSet;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 设置权重</span></span><br><span class="line"><span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">updateSuggest</span><span class="params">(ExampleIndexTemplate indexTemplate)</span> &#123;</span><br><span class="line">    <span class="type">AnalyzeRequestBuilder</span> <span class="variable">requestBuilder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AnalyzeRequestBuilder</span>(</span><br><span class="line">            <span class="built_in">this</span>.esClient, AnalyzeAction.INSTANCE, INDEX_NAME, </span><br><span class="line">            <span class="comment">// 会被搜索的字段的值..</span></span><br><span class="line">            );</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用的分词器</span></span><br><span class="line">    requestBuilder.setAnalyzer(<span class="string">&quot;ik_smart&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="type">AnalyzeResponse</span> <span class="variable">response</span> <span class="operator">=</span> requestBuilder.get();</span><br><span class="line">    List&lt;AnalyzeResponse.AnalyzeToken&gt; tokens = response.getTokens();</span><br><span class="line">    <span class="keyword">if</span> (tokens == <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    List&lt;HouseSuggest&gt; suggests = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span> (AnalyzeResponse.AnalyzeToken token : tokens) &#123;</span><br><span class="line">        <span class="comment">// 生效限制</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="string">&quot;&lt;NUM&gt;&quot;</span>.equals(token.getType()) || token.getTerm().length() &lt; <span class="number">2</span>) &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="type">ExampleSuggest</span> <span class="variable">suggest</span> <span class="operator">=</span> <span class="comment">// ..</span></span><br><span class="line">        suggests.add(suggest);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 其他影响因素</span></span><br><span class="line">    <span class="type">ExampleSuggest</span> <span class="variable">suggest</span> <span class="operator">=</span> <span class="comment">// ..</span></span><br><span class="line">    suggests.add(suggest);</span><br><span class="line"></span><br><span class="line">    indexTemplate.setSuggest(suggests);</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li>聚合统计<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">long</span> <span class="title function_">aggregateNumber</span><span class="params">(String c1, String c2, String c3)</span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="type">BoolQueryBuilder</span> <span class="variable">boolQuery</span> <span class="operator">=</span> QueryBuilders.boolQuery()</span><br><span class="line">                .filter(QueryBuilders.termQuery(</span><br><span class="line">                    <span class="comment">// 聚合条件</span></span><br><span class="line">                ))</span><br><span class="line">                .filter(QueryBuilders.termQuery(</span><br><span class="line">                    <span class="comment">// 聚合条件</span></span><br><span class="line">                ))</span><br><span class="line">                .filter(QueryBuilders.termQuery(</span><br><span class="line">                    <span class="string">&quot;field_name&quot;</span>,</span><br><span class="line">                    c1</span><br><span class="line">                ));</span><br><span class="line"></span><br><span class="line">        <span class="type">SearchRequestBuilder</span> <span class="variable">requestBuilder</span> <span class="operator">=</span> <span class="built_in">this</span>.esClient.prepareSearch(INDEX_NAME)</span><br><span class="line">                .setTypes(INDEX_TYPE)</span><br><span class="line">                .setQuery(boolQuery)</span><br><span class="line">                .addAggregation(</span><br><span class="line">                        AggregationBuilders.terms(<span class="string">&quot;agg_number&quot;</span>)</span><br><span class="line">                        .field(<span class="string">&quot;field_name&quot;</span>)</span><br><span class="line">                ).setSize(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">        logger.debug(requestBuilder.toString());</span><br><span class="line"></span><br><span class="line">        <span class="type">SearchResponse</span> <span class="variable">response</span> <span class="operator">=</span> requestBuilder.get();</span><br><span class="line">        <span class="keyword">if</span> (response.status() == RestStatus.OK) &#123;</span><br><span class="line">            <span class="type">Terms</span> <span class="variable">terms</span> <span class="operator">=</span> response.getAggregations().get(<span class="string">&quot;agg_number&quot;</span>);</span><br><span class="line">            <span class="keyword">if</span> (terms.getBuckets() != <span class="literal">null</span> &amp;&amp; !terms.getBuckets().isEmpty()) &#123;</span><br><span class="line">                <span class="keyword">return</span> terms.getBucketByKey(c1).getDocCount();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0L</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0L</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li>位置范围查询<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> Collection&lt;Long&gt; <span class="title function_">mapQuery</span><span class="params">(SearchBody body)</span> &#123;</span><br><span class="line">    <span class="type">BoolQueryBuilder</span> <span class="variable">boolQuery</span> <span class="operator">=</span> QueryBuilders.boolQuery();</span><br><span class="line">    boolQuery.filter(QueryBuilders.termQuery(</span><br><span class="line">        <span class="comment">// ..</span></span><br><span class="line">    ));</span><br><span class="line"></span><br><span class="line">    boolQuery.filter(</span><br><span class="line">        QueryBuilders.geoBoundingBoxQuery(<span class="string">&quot;location&quot;</span>)</span><br><span class="line">            .setCorners(</span><br><span class="line">                    <span class="comment">// 左上角</span></span><br><span class="line">                    <span class="keyword">new</span> <span class="title class_">GeoPoint</span>(body.getLeftLatitude(), body.getLeftLongitude()),</span><br><span class="line">                    <span class="comment">// 右下角</span></span><br><span class="line">                    <span class="keyword">new</span> <span class="title class_">GeoPoint</span>(body.getRightLatitude(), body.getRightLongitude())</span><br><span class="line">            ));</span><br><span class="line"></span><br><span class="line">    <span class="type">SearchRequestBuilder</span> <span class="variable">builder</span> <span class="operator">=</span> <span class="built_in">this</span>.esClient.prepareSearch(INDEX_NAME)</span><br><span class="line">            .setTypes(INDEX_TYPE)</span><br><span class="line">            .setQuery(boolQuery)</span><br><span class="line">            .addSort(</span><br><span class="line">                <span class="comment">// ..</span></span><br><span class="line">            )</span><br><span class="line">            .setFrom(<span class="number">0</span>)</span><br><span class="line">            .setSize(<span class="number">100</span>);</span><br><span class="line"></span><br><span class="line">    List&lt;Long&gt; ids = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    <span class="type">SearchResponse</span> <span class="variable">response</span> <span class="operator">=</span> builder.get();</span><br><span class="line">    <span class="keyword">if</span> (RestStatus.OK != response.status()) &#123;</span><br><span class="line">        <span class="keyword">return</span> ids;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (SearchHit hit : response.getHits()) &#123;</span><br><span class="line">        ids.add(hit.getSource().get(<span class="string">&quot;example_id&quot;</span>));</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ids;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="JSON格式查询语法"><a href="#JSON格式查询语法" class="headerlink" title="JSON格式查询语法"></a>JSON格式查询语法</h2><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html">官方文档</a></p><h3 id="概要"><a href="#概要" class="headerlink" title="概要"></a>概要</h3><blockquote><ul><li>must<code>参与计算分值</code> -&gt; and</li><li>filter<code>不参与计算分值</code> -&gt; and</li><li>should -&gt; or</li><li>must_not -&gt; not</li></ul></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 布尔查询</span></span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> </span><br><span class="line">    <span class="attr">&quot;bool&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> </span><br><span class="line">      <span class="comment">// The clause (query) must appear in matching documents and will contribute to the score.</span></span><br><span class="line">      <span class="comment">// 所有&quot;must&quot;条件必须匹配成功, 且计算分数</span></span><br><span class="line">      <span class="attr">&quot;must&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;match&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;title&quot;</span><span class="punctuation">:</span>   <span class="string">&quot;Search&quot;</span>        <span class="punctuation">&#125;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span> </span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;match&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;content&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Elasticsearch&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">&#125;</span>  </span><br><span class="line">      <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="comment">// The clause (query) must appear in matching documents. However unlike must the score of the query will be ignored. Filter clauses are executed in filter context, meaning that scoring is ignored and clauses are considered for caching.</span></span><br><span class="line">      <span class="comment">// 所有&quot;filter&quot;条件必须匹配成功, 不计算分数(因此查询速度较快)</span></span><br><span class="line">      <span class="attr">&quot;filter&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span> </span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;term&quot;</span><span class="punctuation">:</span>  <span class="punctuation">&#123;</span> <span class="attr">&quot;status&quot;</span><span class="punctuation">:</span> <span class="string">&quot;published&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span> </span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;range&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;publish_date&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;gte&quot;</span><span class="punctuation">:</span> <span class="string">&quot;2015-01-01&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">&#125;</span><span class="punctuation">&#125;</span> </span><br><span class="line">      <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="comment">// The clause (query) should appear in the matching document. If the bool query is in a query context and has a must or filter clause then a document will match the bool query even if none of the should queries match. In this case these clauses are only used to influence the score. If the bool query is a filter context or has neither must or filter then at least one of the should queries must match a document for it to match the bool query. This behavior may be explicitly controlled by settings the minimum_should_match parameter.</span></span><br><span class="line">      <span class="comment">// 情况一(嵌套bool): 当&quot;should&quot;条件在&quot;must&quot;条件或者&quot;filter&quot;条件内, 此时不要求满足&quot;should&quot;条件, 但是会影响到查询分数</span></span><br><span class="line">      <span class="comment">// 情况二(单条bool): 当&quot;should&quot;条件不在&quot;must&quot;条件或者&quot;filter&quot;条件内, 默认情况至少有一个&quot;should&quot;子句需要满足(可通过配置`minimum_should_match`参数进行变更)</span></span><br><span class="line">      <span class="attr">&quot;should&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;range&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="attr">&quot;age&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;gte&quot;</span> <span class="punctuation">:</span> <span class="number">10</span><span class="punctuation">,</span> <span class="attr">&quot;lte&quot;</span> <span class="punctuation">:</span> <span class="number">20</span> <span class="punctuation">&#125;</span><span class="punctuation">&#125;</span><span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;minimum_should_match&quot;</span><span class="punctuation">:</span> <span class="number">1</span><span class="punctuation">,</span></span><br><span class="line">      <span class="comment">// The clause (query) must not appear in the matching documents. Clauses are executed in filter context meaning that scoring is ignored and clauses are considered for caching. Because scoring is ignored, a score of 0 for all documents is returned.</span></span><br><span class="line">      <span class="comment">// 所有&quot;must_not&quot;条件不能匹配成功</span></span><br><span class="line">      <span class="attr">&quot;must_not&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;term&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;tag&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;wow&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;term&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;tag&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;elasticsearch&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="全文搜索"><a href="#全文搜索" class="headerlink" title="全文搜索"></a>全文搜索</h3><blockquote><p>会走分析器</p></blockquote><ul><li><p>match</p><blockquote><p>描述: 匹配查询, 只需包含部分。eg: hello world, 只匹配”hello”或者”world”<br>可接受类型: text&#x2F;numerics&#x2F;dates</p></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="comment">// 简单查询</span></span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;match&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;message&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;this is a test&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br><span class="line"><span class="comment">// 复杂查询</span></span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;match&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;message&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="string">&quot;this is a test&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;参数&quot;</span><span class="punctuation">:</span> <span class="string">&quot;值&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li><li><p>match_phrase</p><blockquote><p>描述: 匹配词组查询, 多个词一起被查询. eg: hello world, 匹配”hello world”</p></blockquote></li><li><p>match_phrase_prefix</p><blockquote><p>描述: 同<code>match_phrase</code>但是最后一个词会被当作前缀去匹配. eg: hello wo, 可匹配到”hello world”</p></blockquote></li><li><p>multi_match</p><blockquote><p>描述: 同<code>match</code>但是可以作用在多个字段上，且字段支持表达式</p></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;multi_match&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span>    <span class="string">&quot;this is a test&quot;</span><span class="punctuation">,</span> </span><br><span class="line">      <span class="attr">&quot;fields&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span> <span class="string">&quot;subject&quot;</span><span class="punctuation">,</span> <span class="string">&quot;*_name&quot;</span> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;参数&quot;</span><span class="punctuation">:</span> <span class="string">&quot;值&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li><li><p>common</p><blockquote><p>描述: 根据词频进行匹配.</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;common&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;body&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="string">&quot;this is bonsai cool&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="comment">// 词频率: [0, 1]</span></span><br><span class="line">                <span class="attr">&quot;cutoff_frequency&quot;</span><span class="punctuation">:</span> <span class="number">0.001</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li>query_string<blockquote><p>描述: 根据表达式进行匹配, 输入的值为表达式, 支持一些内置参数和语法。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;query_string&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="string">&quot;(content:this OR name:this) AND (content:that OR name:that)&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li>simple_query_string<blockquote><p>描述: 与<code>query_string</code>类似, 支持一些更简便的符号。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;simple_query_string&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="string">&quot;\&quot;fried eggs\&quot; +(eggplant | potato) -frittata&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;fields&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;title^5&quot;</span><span class="punctuation">,</span> <span class="string">&quot;body&quot;</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;default_operator&quot;</span><span class="punctuation">:</span> <span class="string">&quot;and&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="条件查询"><a href="#条件查询" class="headerlink" title="条件查询"></a>条件查询</h3><blockquote><p>精准搜索<br>一般用于结构化数据而非全文匹配: numbers, dates, and enums</p></blockquote><ul><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html">term</a></p><blockquote><p>描述: 匹配单个值, 类似”&#x3D;”, 但是其具备<code>Elasticsearch</code>的特性如: 分数</p></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 简单</span></span><br><span class="line">POST _search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;Kimchy&quot;</span> <span class="punctuation">&#125;</span> </span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br><span class="line"><span class="comment">// 复杂，设定匹配分数之类的</span></span><br><span class="line">GET _search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;bool&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;should&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;term&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;status&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">              <span class="attr">&quot;value&quot;</span><span class="punctuation">:</span> <span class="string">&quot;urgent&quot;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;boost&quot;</span><span class="punctuation">:</span> <span class="number">2.0</span> </span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;term&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;status&quot;</span><span class="punctuation">:</span> <span class="string">&quot;normal&quot;</span> </span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html">terms</a></p><blockquote><p>描述: 匹配多个值, 类似”in”</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 简单</span></span><br><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;terms&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;kimchy&quot;</span><span class="punctuation">,</span> <span class="string">&quot;elasticsearch&quot;</span><span class="punctuation">]</span><span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-set-query.html">terms_set</a><blockquote><p>描述: 定制化匹配规则</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">GET /my-index/_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;terms_set&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;codes&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;terms&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;abc&quot;</span><span class="punctuation">,</span> <span class="string">&quot;def&quot;</span><span class="punctuation">,</span> <span class="string">&quot;ghi&quot;</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;minimum_should_match_field&quot;</span><span class="punctuation">:</span> <span class="string">&quot;required_matches&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html">range</a><blockquote><p>描述: 范围匹配, 支持: string，date，numeric</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">GET _search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;range&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;age&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;gte&quot;</span> <span class="punctuation">:</span> <span class="number">10</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;lte&quot;</span> <span class="punctuation">:</span> <span class="number">20</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;boost&quot;</span> <span class="punctuation">:</span> <span class="number">2.0</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-query.html">exists</a><blockquote><p>描述: 存在查询, 必须至少存在一个非<code>null</code>值. eg: user: [null, ‘hocgin’]</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;exists&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;user&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html">prefix</a><blockquote><p>描述: 前缀匹配.</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span> <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;prefix&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;ki&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wildcard-query.html">wildcard</a></p><blockquote><p>描述: 通配符匹配。类似<code>like</code></p></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;wildcard&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;ki*y&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html">regexp</a></p><blockquote><p>描述: 正则匹配，允许使用正则表达式。<br>⚠️: 性能取决于正则表达式写法，建议用<code>饥饿模式</code></p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;regexp&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;name.first&quot;</span><span class="punctuation">:</span> <span class="string">&quot;s.*y?&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html">fuzzy</a><blockquote><p>描述: 模糊查询. 适用于拼写错误时搜索。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">       <span class="attr">&quot;fuzzy&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;ki&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-type-query.html">type</a><blockquote><p>描述: 文档类型查询</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;type&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;value&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;_doc&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-ids-query.html">ids</a><blockquote><p>描述: 根据<code>id</code>字段过滤文档数据</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;ids&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;type&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;_doc&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;values&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;1&quot;</span><span class="punctuation">,</span> <span class="string">&quot;4&quot;</span><span class="punctuation">,</span> <span class="string">&quot;100&quot;</span><span class="punctuation">]</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="复合查询"><a href="#复合查询" class="headerlink" title="复合查询"></a>复合查询</h3><ul><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-constant-score-query.html#query-dsl-constant-score-query">constant_score</a></p><blockquote><p>描述: 忽略评分查询, 查询速度更快(使用缓存)。</p></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;constant_score&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;filter&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;kimchy&quot;</span><span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;boost&quot;</span> <span class="punctuation">:</span> <span class="number">1.2</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html">Bool 查询</a></p><blockquote><p>描述: 使用其他查询的bool值组合的查询。详细参考<code>概要</code></p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">POST _search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;bool&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;must&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;kimchy&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;filter&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;tag&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;tech&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;must_not&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;range&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;age&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;gte&quot;</span> <span class="punctuation">:</span> <span class="number">10</span><span class="punctuation">,</span> <span class="attr">&quot;lte&quot;</span> <span class="punctuation">:</span> <span class="number">20</span> <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;should&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;tag&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;wow&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;tag&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;elasticsearch&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;minimum_should_match&quot;</span> <span class="punctuation">:</span> <span class="number">1</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;boost&quot;</span> <span class="punctuation">:</span> <span class="number">1.0</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-dis-max-query.html">Dis Max Query</a><blockquote><p>描述: 取多个条件查询结果中，得分最高的查询结果。可以通过: <code>tie_breaker</code> 来关联其他查询结果的分数。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;dis_max&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="comment">// 此处相当于除最佳匹配外，其他匹配结果的参与程度.   --- 言外之意, 多方面考虑</span></span><br><span class="line">            <span class="attr">&quot;tie_breaker&quot;</span> <span class="punctuation">:</span> <span class="number">0.7</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;boost&quot;</span> <span class="punctuation">:</span> <span class="number">1.2</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;queries&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;age&quot;</span> <span class="punctuation">:</span> <span class="number">34</span> <span class="punctuation">&#125;</span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;age&quot;</span> <span class="punctuation">:</span> <span class="number">35</span> <span class="punctuation">&#125;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">]</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html">Function Score Query</a></p><blockquote><p>描述: 打分器. 最后打分阶段，引入一些最佳值的计算方式.         — 言外之意，作弊器</p></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;function_score&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;match_all&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;boost&quot;</span><span class="punctuation">:</span> <span class="string">&quot;5&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;random_score&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span> </span><br><span class="line">            <span class="attr">&quot;boost_mode&quot;</span><span class="punctuation">:</span><span class="string">&quot;multiply&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-boosting-query.html">Boosting Query</a></p><blockquote><p>描述: 设置条件的权重.</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;boosting&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;positive&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;value1&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;negative&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                 <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                     <span class="attr">&quot;field2&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;value2&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;negative_boost&quot;</span> <span class="punctuation">:</span> <span class="number">0.2</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="连接查询"><a href="#连接查询" class="headerlink" title="连接查询"></a>连接查询</h3><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html#query-dsl-nested-query">Nested Query</a><blockquote><p>描述</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;nested&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="comment">// 嵌套对象路径</span></span><br><span class="line">            <span class="attr">&quot;path&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;obj1&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="comment">// 影响的计分方式</span></span><br><span class="line">            <span class="attr">&quot;score_mode&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;avg&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;query&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;bool&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;must&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                        <span class="comment">// ⚠️: 字段必须是完整路径</span></span><br><span class="line">                    <span class="punctuation">&#123;</span> <span class="attr">&quot;match&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="attr">&quot;obj1.name&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;blue&quot;</span><span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="punctuation">&#123;</span> <span class="attr">&quot;range&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="attr">&quot;obj1.count&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="attr">&quot;gt&quot;</span> <span class="punctuation">:</span> <span class="number">5</span><span class="punctuation">&#125;</span><span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line">                    <span class="punctuation">]</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-has-child-query.html">Has Child Query</a><blockquote><p>描述: 进行子文档查询, 返回父文档. 慢查询，慎用</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;has_child&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;type&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;blog_tag&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;score_mode&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;min&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;query&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;tag&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;something&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-has-parent-query.html">Has Parent Query</a><blockquote><p>描述: 父文档查询，返回子文档.</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;has_parent&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;parent_type&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;blog&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;query&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;tag&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;something&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="">Parent Id Query</a><blockquote><p>描述: 父ID查询，返回子文档</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">GET /my_index/_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;parent_id&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;my_child&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><h3 id="地理位置查询"><a href="#地理位置查询" class="headerlink" title="地理位置查询"></a>地理位置查询</h3><blockquote><p>需要<code>geo_shape</code>类型</p></blockquote><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-query.html">GeoShape Query</a><blockquote><p>描述: GeoShape 查询，查询在多边形(基于GeoJSON)内的点。既: 用一个多边形去搜索。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">GET /example/_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;bool&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;must&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;match_all&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;filter&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;geo_shape&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;location&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                        <span class="attr">&quot;shape&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                            <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;envelope&quot;</span><span class="punctuation">,</span></span><br><span class="line">                            <span class="attr">&quot;coordinates&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">[</span><span class="number">13.0</span><span class="punctuation">,</span> <span class="number">53.0</span><span class="punctuation">]</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="number">14.0</span><span class="punctuation">,</span> <span class="number">52.0</span><span class="punctuation">]</span><span class="punctuation">]</span></span><br><span class="line">                        <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                        <span class="attr">&quot;relation&quot;</span><span class="punctuation">:</span> <span class="string">&quot;within&quot;</span></span><br><span class="line">                    <span class="punctuation">&#125;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-bounding-box-query.html#query-dsl-geo-bounding-box-query">Geo Bounding Box Query</a><blockquote><p>描述: 地理边界框查询，即用一个边界范围去搜索。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;bool&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;must&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;match_all&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;filter&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;geo_bounding_box&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;pin.location&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                        <span class="attr">&quot;top_left&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                            <span class="attr">&quot;lat&quot;</span> <span class="punctuation">:</span> <span class="number">40.73</span><span class="punctuation">,</span></span><br><span class="line">                            <span class="attr">&quot;lon&quot;</span> <span class="punctuation">:</span> <span class="number">-74.1</span></span><br><span class="line">                        <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                        <span class="attr">&quot;bottom_right&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                            <span class="attr">&quot;lat&quot;</span> <span class="punctuation">:</span> <span class="number">40.01</span><span class="punctuation">,</span></span><br><span class="line">                            <span class="attr">&quot;lon&quot;</span> <span class="punctuation">:</span> <span class="number">-71.12</span></span><br><span class="line">                        <span class="punctuation">&#125;</span></span><br><span class="line">                    <span class="punctuation">&#125;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-distance-query.html">Geo Distance Query</a><blockquote><p>描述: 地理距离查询</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">GET /my_locations/_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;bool&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;must&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;match_all&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;filter&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;geo_distance&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;distance&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;200km&quot;</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;pin.location&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                        <span class="attr">&quot;lat&quot;</span> <span class="punctuation">:</span> <span class="number">40</span><span class="punctuation">,</span></span><br><span class="line">                        <span class="attr">&quot;lon&quot;</span> <span class="punctuation">:</span> <span class="number">-70</span></span><br><span class="line">                    <span class="punctuation">&#125;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-polygon-query.html">Geo Polygon Query</a><blockquote><p>描述: 地理多边形查询, 返回围栏内的数据</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;bool&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;must&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;match_all&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;filter&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;geo_polygon&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;person.location&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                        <span class="attr">&quot;points&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                            <span class="punctuation">&#123;</span><span class="attr">&quot;lat&quot;</span> <span class="punctuation">:</span> <span class="number">40</span><span class="punctuation">,</span> <span class="attr">&quot;lon&quot;</span> <span class="punctuation">:</span> <span class="number">-70</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                            <span class="punctuation">&#123;</span><span class="attr">&quot;lat&quot;</span> <span class="punctuation">:</span> <span class="number">30</span><span class="punctuation">,</span> <span class="attr">&quot;lon&quot;</span> <span class="punctuation">:</span> <span class="number">-80</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                            <span class="punctuation">&#123;</span><span class="attr">&quot;lat&quot;</span> <span class="punctuation">:</span> <span class="number">20</span><span class="punctuation">,</span> <span class="attr">&quot;lon&quot;</span> <span class="punctuation">:</span> <span class="number">-90</span><span class="punctuation">&#125;</span></span><br><span class="line">                        <span class="punctuation">]</span></span><br><span class="line">                    <span class="punctuation">&#125;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><h3 id="定制化查询"><a href="#定制化查询" class="headerlink" title="定制化查询"></a>定制化查询</h3><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html">More Like This Query</a><blockquote><p>描述: 根据字段进行匹配文字的相识度，一般用于进行文章或内容的相识度推荐</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;more_like_this&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;fields&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;title&quot;</span><span class="punctuation">,</span> <span class="string">&quot;description&quot;</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;like&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;Once upon a time&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;min_term_freq&quot;</span> <span class="punctuation">:</span> <span class="number">1</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;max_query_terms&quot;</span> <span class="punctuation">:</span> <span class="number">12</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-script-query.html">Script Query</a><blockquote><p>描述: 脚本查询，使用特定的语法脚本进行查询。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;bool&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;filter&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;script&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;script&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                        <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;doc[&#x27;num1&#x27;].value &gt; 1&quot;</span><span class="punctuation">,</span></span><br><span class="line">                        <span class="attr">&quot;lang&quot;</span><span class="punctuation">:</span> <span class="string">&quot;painless&quot;</span></span><br><span class="line">                     <span class="punctuation">&#125;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-percolate-query.html">Percolate Query</a><blockquote><p>描述: Percolate查询，可用于匹配存储在索引中的查询,</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">GET /my-index/_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;percolate&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;field&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;query&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;document&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;message&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;A new bonsai tree in the office&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wrapper-query.html">Wrapper Query</a><blockquote><p>描述: 包装器查询, 将查询条件字符串 base64 编码</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;wrapper&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="comment">// &#123;&quot;term&quot; : &#123; &quot;user&quot; : &quot;Kimchy&quot; &#125;&#125;</span></span><br><span class="line">            <span class="attr">&quot;query&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;eyJ0ZXJtIiA6IHsgInVzZXIiIDogIktpbWNoeSIgfX0=&quot;</span> </span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><h3 id="跨度查询"><a href="#跨度查询" class="headerlink" title="跨度查询"></a>跨度查询</h3><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-term-query.html">Span Term Query</a><blockquote><p>描述: 等价于<code>term</code></p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;kimchy&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-multi-term-query.html">Span Multi Term Query</a><blockquote><p>描述: 多个跨度查询组合, 允许 (wildcard, fuzzy, prefix, range or regexp query) 之一</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;span_multi&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;match&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;prefix&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span>  <span class="punctuation">&#123;</span> <span class="attr">&quot;value&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;ki&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;boost&quot;</span> <span class="punctuation">:</span> <span class="number">1.08</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-first-query.html#query-dsl-span-first-query">Span First Query</a><blockquote><p>描述: 跨度优先查询，</p></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;span_first&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;match&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;user&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;kimchy&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;end&quot;</span> <span class="punctuation">:</span> <span class="number">3</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li></ul><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-near-query.html">Span Near Query</a><blockquote><p>描述: 接受多个跨度查询，其匹配必须在彼此的指定距离内，并且可能以相同的顺序。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;span_near&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;clauses&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;value1&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;value2&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;value3&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;slop&quot;</span> <span class="punctuation">:</span> <span class="number">12</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;in_order&quot;</span> <span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-or-query.html">Span Or Query</a><blockquote><p>描述: 组合多个跨度查询 - 返回与任何指定查询匹配的文档。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;span_or&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;clauses&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;value1&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;value2&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;value3&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">]</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-not-query.html">Span Not Query</a><blockquote><p>描述: 包装另一个span查询，并排除与该查询匹配的任何文档。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">GET /_search</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;span_not&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;include&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;hoya&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;exclude&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;span_near&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;clauses&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                        <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;la&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                        <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;hoya&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line">                    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;slop&quot;</span> <span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;in_order&quot;</span> <span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-containing-query.html">Span Containing Query</a><blockquote><p>描述: 接受跨度查询列表，但仅返回与第二个跨度查询匹配的跨度。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">curl -X GET <span class="string">&quot;localhost:9200/_search&quot;</span> -H &#x27;Content-Type<span class="punctuation">:</span> application/json&#x27; -d&#x27;</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;span_containing&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;little&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;foo&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;big&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;span_near&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;clauses&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                        <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;bar&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                        <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;baz&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line">                    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;slop&quot;</span> <span class="punctuation">:</span> <span class="number">5</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;in_order&quot;</span> <span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br><span class="line">&#x27;</span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-within-query.html">Span Within Query</a><blockquote><p>描述: 只要其跨度落在由其他跨度查询列表返回的跨度内，就会返回单跨度查询的结果。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">curl -X GET <span class="string">&quot;localhost:9200/_search&quot;</span> -H &#x27;Content-Type<span class="punctuation">:</span> application/json&#x27; -d&#x27;</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;span_within&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;little&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;foo&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;big&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;span_near&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;clauses&quot;</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                        <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;bar&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                        <span class="punctuation">&#123;</span> <span class="attr">&quot;span_term&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;field1&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;baz&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line">                    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;slop&quot;</span> <span class="punctuation">:</span> <span class="number">5</span><span class="punctuation">,</span></span><br><span class="line">                    <span class="attr">&quot;in_order&quot;</span> <span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br><span class="line">&#x27;</span><br></pre></td></tr></table></figure><hr><ul><li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-field-masking-query.html">Span Field Masking Query</a><blockquote><p>描述: 允许查询不同的字段span-near或span-or跨不同字段。</p></blockquote></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">curl -X GET <span class="string">&quot;localhost:9200/_search&quot;</span> -H &#x27;Content-Type<span class="punctuation">:</span> application/json&#x27; -d&#x27;</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;span_near&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;clauses&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;span_term&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;text&quot;</span><span class="punctuation">:</span> <span class="string">&quot;quick brown&quot;</span></span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;field_masking_span&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;query&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">              <span class="attr">&quot;span_term&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;text.stems&quot;</span><span class="punctuation">:</span> <span class="string">&quot;fox&quot;</span></span><br><span class="line">              <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;field&quot;</span><span class="punctuation">:</span> <span class="string">&quot;text&quot;</span></span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;slop&quot;</span><span class="punctuation">:</span> <span class="number">5</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;in_order&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br><span class="line">&#x27;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h2><blockquote><p>elasticsearch-plugin install {url}</p></blockquote><ul><li><a href="https://github.com/medcl/elasticsearch-analysis-ik">中文分词插件</a></li></ul><hr><h2 id="文档"><a href="#文档" class="headerlink" title="文档"></a>文档</h2><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">ElasticSearch 官方文档</a><br><a href="http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html">全文搜索引擎 Elasticsearch 入门教程</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Elasticsearch 随手记 😋&lt;/p&gt;</summary>
    
    
    
    <category term="服务端" scheme="https://hocg.in/categories/%E6%9C%8D%E5%8A%A1%E7%AB%AF/"/>
    
    
    <category term="Elasticsearch" scheme="https://hocg.in/tags/Elasticsearch/"/>
    
  </entry>
  
  <entry>
    <title>K8s 与 kubeadm 使用的一些记录</title>
    <link href="https://hocg.in/2019/03/08/k8s%E4%B8%8Ekubeadm%E4%BD%BF%E7%94%A8%E7%9A%84%E4%B8%80%E4%BA%9B%E8%AE%B0%E5%BD%95/"/>
    <id>https://hocg.in/2019/03/08/k8s%E4%B8%8Ekubeadm%E4%BD%BF%E7%94%A8%E7%9A%84%E4%B8%80%E4%BA%9B%E8%AE%B0%E5%BD%95/</id>
    <published>2019-03-08T09:13:00.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>这篇是了解 k8s 过程随手记录与之相关的一些概念</p><span id="more"></span><h2 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h2><h3 id="底层技术"><a href="#底层技术" class="headerlink" title="底层技术"></a>底层技术</h3><ul><li>限制, Cgoups <code>用来分配资源的, 如cpu,内存</code> </li><li>隔离, Namespace技术 <code>有点类似命名空间的概念, 隔离进程</code> 容器本质既特殊进程<ul><li>pid&#x3D;1</li></ul></li><li>文件系统, pivot_root&#x2F;chroot 构建文件系统</li><li>文件层, Union File System</li></ul><h2 id="k8s"><a href="#k8s" class="headerlink" title="k8s"></a>k8s</h2><blockquote><p>处理容器间的关系, 既编排</p></blockquote><ul><li>Master</li><li>Node</li></ul><h3 id="组件和职责"><a href="#组件和职责" class="headerlink" title="组件和职责"></a>组件和职责</h3><ul><li>Master 节点<ul><li>kube-apiserver 负责API服务</li><li>etcd 持久化数据</li><li>kubelet 核心<ul><li>与容器交互(CRI)</li><li>管理宿主机(Device Plugin)</li><li>网络配置(CNI)</li><li>持久化存储(CSI)</li></ul></li><li>kube-scheduler 负责调度</li><li>kube-controller-manager 负责容器编排</li></ul></li><li>Worker 节点</li></ul><h2 id="kubeadm"><a href="#kubeadm" class="headerlink" title="kubeadm"></a>kubeadm</h2><h3 id="准备源环境"><a href="#准备源环境" class="headerlink" title="准备源环境"></a>准备源环境</h3><blockquote><p>OS: Ubuntu 16.04 LTS</p></blockquote><ul><li>Master 节点</li></ul><ol><li><p>准备源环境</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><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">curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -</span><br><span class="line">cat &lt;&lt;EOF &gt; /etc/apt/sources.list.d/kubernetes.list</span><br><span class="line">deb http://apt.kubernetes.io/ kubernetes-xenial main</span><br><span class="line">EOF</span><br><span class="line">apt-get update</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">E: The method driver /usr/lib/apt/methods/https could not be found.</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">sudo apt-get install apt-transport-https</span></span><br><span class="line"></span><br><span class="line">apt-get install -y docker.io kubeadm</span><br></pre></td></tr></table></figure></li><li><p>准备<code>kubeadm.yml</code>脚本</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">kubeadm.k8s.io/v1alpha1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">MasterConfiguration</span></span><br><span class="line"><span class="attr">controllerManagerExtraArgs:</span></span><br><span class="line">  <span class="attr">horizontal-pod-autoscaler-use-rest-clients:</span> <span class="string">&quot;true&quot;</span></span><br><span class="line">  <span class="attr">horizontal-pod-autoscaler-sync-period:</span> <span class="string">&quot;10s&quot;</span></span><br><span class="line">  <span class="attr">node-monitor-grace-period:</span> <span class="string">&quot;10s&quot;</span></span><br><span class="line"><span class="attr">apiServerExtraArgs:</span></span><br><span class="line">  <span class="attr">runtime-config:</span> <span class="string">&quot;api/all=true&quot;</span></span><br><span class="line"><span class="attr">kubernetesVersion:</span> <span class="string">&quot;stable-1.11&quot;</span></span><br></pre></td></tr></table></figure></li><li><p>执行 kubeadm 初始化</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kubeadm init config kubeadm.yml</span><br></pre></td></tr></table></figure></li><li><p>执行结果</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">...</span></span><br><span class="line">Your Kubernetes master has initialized successfully!</span><br><span class="line"></span><br><span class="line">To start using your cluster, you need to run the following as a regular user:</span><br><span class="line"></span><br><span class="line">  mkdir -p $HOME/.kube</span><br><span class="line">  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config</span><br><span class="line">  sudo chown $(id -u):$(id -g) $HOME/.kube/config</span><br><span class="line"></span><br><span class="line">You should now deploy a pod network to the cluster.</span><br><span class="line">Run &quot;kubectl apply -f [podnetwork].yaml&quot; with one of the options listed at:</span><br><span class="line">  https://kubernetes.io/docs/concepts/cluster-administration/addons/</span><br><span class="line"></span><br><span class="line">You can now join any number of machines by running the following on each node</span><br><span class="line">as root:</span><br><span class="line"></span><br><span class="line">  kubeadm join 10.140.0.2:6443 --token 9tf8vg.633b2jjzzsglp9n6 --discovery-token-ca-cert-hash sha256:7bc87892cf9715e1393da6c9aace18e13bc6eeeec2ed8bbf8f01d3bccc5b0c20</span><br></pre></td></tr></table></figure></li><li><p>需要的集群配置</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p $HOME/.kube</span><br><span class="line">sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config</span><br><span class="line">sudo chown $(id -u):$(id -g) $HOME/.kube/config</span><br></pre></td></tr></table></figure></li><li><p>部署网络插件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kubectl apply -f https://git.io/weave-kube-1.6</span><br></pre></td></tr></table></figure></li></ol><ul><li>Cluster 节点</li></ul><ol><li><p>同 [Master 节点 1. 准备源环境]</p></li><li><p>将 Cluster 加入 Master 管理</p><blockquote><p>执行 [Master 节点 4. 执行结果 中的 <code>kubeadm join ...</code>]<br>:重点: 有一种情况, 当<code>kubeadm init</code>生成的<code>token</code>过期时, 可使用<code>kubeadm token create</code>重新生成</p></blockquote></li></ol><h3 id="基本指令"><a href="#基本指令" class="headerlink" title="基本指令"></a>基本指令</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看节点状态</span></span><br><span class="line">kubectl get nodes</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看节点对象的详情</span></span><br><span class="line">kubectl describe node k8s-3</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看该节点, kube-system 系统上 pods 状态</span></span><br><span class="line">kubectl get pods -n kube-system</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装插件, 例如: 安装网络插件</span></span><br><span class="line">kubectl apply -f https://git.io/weave-kube-1.6</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">移除所有 Taint, <span class="string">&quot;-&quot;</span> 匹配 <span class="string">&quot;:xx&quot;</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">注意: 单机 Master 需要使用</span></span><br><span class="line">kubectl taint nodes --all node-role.kubernetes.io/master-</span><br></pre></td></tr></table></figure><h3 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Dashboard, 仪表盘, 项目地址: https://github.com/kubernetes/dashboard</span></span><br><span class="line">kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Rook, 云存储, 项目地址: https://github.com/rook/rook</span></span><br><span class="line">kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/operator.yaml</span><br><span class="line"></span><br><span class="line">kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/cluster.yaml</span><br></pre></td></tr></table></figure><h3 id="高可用项目"><a href="#高可用项目" class="headerlink" title="高可用项目"></a>高可用项目</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">RocketMQ</span></span><br><span class="line">kubectl apply -f https://raw.githubusercontent.com/apache/rocketmq-externals/master/rocketmq-docker/4.4.0/kubernetes/deployment.yaml</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="编排文件"><a href="#编排文件" class="headerlink" title="编排文件"></a>编排文件</h2><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">extensions/v1beta1</span> <span class="comment"># 必选，版本号</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Deployment</span> <span class="comment"># 必选</span></span><br><span class="line"><span class="attr">metadata:</span> <span class="comment"># 元数据</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">rocketmq</span></span><br><span class="line"><span class="comment"># =========== 控制器部分 ===========</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line">  <span class="attr">replicas:</span> <span class="number">1</span> <span class="comment"># Pods 数量</span></span><br><span class="line"><span class="comment"># =========== Pods 部分 ===========</span></span><br><span class="line">  <span class="attr">template:</span></span><br><span class="line">    <span class="attr">metadata:</span></span><br><span class="line">     <span class="attr">labels:</span></span><br><span class="line">       <span class="attr">app:</span> <span class="string">rocketmq</span></span><br><span class="line">    <span class="attr">spec:</span></span><br><span class="line">      <span class="attr">containers:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">broker</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">rocketmqinc/rocketmq:4.4.0</span></span><br><span class="line">        <span class="attr">command:</span> [<span class="string">&quot;sh&quot;</span>,<span class="string">&quot;mqbroker&quot;</span>, <span class="string">&quot;-n&quot;</span>,<span class="string">&quot;localhost:9876&quot;</span>]</span><br><span class="line">        <span class="attr">imagePullPolicy:</span> <span class="string">IfNotPresent</span></span><br><span class="line">        <span class="attr">ports:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">10909</span> <span class="comment"># 容器端口</span></span><br><span class="line">        <span class="comment">#   - hostPort: 10909 # 主机端口</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">10911</span></span><br><span class="line">        <span class="attr">volumeMounts:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">mountPath:</span> <span class="string">/root/logs</span></span><br><span class="line">            <span class="attr">name:</span> <span class="string">brokeroptlogs</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">mountPath:</span> <span class="string">/root/store</span></span><br><span class="line">            <span class="attr">name:</span> <span class="string">brokeroptstore</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">namesrv</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">rocketmqinc/rocketmq:4.4.0</span></span><br><span class="line">        <span class="attr">command:</span> [<span class="string">&quot;sh&quot;</span>,<span class="string">&quot;mqnamesrv&quot;</span>]</span><br><span class="line">        <span class="attr">imagePullPolicy:</span> <span class="string">IfNotPresent</span></span><br><span class="line">        <span class="attr">ports:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">9876</span></span><br><span class="line">        <span class="attr">volumeMounts:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">mountPath:</span> <span class="string">/root/logs</span></span><br><span class="line">            <span class="attr">name:</span> <span class="string">namesrvoptlogs</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">mountPath:</span> <span class="string">/root/store</span></span><br><span class="line">            <span class="attr">name:</span> <span class="string">namesrvoptstore</span></span><br><span class="line">      <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">brokeroptlogs</span></span><br><span class="line">        <span class="attr">hostPath:</span></span><br><span class="line">          <span class="attr">path:</span> <span class="string">/data/broker/logs</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">brokeroptstore</span></span><br><span class="line">        <span class="attr">hostPath:</span></span><br><span class="line">          <span class="attr">path:</span> <span class="string">/data/broker/store</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">namesrvoptlogs</span></span><br><span class="line">        <span class="attr">hostPath:</span></span><br><span class="line">          <span class="attr">path:</span> <span class="string">/data/namesrv/logs</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">namesrvoptstore</span></span><br><span class="line">        <span class="attr">hostPath:</span></span><br><span class="line">          <span class="attr">path:</span> <span class="string">/data/namesrv/store</span></span><br></pre></td></tr></table></figure><h3 id="知识点-service·pods·node·cluster·container"><a href="#知识点-service·pods·node·cluster·container" class="headerlink" title="知识点: service·pods·node·cluster·container"></a>知识点: service·pods·node·cluster·container</h3><ul><li>Service: 一组 pods.</li></ul><h3 id="知识点-nodePort·port·targetPort·containerPort"><a href="#知识点-nodePort·port·targetPort·containerPort" class="headerlink" title="知识点: nodePort·port·targetPort·containerPort"></a>知识点: nodePort·port·targetPort·containerPort</h3><h4 id="service相关"><a href="#service相关" class="headerlink" title="service相关"></a>service相关</h4><ol><li>Service 的类型为 ClusterIP</li></ol><ul><li><p>port: 暴露在 Service(Cluster IP) 上的端口, 即集群中使用.</p><blockquote><p>service 暴露在 cluster ip 上的端口，<cluster ip>:port 是提供给集群内部客户访问 service 的入口</p></blockquote></li><li><p>targetPort: 指定 pod 上的端口, 会被映射到 port 上.</p><blockquote><p>targetPort 是 pod 上的端口，从 port 和 nodePort 上到来的数据最终经过 kube-proxy 流入到后端 pod 的 targetPort 上进入容器</p></blockquote></li></ul><ol start="2"><li>Service 的类型为 NodePort</li></ol><ul><li>nodePort: 用于集群外部访问<blockquote><p>Cluster IP 只能集群内部访问(源与目标需要满足两个条件: kube-proxy正常运行，跨主机容器网络通信正常)，NodePort 会在每个 kubelet 节点的宿主机开启一个端口，用于应用集群外部访问。</p></blockquote></li></ul><h4 id="容器相关类似docker-p"><a href="#容器相关类似docker-p" class="headerlink" title="容器相关类似docker -p"></a>容器相关<code>类似docker -p</code></h4><ul><li>containerPort: 容器需要暴露的端口</li><li>hostPort: 容器暴露的端口映射到的主机端口，默认与Container相同</li></ul><hr><h3 id="随笔"><a href="#随笔" class="headerlink" title="随笔"></a>随笔</h3><ul><li>紧密交互关系, Pod 共享一组 Network Namespace, 一组数据卷</li><li>Service 分配 Pod 固定的虚拟IP</li><li>Pod 洁癖机制, Taint&#x2F;Toleration</li><li>kubeadm 方案, 一键部署, 可通过配置实现生产环境使用(未到GA阶段)</li><li>minikuke 方案, 一键部署, 仅能用于本地实验</li><li>kops 方案, 可用于部署生产环境</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;这篇是了解 k8s 过程随手记录与之相关的一些概念&lt;/p&gt;</summary>
    
    
    
    <category term="K8s" scheme="https://hocg.in/categories/K8s/"/>
    
    
    <category term="K8s" scheme="https://hocg.in/tags/K8s/"/>
    
  </entry>
  
  <entry>
    <title>如何做单元测试</title>
    <link href="https://hocg.in/2019/02/02/%E5%A6%82%E4%BD%95%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/"/>
    <id>https://hocg.in/2019/02/02/%E5%A6%82%E4%BD%95%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/</id>
    <published>2019-02-02T13:17:21.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>如何在项目中做好单元测试，在此总结和记录</p><span id="more"></span><h1 id="单元测试"><a href="#单元测试" class="headerlink" title="单元测试"></a>单元测试</h1><p><a href="https://github.com/hocgin/SpringBootUnitTesting">栗子</a></p><h2 id="各层测试方式"><a href="#各层测试方式" class="headerlink" title="各层测试方式"></a>各层测试方式</h2><h3 id="Controller-层"><a href="#Controller-层" class="headerlink" title="Controller 层"></a>Controller 层</h3><ul><li>使用 Rest 模拟请求</li><li>Mock 相关 Service 接口</li></ul><h3 id="Service-层"><a href="#Service-层" class="headerlink" title="Service 层"></a>Service 层</h3><ul><li>使用 Mockit Mock 函数</li></ul><h3 id="Mapper-层"><a href="#Mapper-层" class="headerlink" title="Mapper 层"></a>Mapper 层</h3><ul><li>使用 @Sql 制造数据</li></ul><hr><h2 id="链接"><a href="#链接" class="headerlink" title="链接"></a>链接</h2><ul><li><a href="https://github.com/hocgin/SpringBootUnitTesting">参考示例</a></li><li><a href="https://blog.csdn.net/x5fnncxzq4/article/details/81437393">小谈 Java 单元测试 - 芋道源码 - CSDN博客</a></li><li><a href="https://github.com/ctripcorp/apollo">Apollo（阿波罗）</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;如何在项目中做好单元测试，在此总结和记录&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>关于项目结构划分</title>
    <link href="https://hocg.in/2019/01/12/%E5%85%B3%E4%BA%8E%E9%A1%B9%E7%9B%AE%E7%BB%93%E6%9E%84%E5%88%92%E5%88%86/"/>
    <id>https://hocg.in/2019/01/12/%E5%85%B3%E4%BA%8E%E9%A1%B9%E7%9B%AE%E7%BB%93%E6%9E%84%E5%88%92%E5%88%86/</id>
    <published>2019-01-12T12:24:23.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>关于项目结构划分的思考和总结</p><span id="more"></span><h2 id="项目分层"><a href="#项目分层" class="headerlink" title="项目分层"></a>项目分层</h2><p><img src="http://cdn.hocgin.top/image.png" alt="image.png"></p><ul><li><strong>Controller</strong></li></ul><ol><li>参数常规合法性校验</li><li>每个Controller函数对应一个Service函数</li></ol><ul><li><strong>Service</strong> 业务层，复用性低</li></ul><ol><li>参数业务合法性校验，使用 throw 处理异常</li></ol><ul><li><strong>Manager</strong> 可复用逻辑层</li></ul><ol><li>主要是Cache、MQ、复合Manager、RCP、HTTP等服务</li></ol><ul><li><strong>Mapper</strong> 数据库访问层</li></ul><ol><li>只允许自己的Service访问，其他Service访问仅能通过其Service</li></ol><hr><h2 id="领域模型"><a href="#领域模型" class="headerlink" title="领域模型"></a>领域模型</h2><p><strong>DO</strong> Data Object</p><blockquote><p>与数据库表结构对应，作为 Mapper 的返回值</p></blockquote><p><strong>DTO</strong> Data Transfer Object</p><blockquote><p>数据传输对象，作为 Service 或 Manager 的返回值</p></blockquote><p><strong>BO</strong> Business Object</p><blockquote><p>业务对象，作为 Service 的返回值，封装了业务逻辑的对象</p></blockquote><p><strong>AO</strong> Application Object</p><blockquote><p>应用对象，</p></blockquote><p><strong>VO</strong> View Object</p><blockquote><p>显示层对象，通常为 Web 层返回内容或模版渲染传输对象</p></blockquote><p><strong>Query</strong> </p><blockquote><p>数据查询对象，上层封装的查询对象</p></blockquote><h3 id="简化后的方案"><a href="#简化后的方案" class="headerlink" title="简化后的方案"></a>简化后的方案</h3><h2 id="Mapper-层返回的-DO-仅允许传入到-Service-或-Manager-Service-或-Manager-返回的-VO-仅允许传入到-Controller-或-TService"><a href="#Mapper-层返回的-DO-仅允许传入到-Service-或-Manager-Service-或-Manager-返回的-VO-仅允许传入到-Controller-或-TService" class="headerlink" title="* Mapper 层返回的 DO 仅允许传入到 Service 或 Manager* Service 或 Manager 返回的 VO 仅允许传入到 Controller 或 TService"></a><img src="http://cdn.hocgin.top/image.png" alt="image.png"><br>* Mapper 层返回的 DO 仅允许传入到 Service 或 Manager<br>* Service 或 Manager 返回的 VO 仅允许传入到 Controller 或 TService</h2><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">C -Query—&gt; S —DTO—&gt; M</span><br><span class="line">C &lt;—VO- S &lt;—DO- M</span><br></pre></td></tr></table></figure><hr><h2 id="链接"><a href="#链接" class="headerlink" title="链接"></a>链接</h2><p><a href="https://juejin.im/post/5b44e62e6fb9a04fc030f216">原文地址</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;关于项目结构划分的思考和总结&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>2018 图片墙</title>
    <link href="https://hocg.in/2018/12/31/2018%20%E5%9B%BE%E7%89%87%E5%A2%99/"/>
    <id>https://hocg.in/2018/12/31/2018%20%E5%9B%BE%E7%89%87%E5%A2%99/</id>
    <published>2018-12-31T23:59:59.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    
    
    
    <category term="生活" scheme="https://hocg.in/categories/%E7%94%9F%E6%B4%BB/"/>
    
    
    <category term="图片墙" scheme="https://hocg.in/tags/%E5%9B%BE%E7%89%87%E5%A2%99/"/>
    
  </entry>
  
  <entry>
    <title>React使用过程中的记录点</title>
    <link href="https://hocg.in/2018/11/20/React%E4%BD%BF%E7%94%A8%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%9A%84%E8%AE%B0%E5%BD%95%E7%82%B9/"/>
    <id>https://hocg.in/2018/11/20/React%E4%BD%BF%E7%94%A8%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%9A%84%E8%AE%B0%E5%BD%95%E7%82%B9/</id>
    <published>2018-11-20T19:15:36.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>  React 使用过程中的一些记录..</p><span id="more"></span><h2 id="定义清晰可维护的接口"><a href="#定义清晰可维护的接口" class="headerlink" title="定义清晰可维护的接口"></a>定义清晰可维护的接口</h2><ul><li>避免 <code>render</code>替代方式<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">SplitTimes</span> = (<span class="params">props</span>) =&gt; &#123;</span><br><span class="line">  <span class="comment">//<span class="doctag">TODO:</span> 返回JSX</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>回调类 props 属性使用前缀<code>on</code><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">onDone</span>=<span class="string">&#123;&#125;/</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li>尽量写 props-type</li></ul><hr><h2 id="组件的内部实现"><a href="#组件的内部实现" class="headerlink" title="组件的内部实现"></a>组件的内部实现</h2><ul><li>解构赋值<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">super</span>(...<span class="variable language_">arguments</span>); <span class="comment">//永远正确！</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>避免内联函数<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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;<span class="title class_">ControlButtons</span></span><br><span class="line">  activated=&#123;<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">isStarted</span>&#125;</span><br><span class="line">  onStart=&#123;<span class="function">() =&gt;</span> &#123; <span class="comment">/* TODO */</span>&#125;&#125;</span><br><span class="line">  onPause=&#123;<span class="function">() =&gt;</span> &#123; <span class="comment">/* TODO */</span>&#125;&#125;</span><br><span class="line">  onReset=&#123;<span class="function">() =&gt;</span> &#123; <span class="comment">/* TODO */</span>&#125;&#125;</span><br><span class="line">  onSplit=&#123;<span class="function">() =&gt;</span> &#123; <span class="comment">/* TODO */</span>&#125;&#125;</span><br><span class="line">/&gt;</span><br></pre></td></tr></table></figure></li><li>利用<strong>属性初始化</strong>（property initializer）来定义 state 和成员函数。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">state = &#123;</span><br><span class="line">    <span class="attr">isStarted</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">startTime</span>: <span class="literal">null</span>,</span><br><span class="line">    <span class="attr">currentTime</span>: <span class="literal">null</span>,</span><br><span class="line">    <span class="attr">splits</span>: [],</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">onReset = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;</span><br><span class="line">      <span class="attr">startTime</span>: <span class="literal">null</span>,</span><br><span class="line">      <span class="attr">currentTime</span>: <span class="literal">null</span>,</span><br><span class="line">      <span class="attr">splits</span>: [],</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="组件化样式"><a href="#组件化样式" class="headerlink" title="组件化样式"></a>组件化样式</h2><ul><li>避免内联 <code>style</code><figure class="highlight jsx"><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">&lt;h1 style=&#123;&#123;</span><br><span class="line">   <span class="string">&#x27;font-family&#x27;</span>: <span class="string">&#x27;monospace&#x27;</span></span><br><span class="line"> &#125;&#125;&gt;&#123;<span class="title function_">ms2Time</span>(milliseconds)&#125;&lt;/h1&gt;</span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="聪明组件和傻瓜组件"><a href="#聪明组件和傻瓜组件" class="headerlink" title="聪明组件和傻瓜组件"></a>聪明组件和傻瓜组件</h2><ul><li>不用 PureComponent 写一个傻瓜组件<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">Joke</span> = <span class="title class_">React</span>.<span class="title function_">memo</span>(<span class="function">() =&gt;</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&#123;SmileFace&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        &#123;this.props.value || &#x27;loading...&#x27; &#125;</span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">));</span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="render-props-模式"><a href="#render-props-模式" class="headerlink" title="render props 模式"></a>render props 模式</h2><ul><li>高阶组件<blockquote><p>可以是普通属性，也可以是<code>children</code></p></blockquote><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">Auth</span>= (<span class="params">props</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">const</span> userName = <span class="title function_">getUserName</span>();</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (userName) &#123;</span><br><span class="line">    <span class="keyword">const</span> allProps = &#123;userName, ...props&#125;;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">React.Fragment</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        &#123;props.login(allProps)&#125;</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">React.Fragment</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">React.Fragment</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      &#123;props.nologin(props)&#125;</span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">React.Fragment</span>&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">Auth</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">login</span>=<span class="string">&#123;(&#123;userName&#125;)</span> =&gt;</span> <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Hello &#123;userName&#125;<span class="tag">&lt;/<span class="name">h1</span>&gt;</span>&#125;</span></span><br><span class="line"><span class="language-xml">    nologin=&#123;() =&gt; <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Please login<span class="tag">&lt;/<span class="name">h1</span>&gt;</span>&#125;</span></span><br><span class="line"><span class="language-xml">  /&gt;</span></span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="提供者模式"><a href="#提供者模式" class="headerlink" title="提供者模式"></a>提供者模式</h2><ul><li>新版-提供者模式<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">ThemeContext</span> = <span class="title class_">React</span>.<span class="title function_">createContext</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">ThemeProvider</span> = <span class="title class_">ThemeContext</span>.<span class="property">Provider</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">ThemeConsumer</span> = <span class="title class_">ThemeContext</span>.<span class="property">Consumer</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Subject</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">ThemeConsumer</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        &#123;</span></span><br><span class="line"><span class="language-xml">          (theme) =&gt; (</span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h1</span> <span class="attr">style</span>=<span class="string">&#123;&#123;color:</span> <span class="attr">theme.mainColor</span>&#125;&#125;&gt;</span></span></span><br><span class="line"><span class="language-xml">              &#123;this.props.children&#125;</span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">          )</span></span><br><span class="line"><span class="language-xml">        &#125;</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">ThemeConsumer</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="组合组件"><a href="#组合组件" class="headerlink" title="组合组件"></a>组合组件</h2><blockquote><p>模式 &#x3D; 问题场景 + 解决办法</p></blockquote><ul><li>组合组件<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 案例</span></span><br><span class="line">    &lt;<span class="title class_">Tabs</span>&gt;</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">TabItem</span>&gt;</span>One<span class="tag">&lt;/<span class="name">TabItem</span>&gt;</span></span></span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">TabItem</span>&gt;</span>Two<span class="tag">&lt;/<span class="name">TabItem</span>&gt;</span></span></span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">TabItem</span>&gt;</span>Three<span class="tag">&lt;/<span class="name">TabItem</span>&gt;</span></span></span><br><span class="line">    &lt;/<span class="title class_">Tabs</span>&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// TabItem</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">TabItem</span> = (<span class="params">props</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">const</span> &#123;active, onClick&#125; = props;</span><br><span class="line">  <span class="keyword">const</span> tabStyle = &#123;</span><br><span class="line">    <span class="string">&#x27;max-width&#x27;</span>: <span class="string">&#x27;150px&#x27;</span>,</span><br><span class="line">    <span class="attr">color</span>: active ? <span class="string">&#x27;red&#x27;</span> : <span class="string">&#x27;green&#x27;</span>,</span><br><span class="line">    <span class="attr">border</span>: active ? <span class="string">&#x27;1px red solid&#x27;</span> : <span class="string">&#x27;0px&#x27;</span>,</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span> <span class="attr">style</span>=<span class="string">&#123;tabStyle&#125;</span> <span class="attr">onClick</span>=<span class="string">&#123;onClick&#125;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      &#123;props.children&#125;</span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">  );</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Tabs</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Tabs</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">  state = &#123;</span><br><span class="line">    <span class="attr">activeIndex</span>:  <span class="number">0</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> newChildren = <span class="title class_">React</span>.<span class="property">Children</span>.<span class="title function_">map</span>(<span class="variable language_">this</span>.<span class="property">props</span>.<span class="property">children</span>, <span class="function">(<span class="params">child, index</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="keyword">if</span> (child.<span class="property">type</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">React</span>.<span class="title function_">cloneElement</span>(child, &#123;</span><br><span class="line">          <span class="attr">active</span>: <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">activeIndex</span> === index,</span><br><span class="line">          <span class="attr">onClick</span>: <span class="function">() =&gt;</span> <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;<span class="attr">activeIndex</span>: index&#125;)</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> child;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">Fragment</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        &#123;newChildren&#125;</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">Fragment</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="React-单元测试"><a href="#React-单元测试" class="headerlink" title="React 单元测试"></a>React 单元测试</h2><ul><li>测试框架<ul><li>Jest</li></ul></li></ul><hr><h2 id="组件状态"><a href="#组件状态" class="headerlink" title="组件状态"></a>组件状态</h2><blockquote><p>props 是组件外传递进来的数据，state 代表的就是 React 组件的内部状态。</p></blockquote><ul><li>判断一个数据放在哪<ol><li>如果数据由外部传入，放在 props 中；</li><li>如果是组件内部状态，是否这个状态更改应该立刻引发一次组件重新渲染？如果是，放在 state 中；不是，放在成员变量中。</li></ol></li><li>函数参数的 state 更新<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">increment</span>(<span class="params">state, props</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> &#123;<span class="attr">count</span>: state.<span class="property">count</span> + <span class="number">1</span>&#125;;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">this</span>.<span class="title function_">setState</span>(increment);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2 </span></span><br><span class="line"><span class="variable language_">this</span>.<span class="title function_">setState</span>(<span class="function">(<span class="params">preState, props</span>) =&gt;</span> (&#123;&#125;)</span><br></pre></td></tr></table></figure></li></ul><h2 id="Redux-使用模式"><a href="#Redux-使用模式" class="headerlink" title="Redux 使用模式"></a>Redux 使用模式</h2><ul><li>connect( mapStateToProps , mapDispatchToProps )<ol><li>前者把 state 映射到 props 上</li><li>后者把 dispatch 映射到 props 上<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 后续写法</span></span><br><span class="line"><span class="title function_">connect</span>(<span class="function">(<span class="params"> state </span>)=&gt;</span>(&#123;</span><br><span class="line"><span class="attr">count</span>: state.<span class="property">count</span>,</span><br><span class="line">&#125;), <span class="function">(<span class="params"> dispatch </span>)=&gt;</span>(&#123;</span><br><span class="line"> <span class="attr">onIncrement</span>: <span class="function">() =&gt;</span> <span class="title function_">dispatch</span>(&#123;<span class="attr">type</span>: <span class="string">&#x27;INCREMENT&#x27;</span>&#125;),</span><br><span class="line">   <span class="attr">$fetch</span>: <span class="function">(<span class="params">&#123;payload, callback&#125;</span>)=&gt;</span> <span class="title function_">dispatch</span>(&#123;<span class="attr">type</span>: <span class="string">&#x27;fetch&#x27;</span>, payload, callback&#125;),</span><br><span class="line">&#125;))</span><br><span class="line"></span><br><span class="line"><span class="comment">// this.props.$fetch(&#123;&#125;)</span></span><br></pre></td></tr></table></figure></li></ol></li></ul><h2 id="React-Router"><a href="#React-Router" class="headerlink" title="React Router"></a>React Router</h2><ul><li>路由的种类<ul><li>HashRouter <code>/#/about</code></li><li>BrowserRouter <code>/about</code> <strong>推荐</strong></li></ul></li></ul><h2 id="拥抱异步渲染"><a href="#拥抱异步渲染" class="headerlink" title="拥抱异步渲染"></a>拥抱异步渲染</h2><ul><li>在 <code>componentDidMount</code> 发起网络请求</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;  React 使用过程中的一些记录..&lt;/p&gt;</summary>
    
    
    
    <category term="React" scheme="https://hocg.in/categories/React/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="React" scheme="https://hocg.in/tags/React/"/>
    
  </entry>
  
  <entry>
    <title>关于Java IO、NIO、AIO</title>
    <link href="https://hocg.in/2018/07/02/%E5%85%B3%E4%BA%8EJava%20IO%E3%80%81NIO%E3%80%81AIO/"/>
    <id>https://hocg.in/2018/07/02/%E5%85%B3%E4%BA%8EJava%20IO%E3%80%81NIO%E3%80%81AIO/</id>
    <published>2018-07-02T08:10:39.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>关于Java常用数据结构，后期继续整理</p><span id="more"></span><h2 id="关于-IO"><a href="#关于-IO" class="headerlink" title="关于 IO"></a>关于 IO</h2><ul><li>BIO 同步并阻塞</li><li>NIO 同步非阻塞</li><li>AIO(NIO.2) <code>JDK7</code>, 异步非阻塞</li></ul><h2 id="NIO"><a href="#NIO" class="headerlink" title="NIO"></a>NIO</h2><ul><li>Channel <code>通道</code> 传输</li><li>Buffer <code>缓冲区</code> 存储</li><li>Selectors <code>多路复用器</code> 监听 Channel IO 状况</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Created by hocgin on 2018/7/2.</span></span><br><span class="line"><span class="comment"> * email: hocgin@gmail.com</span></span><br><span class="line"><span class="comment"> * NIO</span></span><br><span class="line"><span class="comment"> * Non-blocking IO（非阻塞IO）</span></span><br><span class="line"><span class="comment"> * - Selectors 多路复用器，用于监控 SelectableChannel IO状况</span></span><br><span class="line"><span class="comment"> * -- SelectableChannel</span></span><br><span class="line"><span class="comment"> * ----SocketChannel</span></span><br><span class="line"><span class="comment"> * ----ServerSocketChannel</span></span><br><span class="line"><span class="comment"> * ----DatagramChannel</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * ----Pipe.SinkChannel 单向管道-写</span></span><br><span class="line"><span class="comment"> * ----Pipe.SourceChannel 单向管道-读</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * - Channels</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * - Buffers</span></span><br><span class="line"><span class="comment"> * -- capacity 总容量</span></span><br><span class="line"><span class="comment"> * -- limit 界限，可操作最大范围</span></span><br><span class="line"><span class="comment"> * -- position 当前操作位置</span></span><br><span class="line"><span class="comment"> * -- mark 标记，记录position</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;</span></span><br><span class="line"><span class="comment"> * 0 &lt;= mark &lt;= position &lt;= limit &lt;= capacity</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NIOTest</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 阻塞模式的 Socket NIO</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">nio_client</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">path</span> <span class="operator">=</span> <span class="string">&quot;/Users/hocgin/Document/Projects/GitHub/23-Day/src/test/java/in/hocg/Test.java&quot;</span>;</span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">                <span class="type">SocketChannel</span> <span class="variable">channel</span> <span class="operator">=</span> SocketChannel.open(<span class="keyword">new</span> <span class="title class_">InetSocketAddress</span>(<span class="string">&quot;127.0.0.1&quot;</span>, <span class="number">9898</span>));</span><br><span class="line">                <span class="type">FileChannel</span> <span class="variable">inChannel</span> <span class="operator">=</span> FileChannel.open(Paths.get(path), StandardOpenOption.READ);</span><br><span class="line">        ) &#123;</span><br><span class="line">            <span class="type">ByteBuffer</span> <span class="variable">buffer</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">            <span class="keyword">while</span> (inChannel.read(buffer) != -<span class="number">1</span>) &#123;</span><br><span class="line">                buffer.flip();</span><br><span class="line">                channel.write(buffer);</span><br><span class="line">                buffer.clear();</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">            channel.shutdownOutput();</span><br><span class="line">            </span><br><span class="line">            <span class="comment">/**</span></span><br><span class="line"><span class="comment">             * 接收反馈</span></span><br><span class="line"><span class="comment">             */</span></span><br><span class="line">            <span class="keyword">while</span> (channel.read(buffer) != -<span class="number">1</span>) &#123;</span><br><span class="line">                buffer.flip();</span><br><span class="line">                System.out.println(<span class="keyword">new</span> <span class="title class_">String</span>(buffer.array(), <span class="number">0</span>, buffer.limit()));</span><br><span class="line">                buffer.clear();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 阻塞模式的 Socket NIO</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">nio_server</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">                <span class="type">ServerSocketChannel</span> <span class="variable">channel</span> <span class="operator">=</span> ServerSocketChannel.open();</span><br><span class="line">        ) &#123;</span><br><span class="line">            channel.bind(<span class="keyword">new</span> <span class="title class_">InetSocketAddress</span>(<span class="number">9898</span>));</span><br><span class="line">            <span class="type">SocketChannel</span> <span class="variable">socketChannel</span> <span class="operator">=</span> channel.accept();</span><br><span class="line">            <span class="type">ByteBuffer</span> <span class="variable">buffer</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">            <span class="keyword">while</span> (socketChannel.read(buffer) != -<span class="number">1</span>) &#123;</span><br><span class="line">                buffer.flip();</span><br><span class="line">                System.out.println(<span class="keyword">new</span> <span class="title class_">String</span>(buffer.array(), <span class="number">0</span>, buffer.limit()));</span><br><span class="line">                buffer.clear();</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">            buffer.put(<span class="string">&quot;接收完毕&quot;</span>.getBytes());</span><br><span class="line">            buffer.flip();</span><br><span class="line">            socketChannel.write(buffer);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 非阻塞模式的 Socket NIO</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">nio_client2</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">                <span class="type">SocketChannel</span> <span class="variable">channel</span> <span class="operator">=</span> SocketChannel.open(<span class="keyword">new</span> <span class="title class_">InetSocketAddress</span>(<span class="string">&quot;127.0.0.1&quot;</span>, <span class="number">9898</span>));</span><br><span class="line">        ) &#123;</span><br><span class="line">            <span class="comment">// 非阻塞</span></span><br><span class="line">            channel.configureBlocking(<span class="literal">false</span>);</span><br><span class="line">            <span class="type">ByteBuffer</span> <span class="variable">buffer</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">            <span class="comment">/**</span></span><br><span class="line"><span class="comment">             * 发送信息</span></span><br><span class="line"><span class="comment">             */</span></span><br><span class="line">            buffer.put(LocalDateTime.now().toString().getBytes());</span><br><span class="line">            buffer.flip();</span><br><span class="line">            channel.write(buffer);</span><br><span class="line">            </span><br><span class="line">            <span class="comment">/**</span></span><br><span class="line"><span class="comment">             * 接收反馈</span></span><br><span class="line"><span class="comment">             */</span></span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 非阻塞模式的 Socket NIO</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">nio_server2</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">                <span class="type">ServerSocketChannel</span> <span class="variable">channel</span> <span class="operator">=</span> ServerSocketChannel.open();</span><br><span class="line">        ) &#123;</span><br><span class="line">            <span class="comment">// 非阻塞</span></span><br><span class="line">            channel.configureBlocking(<span class="literal">false</span>);</span><br><span class="line">            </span><br><span class="line">            channel.bind(<span class="keyword">new</span> <span class="title class_">InetSocketAddress</span>(<span class="number">9898</span>));</span><br><span class="line">            </span><br><span class="line">            <span class="type">Selector</span> <span class="variable">selector</span> <span class="operator">=</span> Selector.open();</span><br><span class="line">            <span class="comment">/**</span></span><br><span class="line"><span class="comment">             * 注册通道 指定事件类型</span></span><br><span class="line"><span class="comment">             */</span></span><br><span class="line">            channel.register(selector, SelectionKey.OP_ACCEPT);</span><br><span class="line">            </span><br><span class="line">            <span class="keyword">while</span> (selector.select() &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                Iterator&lt;SelectionKey&gt; iterator = selector.selectedKeys().iterator();</span><br><span class="line">                <span class="keyword">while</span> (iterator.hasNext()) &#123;</span><br><span class="line">                    <span class="type">SelectionKey</span> <span class="variable">action</span> <span class="operator">=</span> iterator.next();</span><br><span class="line">                    <span class="keyword">if</span> (action.isAcceptable()) &#123;</span><br><span class="line">                        <span class="type">SocketChannel</span> <span class="variable">socketChannel</span> <span class="operator">=</span> channel.accept();</span><br><span class="line">                        socketChannel.configureBlocking(<span class="literal">false</span>);</span><br><span class="line">                        socketChannel.register(selector, SelectionKey.OP_READ);</span><br><span class="line">                    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (action.isReadable()) &#123;</span><br><span class="line">                        <span class="type">SocketChannel</span> <span class="variable">socketChannel</span> <span class="operator">=</span> (SocketChannel) action.channel();</span><br><span class="line">                        <span class="type">ByteBuffer</span> <span class="variable">buffer</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">                        <span class="keyword">try</span> &#123;</span><br><span class="line">                            <span class="keyword">while</span> (socketChannel.read(buffer) != -<span class="number">1</span>) &#123;</span><br><span class="line">                                buffer.flip();</span><br><span class="line">                                <span class="type">String</span> <span class="variable">s</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(buffer.array(), <span class="number">0</span>, buffer.limit());</span><br><span class="line">                                <span class="keyword">if</span> (!Strings.isNullOrEmpty(s)) &#123;</span><br><span class="line">                                    System.out.println(s);</span><br><span class="line">                                &#125;</span><br><span class="line">                                buffer.clear();</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">                            e.printStackTrace();</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                    iterator.remove();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">aio_server</span><span class="params">()</span> <span class="keyword">throws</span> IOException, InterruptedException &#123;</span><br><span class="line"><span class="comment">//        AsynchronousChannelGroup group = AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(), 10);</span></span><br><span class="line">        <span class="type">AsynchronousServerSocketChannel</span> <span class="variable">channel</span> <span class="operator">=</span> AsynchronousServerSocketChannel.open();</span><br><span class="line">        channel.bind(<span class="keyword">new</span> <span class="title class_">InetSocketAddress</span>(<span class="number">9898</span>));</span><br><span class="line">        channel.accept(<span class="literal">null</span>, <span class="keyword">new</span> <span class="title class_">CompletionHandler</span>&lt;AsynchronousSocketChannel, Void&gt;() &#123;</span><br><span class="line">            <span class="keyword">final</span> <span class="type">ByteBuffer</span> <span class="variable">buffer</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">            </span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">completed</span><span class="params">(AsynchronousSocketChannel result, Void attachment)</span> &#123;</span><br><span class="line">                </span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    result.read(buffer).get();</span><br><span class="line">                    buffer.flip();</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;服务端 成功 :%s&quot;</span>, <span class="keyword">new</span> <span class="title class_">String</span>(buffer.array()).trim()));</span><br><span class="line">                    result.close();</span><br><span class="line">                    channel.accept(<span class="literal">null</span>, <span class="built_in">this</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (IOException | InterruptedException | ExecutionException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">failed</span><span class="params">(Throwable exc, Void attachment)</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;failed&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        </span><br><span class="line">        LockSupport.park();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">aio_client</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">AsynchronousSocketChannel</span> <span class="variable">channel</span> <span class="operator">=</span> AsynchronousSocketChannel.open();</span><br><span class="line">        channel.connect(<span class="keyword">new</span> <span class="title class_">InetSocketAddress</span>(<span class="string">&quot;127.0.0.1&quot;</span>, <span class="number">9898</span>), <span class="literal">null</span>, <span class="keyword">new</span> <span class="title class_">CompletionHandler</span>&lt;Void, Void&gt;() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">completed</span><span class="params">(Void result, Void attachment)</span> &#123;</span><br><span class="line">                <span class="type">ByteBuffer</span> <span class="variable">buffer</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">                buffer.put(<span class="string">&quot;你好&quot;</span>.getBytes());</span><br><span class="line">                buffer.flip();</span><br><span class="line">                channel.write(buffer);</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">failed</span><span class="params">(Throwable exc, Void attachment)</span> &#123;</span><br><span class="line">                System.out.println(exc);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Buffer</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IOException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">buffer</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">ByteBuffer</span> <span class="variable">buffer</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">        System.out.println(buffer.position()); <span class="comment">// 0</span></span><br><span class="line">        System.out.println(buffer.limit());    <span class="comment">// 1024</span></span><br><span class="line">        System.out.println(buffer.capacity());  <span class="comment">// 1024</span></span><br><span class="line">        buffer.put(<span class="string">&quot;asd&quot;</span>.getBytes());</span><br><span class="line">        </span><br><span class="line">        buffer.flip(); <span class="comment">// 设置读取的范围限制至 position</span></span><br><span class="line">        <span class="type">byte</span>[] dst = <span class="keyword">new</span> <span class="title class_">byte</span>[buffer.limit()];</span><br><span class="line">        buffer.get(dst);</span><br><span class="line">        System.out.println(<span class="keyword">new</span> <span class="title class_">String</span>(dst, <span class="number">0</span>, dst.length));</span><br><span class="line">        </span><br><span class="line">        buffer.rewind(); <span class="comment">// 重读 position = 0 mark = -1</span></span><br><span class="line">        </span><br><span class="line">        buffer.clear(); <span class="comment">// 清空 position = 0  limit = capacity mark = -1</span></span><br><span class="line">        </span><br><span class="line">        buffer.mark(); <span class="comment">// 标记 mark = position</span></span><br><span class="line">        </span><br><span class="line">        buffer.reset(); <span class="comment">// position恢复为标记位置 position = mark</span></span><br><span class="line">        </span><br><span class="line">        buffer.hasRemaining(); <span class="comment">// 是否有剩余数据 position &lt; limit</span></span><br><span class="line">        </span><br><span class="line">        buffer.remaining(); <span class="comment">// 剩余数量 limit - position</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * getChannel</span></span><br><span class="line"><span class="comment">     * - 本地</span></span><br><span class="line"><span class="comment">     * - FileInputStream/FileOutputStream</span></span><br><span class="line"><span class="comment">     * - RandomAccessFile</span></span><br><span class="line"><span class="comment">     * - 网络</span></span><br><span class="line"><span class="comment">     * - Socket</span></span><br><span class="line"><span class="comment">     * - ServerSocket</span></span><br><span class="line"><span class="comment">     * - DatagramSocket</span></span><br><span class="line"><span class="comment">     * - JDK 7</span></span><br><span class="line"><span class="comment">     * - xxChannel.open()</span></span><br><span class="line"><span class="comment">     * - Files.newByteChannel()</span></span><br><span class="line"><span class="comment">     * - Channels.newXXX</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">channel</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">path</span> <span class="operator">=</span> <span class="string">&quot;/Users/hocgin/Document/Projects/GitHub/23-Day/src/test/java/in/hocg/Test.java&quot;</span>;</span><br><span class="line">        <span class="type">FileInputStream</span> <span class="variable">in</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(path);</span><br><span class="line">        <span class="type">ReadableByteChannel</span> <span class="variable">channel</span> <span class="operator">=</span> Channels.newChannel(in);</span><br><span class="line">        <span class="type">ByteBuffer</span> <span class="variable">buffer</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">        <span class="keyword">while</span> (channel.read(buffer) != -<span class="number">1</span>) &#123;</span><br><span class="line">            buffer.flip();</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;%s&quot;</span>, <span class="keyword">new</span> <span class="title class_">String</span>(buffer.array(), <span class="number">0</span>, buffer.limit())));</span><br><span class="line">            buffer.clear();</span><br><span class="line">        &#125;</span><br><span class="line">        channel.close();</span><br><span class="line">        in.close();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 直接缓冲区</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">channel2</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">path</span> <span class="operator">=</span> <span class="string">&quot;/Users/hocgin/Document/Projects/GitHub/23-Day/src/test/java/in/hocg/Test.java&quot;</span>;</span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">                <span class="type">FileChannel</span> <span class="variable">inChannel</span> <span class="operator">=</span> FileChannel.open(Paths.get(path), StandardOpenOption.READ);</span><br><span class="line">                <span class="type">FileChannel</span> <span class="variable">outChannel</span> <span class="operator">=</span> FileChannel.open(Paths.get(path), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)</span><br><span class="line">        ) &#123;</span><br><span class="line">            <span class="type">MappedByteBuffer</span> <span class="variable">inMap</span> <span class="operator">=</span> inChannel.map(FileChannel.MapMode.READ_ONLY, <span class="number">0</span>, inChannel.size());</span><br><span class="line">            <span class="type">MappedByteBuffer</span> <span class="variable">outMap</span> <span class="operator">=</span> outChannel.map(FileChannel.MapMode.READ_WRITE, <span class="number">0</span>, inChannel.size());</span><br><span class="line">            <span class="type">byte</span>[] bytes = <span class="keyword">new</span> <span class="title class_">byte</span>[inMap.limit()];</span><br><span class="line">            inMap.get(bytes);</span><br><span class="line">            outMap.put(bytes);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 通道间的数据传输(直接缓冲区)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">transfer</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">path</span> <span class="operator">=</span> <span class="string">&quot;/Users/hocgin/Document/Projects/GitHub/23-Day/src/test/java/in/hocg/Test.java&quot;</span>;</span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">                <span class="type">FileChannel</span> <span class="variable">inChannel</span> <span class="operator">=</span> FileChannel.open(Paths.get(path), StandardOpenOption.READ);</span><br><span class="line">                <span class="type">FileChannel</span> <span class="variable">outChannel</span> <span class="operator">=</span> FileChannel.open(Paths.get(path), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)</span><br><span class="line">        ) &#123;</span><br><span class="line">            inChannel.transferTo(<span class="number">0</span>, inChannel.size(), outChannel);</span><br><span class="line"><span class="comment">//            inChannel.transferFrom(outChannel,0, inChannel.size());</span></span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 分散读取(Scatter)</span></span><br><span class="line"><span class="comment">     * 聚集写入(Gather)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">scatter</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">path</span> <span class="operator">=</span> <span class="string">&quot;/Users/hocgin/Document/Projects/GitHub/23-Day/src/test/java/in/hocg/Test.java&quot;</span>;</span><br><span class="line">        <span class="keyword">try</span> (</span><br><span class="line">                <span class="type">RandomAccessFile</span> <span class="variable">f</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">RandomAccessFile</span>(path, <span class="string">&quot;rw&quot;</span>);</span><br><span class="line">        ) &#123;</span><br><span class="line">            <span class="type">FileChannel</span> <span class="variable">channel</span> <span class="operator">=</span> f.getChannel();</span><br><span class="line">            <span class="type">ByteBuffer</span> <span class="variable">allocate1</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">            <span class="type">ByteBuffer</span> <span class="variable">allocate2</span> <span class="operator">=</span> ByteBuffer.allocate(<span class="number">1024</span>);</span><br><span class="line">            ByteBuffer[] all = &#123;allocate1, allocate2&#125;;</span><br><span class="line">            </span><br><span class="line">            <span class="comment">// 分散读取</span></span><br><span class="line">            channel.read(all);</span><br><span class="line">            </span><br><span class="line">            <span class="comment">// 聚集写入</span></span><br><span class="line">            channel.write(all);</span><br><span class="line">            </span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SortedMap&lt;String, Charset&gt; map = Charset.availableCharsets();</span><br><span class="line">        System.out.println(map);</span><br><span class="line">        System.out.println(Charset.defaultCharset());</span><br><span class="line">        <span class="type">Charset</span> <span class="variable">charset</span> <span class="operator">=</span> Charset.forName(<span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line">        <span class="type">CharsetEncoder</span> <span class="variable">charsetEncoder</span> <span class="operator">=</span> charset.newEncoder();</span><br><span class="line">        <span class="type">CharsetDecoder</span> <span class="variable">charsetDecoder</span> <span class="operator">=</span> charset.newDecoder();</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;关于Java常用数据结构，后期继续整理&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="IO" scheme="https://hocg.in/tags/IO/"/>
    
  </entry>
  
  <entry>
    <title>使用 GitLab 来对 Spring Boot 项目进行 CI/CD</title>
    <link href="https://hocg.in/2018/06/20/%E4%BD%BF%E7%94%A8%20GitLab%20%E6%9D%A5%E5%AF%B9%20Spring%20Boot%20%E9%A1%B9%E7%9B%AE%E8%BF%9B%E8%A1%8C%20CI:CD/"/>
    <id>https://hocg.in/2018/06/20/%E4%BD%BF%E7%94%A8%20GitLab%20%E6%9D%A5%E5%AF%B9%20Spring%20Boot%20%E9%A1%B9%E7%9B%AE%E8%BF%9B%E8%A1%8C%20CI:CD/</id>
    <published>2018-06-20T22:34:20.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>利用 GitLab Pipelines 来进行项目的持续集成和部署。</p><span id="more"></span><h2 id="使用-GitLab-CI-构建-Spring-Boot-项目"><a href="#使用-GitLab-CI-构建-Spring-Boot-项目" class="headerlink" title="使用 GitLab CI 构建 Spring Boot 项目"></a>使用 GitLab CI 构建 Spring Boot 项目</h2><h3 id="搭建-GitLab-CE"><a href="#搭建-GitLab-CE" class="headerlink" title="搭建 GitLab CE"></a>搭建 GitLab CE</h3><blockquote><p>使用 Docker 方式搭建 GitLab CE</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">sudo docker run --detach \</span><br><span class="line">    --publish 443:443 \</span><br><span class="line">    --publish 80:80 \</span><br><span class="line">    --publish 2222:22 \</span><br><span class="line">    --name gitlab \</span><br><span class="line">    --restart always \</span><br><span class="line">    --volume /data/gitlab/config:/etc/gitlab \</span><br><span class="line">    --volume /data/gitlab/logs:/var/log/gitlab \</span><br><span class="line">    --volume /data/gitlab/data:/var/opt/gitlab \</span><br><span class="line">    gitlab/gitlab-ce:latest</span><br></pre></td></tr></table></figure><h3 id="搭建-GitLab-Runner"><a href="#搭建-GitLab-Runner" class="headerlink" title="搭建 GitLab Runner"></a>搭建 GitLab Runner</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">sudo docker run --rm -t -d -i -p 8084:8080 \</span><br><span class="line">    -v /data/gitlab-runner:/etc/gitlab-runner \</span><br><span class="line">    -v /var/run/docker.sock:/var/run/docker.sock \</span><br><span class="line">    --add-host ad4aac43c567:172.17.0.2 \</span><br><span class="line">    --name gitlab-runner \</span><br><span class="line">    gitlab/gitlab-runner</span><br></pre></td></tr></table></figure><ul><li><ol><li>此处需注意<code>--add-host</code>请自行替换为GitLab CE Docker 容器 ID，此处是为了让 GitLab CE Docker 容器可以被 GitLab Runner 访问到, 如果使用公网 IP 可以忽略。</li></ol></li><li><ol start="2"><li>如果通过<code>/etc/hosts</code>仍然无法解决HOST问题, 请自行更改<code>/data/gitlab-runner/config.toml</code>文件，在<code>[runners.docker]</code>节点下面添加<code>extra_hosts = [&quot;ad4aac43c567:172.17.0.2&quot;]</code>。</li></ol></li></ul><h3 id="注册-Runner"><a href="#注册-Runner" class="headerlink" title="注册 Runner"></a>注册 Runner</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">sudo docker exec -it gitlab-runner  gitlab-runner register -n \</span><br><span class="line">      --url http://192.168.1.13/ \</span><br><span class="line">      --registration-token pfHxurfRMBctWwkqrt1c \</span><br><span class="line">      --tag-list=docker-privileged \</span><br><span class="line">      --description &quot;dockersock&quot; \</span><br><span class="line">      --docker-privileged=false \</span><br><span class="line">      --docker-image &quot;docker:latest&quot; \</span><br><span class="line">      --docker-volumes /var/run/docker.sock:/var/run/docker.sock \</span><br><span class="line">      --docker-volumes /root/m2:/root/.m2 \</span><br><span class="line">      --executor docker</span><br></pre></td></tr></table></figure><ul><li>url: GitLab CE 里面 CI 栏目查看</li><li>registration-token: GitLab CE 里面 CI 栏目查看</li><li>tag-list: 标签, 后续用于执行步骤时指定 Runner</li><li>description: 描述</li><li>docker-image: 外层使用的 Docker 镜像</li><li>executor: 执行器</li></ul><h3 id="编写-gitlab-ci-yml"><a href="#编写-gitlab-ci-yml" class="headerlink" title="编写 .gitlab-ci.yml"></a>编写 <code>.gitlab-ci.yml</code></h3><p>点击<a href="https://github.com/hocgin/GitLab-CI/blob/master/.gitlab-ci.yml">.gitlab-ci.yml</a>查看</p><h3 id="一键部署"><a href="#一键部署" class="headerlink" title="一键部署"></a>一键部署</h3><p><a href="https://github.com/hocgin/GitLab-CI/blob/master/docker-compose.yml">点击获取</a>, 记得修改HOST。</p><h3 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h3><p><a href="https://github.com/hocgin/GitLab-CI">GitLab-CI</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;利用 GitLab Pipelines 来进行项目的持续集成和部署。&lt;/p&gt;</summary>
    
    
    
    <category term="DevOps" scheme="https://hocg.in/categories/DevOps/"/>
    
    
    <category term="DevOps" scheme="https://hocg.in/tags/DevOps/"/>
    
    <category term="GitLab" scheme="https://hocg.in/tags/GitLab/"/>
    
    <category term="CI/CD" scheme="https://hocg.in/tags/CI-CD/"/>
    
  </entry>
  
  <entry>
    <title>关于Java-数据结构</title>
    <link href="https://hocg.in/2018/03/20/%E5%85%B3%E4%BA%8EJava-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    <id>https://hocg.in/2018/03/20/%E5%85%B3%E4%BA%8EJava-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/</id>
    <published>2018-03-20T17:10:39.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>关于Java常用数据结构，后期继续整理</p><span id="more"></span><h2 id="List"><a href="#List" class="headerlink" title="List"></a>List</h2><blockquote><p>List必须保持元素特定的顺序</p></blockquote><h3 id="LinkedList-List、Queue"><a href="#LinkedList-List、Queue" class="headerlink" title="LinkedList List、Queue"></a>LinkedList <code>List</code>、<code>Queue</code></h3><ul><li>双链表<code>Node</code></li><li>非线程安全的</li><li>转换为线程安全<code>Collections.synchronizedList(new LinkedList(...));</code></li><li>特点: 实现了List、Deque接口，双向链表，适合频繁插入&#x2F;删除，不适合使用set、set。</li></ul><h3 id="ArrayList-List"><a href="#ArrayList-List" class="headerlink" title="ArrayList List"></a>ArrayList <code>List</code></h3><ul><li>数组实现</li><li>非线程安全的</li><li>特点: 动态长度(默认长度为10，增长默认为当前长度的1&#x2F;2，不可大于Integer.MAX_VALUE - 8，否则 OutOfMemoryError), get、set直接访问。</li></ul><h3 id="Vector-List"><a href="#Vector-List" class="headerlink" title="Vector List"></a>Vector <code>List</code></h3><ul><li>线程安全</li><li>用<code>synchronized</code>修饰函数</li><li></li></ul><h3 id="CopyOnWriteArrayList-List"><a href="#CopyOnWriteArrayList-List" class="headerlink" title="CopyOnWriteArrayList List"></a>CopyOnWriteArrayList <code>List</code></h3><ul><li>数组实现</li><li>线程安全</li><li>特点: 数组长度默认为0，每次修改都会重新增长长度和拷贝数组。</li></ul><h3 id="Stack"><a href="#Stack" class="headerlink" title="Stack"></a>Stack</h3><ul><li>线程安全</li><li>数组实现</li><li>特点: 模拟栈。</li></ul><h3 id="工具类"><a href="#工具类" class="headerlink" title="工具类"></a>工具类</h3><ul><li>转换为线程安全<code>Collections.synchronizedList(new ArrayList(...));</code><ul><li>内部是用List实现存储的</li><li>与<code>Vector</code>差别是可以传入定制的锁。</li></ul></li><li>转为不可变List <code>Collections.unmodifiableList(new ArrayList&lt;&gt;())</code><ul><li>门面模式(List)</li><li>线程安全</li><li>特点: 不可变。</li></ul></li></ul><h3 id="常用技巧"><a href="#常用技巧" class="headerlink" title="常用技巧"></a>常用技巧</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">lists</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 打乱数组</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    List&lt;Integer&gt; list = Arrays.asList(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);</span><br><span class="line">    Collections.shuffle(list);</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;打乱 %s&quot;</span>, list));</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 移除所有 NULL</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    list.removeIf(Objects::isNull);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 去重</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    list = list.stream().distinct().collect(Collectors.toList());</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 分组</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Map&lt;String, List&lt;Integer&gt;&gt; collect = list.stream()</span><br><span class="line">            .collect(Collectors.groupingBy(Object::toString));</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查找一个元素</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">Integer</span> <span class="variable">integer</span> <span class="operator">=</span> list.stream().filter(item -&gt; &#123;</span><br><span class="line">        <span class="keyword">return</span> item == <span class="number">1</span>;</span><br><span class="line">    &#125;).findAny().orElse(<span class="literal">null</span>);</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h2><blockquote><p>Set不能有重复元素</p></blockquote><h3 id="HashSet-Set"><a href="#HashSet-Set" class="headerlink" title="HashSet Set"></a>HashSet <code>Set</code></h3><ul><li>线程不安全</li><li>利用 HashMap 的 Key 值进行存储。</li><li>无序</li><li>利用Hash存储，存取和查找高效。</li></ul><h3 id="LinkedHashSet-Set"><a href="#LinkedHashSet-Set" class="headerlink" title="LinkedHashSet Set"></a>LinkedHashSet <code>Set</code></h3><ul><li>线程不安全</li><li>利用 LinkedHashMap 的 Key 值进行存储。</li><li>按插入排序</li></ul><h3 id="TreeSet-Set"><a href="#TreeSet-Set" class="headerlink" title="TreeSet Set"></a>TreeSet <code>Set</code></h3><ul><li>线程不安全</li><li>利用 TreeMap 的 Key 值进行存储。</li><li>插入有序, 默认自然排序。</li></ul><h2 id="Queue"><a href="#Queue" class="headerlink" title="Queue"></a>Queue</h2><blockquote><p>Queue保持一个队列(先进先出)的顺序.</p></blockquote><h3 id="PriorityQueue-Queue"><a href="#PriorityQueue-Queue" class="headerlink" title="PriorityQueue Queue"></a>PriorityQueue <code>Queue</code></h3><ul><li>线程不安全</li><li>数组实现</li></ul><h3 id="Deque-Queue"><a href="#Deque-Queue" class="headerlink" title="Deque Queue"></a>Deque <code>Queue</code></h3><ul><li>双端队列</li></ul><h5 id="ArrayDeque-Queue"><a href="#ArrayDeque-Queue" class="headerlink" title="ArrayDeque Queue"></a>ArrayDeque <code>Queue</code></h5><ul><li>数组实现</li><li>线程不安全</li><li>动态长度</li></ul><h3 id="BlockingQueue"><a href="#BlockingQueue" class="headerlink" title="BlockingQueue"></a>BlockingQueue</h3><h3 id="DelayQueue"><a href="#DelayQueue" class="headerlink" title="DelayQueue"></a>DelayQueue</h3><h2 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h2><blockquote><p>用于保存具有”映射关系”的数据</p></blockquote><h3 id="HashMap"><a href="#HashMap" class="headerlink" title="HashMap"></a>HashMap</h3><ul><li>不能保证key-value对的顺序</li><li>线程不安全</li></ul><h3 id="LinkedHashMap"><a href="#LinkedHashMap" class="headerlink" title="LinkedHashMap"></a>LinkedHashMap</h3><ul><li>插入顺序</li><li>线程不安全</li></ul><h3 id="TreeMap"><a href="#TreeMap" class="headerlink" title="TreeMap"></a>TreeMap</h3><ul><li>线程不安全</li><li>插入有序, 默认自然排序。</li></ul><h3 id="ConcurrentHashMap"><a href="#ConcurrentHashMap" class="headerlink" title="ConcurrentHashMap"></a>ConcurrentHashMap</h3><ul><li>线程安全</li><li>特点: 分多个块</li></ul><h2 id="整理了两张图"><a href="#整理了两张图" class="headerlink" title="整理了两张图"></a>整理了两张图</h2><p><img src="http://cdn.hocgin.top/map.png" alt="map.png"><br><img src="http://cdn.hocgin.top/%E9%9B%86%E5%90%88.png" alt="集合.png"></p><p><a href="https://www.kancloud.cn/this_is_lxf/javabase/210926">推荐</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;关于Java常用数据结构，后期继续整理&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="数据结构" scheme="https://hocg.in/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
  </entry>
  
  <entry>
    <title>关于Java多线程-几个辅助类</title>
    <link href="https://hocg.in/2018/03/06/%E5%85%B3%E4%BA%8EJava%E5%A4%9A%E7%BA%BF%E7%A8%8B-%E5%87%A0%E4%B8%AA%E8%BE%85%E5%8A%A9%E7%B1%BB/"/>
    <id>https://hocg.in/2018/03/06/%E5%85%B3%E4%BA%8EJava%E5%A4%9A%E7%BA%BF%E7%A8%8B-%E5%87%A0%E4%B8%AA%E8%BE%85%E5%8A%A9%E7%B1%BB/</id>
    <published>2018-03-06T17:13:39.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>关于Java多线程-几个辅助类，后期继续整理</p><span id="more"></span><h2 id="几个辅助类"><a href="#几个辅助类" class="headerlink" title="几个辅助类"></a>几个辅助类</h2><ul><li>CountDownLatch 计数器</li><li>CyclicBarrier 同步器</li><li>Phaser <code>1.7</code> 阶段性、同步、计数</li></ul><h3 id="Example"><a href="#Example" class="headerlink" title="Example"></a>Example</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><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></pre></td><td class="code"><pre><span class="line">    <span class="type">ExecutorService</span> <span class="variable">executorService</span> <span class="operator">=</span> Executors.newFixedThreadPool(<span class="number">4</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 计数器 latch.await() 会等待计数为 0</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">countDownLatch</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">CountDownLatch</span> <span class="variable">latch</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CountDownLatch</span>(<span class="number">4</span>);</span><br><span class="line">        LongStream.range(<span class="number">0</span>, <span class="number">4</span>).forEach((i)-&gt;&#123;</span><br><span class="line">            executorService.submit(latch::countDown);</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;index: %d&quot;</span>, latch.getCount()));</span><br><span class="line">        &#125;);</span><br><span class="line">    </span><br><span class="line">        latch.await();</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;index: %d&quot;</span>, latch.getCount()));</span><br><span class="line"><span class="comment">//        index: 4</span></span><br><span class="line"><span class="comment">//        index: 3</span></span><br><span class="line"><span class="comment">//        index: 2</span></span><br><span class="line"><span class="comment">//        index: 1</span></span><br><span class="line"><span class="comment">//        index: 0</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 等待指定数目的线程完成后, 才继续执行</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">cyclicBarrier</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">CyclicBarrier</span> <span class="variable">cyclicBarrier</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CyclicBarrier</span>(<span class="number">4</span>, ()-&gt;&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;所有任务执行完成，继续&quot;</span>);</span><br><span class="line">        &#125;);</span><br><span class="line">        LongStream.range(<span class="number">0</span>, <span class="number">4</span>).forEach((i)-&gt;&#123;</span><br><span class="line">            executorService.submit(()-&gt;&#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;已经完成数目: %d/%d&quot;</span>, cyclicBarrier.getNumberWaiting(), cyclicBarrier.getParties()));</span><br><span class="line">                    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">                    cyclicBarrier.await();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException | BrokenBarrierException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">                System.out.println(String.format(<span class="string">&quot;进行其他任务 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">    </span><br><span class="line">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">        </span><br><span class="line"><span class="comment">//        已经完成数目: 0/4</span></span><br><span class="line"><span class="comment">//        已经完成数目: 0/4</span></span><br><span class="line"><span class="comment">//        已经完成数目: 0/4</span></span><br><span class="line"><span class="comment">//        已经完成数目: 0/4</span></span><br><span class="line"><span class="comment">//        所有任务执行完成，继续</span></span><br><span class="line"><span class="comment">//        进行其他任务 pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        进行其他任务 pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        进行其他任务 pool-1-thread-1</span></span><br><span class="line"><span class="comment">//        进行其他任务 pool-1-thread-3</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 配置同时允许申请许可的数目，如果数目已满则进行阻塞等待释放许可。</span></span><br><span class="line"><span class="comment">     * Semaphore 可配置是否使用公平机制，类似Lock</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">semaphore</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">Semaphore</span> <span class="variable">semaphore</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Semaphore</span>(<span class="number">2</span>);</span><br><span class="line">        LongStream.range(<span class="number">0</span>, <span class="number">4</span>).forEach((i)-&gt;&#123;</span><br><span class="line">            executorService.submit(()-&gt;&#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;正在申请许可 ID:%s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">                    semaphore.acquire();</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;申请许可成功 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">                    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;进行任务 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;释放许可 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">                    semaphore.release();</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">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">    </span><br><span class="line"><span class="comment">//        正在申请许可 ID:pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        正在申请许可 ID:pool-1-thread-1</span></span><br><span class="line"><span class="comment">//        申请许可成功 pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        正在申请许可 ID:pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        正在申请许可 ID:pool-1-thread-3</span></span><br><span class="line"><span class="comment">//        申请许可成功 pool-1-thread-1</span></span><br><span class="line"><span class="comment">//        进行任务 pool-1-thread-1</span></span><br><span class="line"><span class="comment">//        进行任务 pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        释放许可 pool-1-thread-1</span></span><br><span class="line"><span class="comment">//        释放许可 pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        申请许可成功 pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        申请许可成功 pool-1-thread-3</span></span><br><span class="line"><span class="comment">//        进行任务 pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        进行任务 pool-1-thread-3</span></span><br><span class="line"><span class="comment">//        释放许可 pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        释放许可 pool-1-thread-3</span></span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 阶段性, 会等待所有人完成该步骤再进入下一个步骤</span></span><br><span class="line"><span class="comment">     * - 每个阶段均可进行加入或移除</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 函数</span></span><br><span class="line"><span class="comment">     * - arriveAndAwaitAdvance 等待阶段</span></span><br><span class="line"><span class="comment">     * - arriveAndDeregister 移除</span></span><br><span class="line"><span class="comment">     * - bulkRegister 加入</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">phaser</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">Phaser</span> <span class="variable">phaser</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Phaser</span>(<span class="number">4</span>);</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 阶段性任务</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        System.out.println(<span class="string">&quot;【阶段性任务】&quot;</span>);</span><br><span class="line">        LongStream.range(<span class="number">0</span>, <span class="number">4</span>).forEach((i)-&gt;&#123;</span><br><span class="line">            executorService.submit(()-&gt;&#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;第一步 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">                    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">                    phaser.arriveAndAwaitAdvance();</span><br><span class="line">                    </span><br><span class="line">                    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;第2步 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">                    phaser.arriveAndAwaitAdvance();</span><br><span class="line">                    </span><br><span class="line">                    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;第三步 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">                    phaser.arriveAndAwaitAdvance();</span><br><span class="line">                    </span><br><span class="line">                    System.out.println(<span class="string">&quot;Done&quot;</span>);</span><br><span class="line">                &#125;<span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">    </span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">    </span><br><span class="line">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 计数任务</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        System.out.println(<span class="string">&quot;【计数任务】&quot;</span>);</span><br><span class="line">        LongStream.range(<span class="number">0</span>, <span class="number">4</span>).forEach((i)-&gt;&#123;</span><br><span class="line">            executorService.submit(()-&gt;&#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;已经完成 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">                    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">                    phaser.awaitAdvance(phaser.getPhase()); <span class="comment">//cyclicBarrier.await();</span></span><br><span class="line">                &#125;<span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">        phaser.arrive();</span><br><span class="line">        System.out.println(<span class="string">&quot;计数完成&quot;</span>);</span><br><span class="line">        </span><br><span class="line"><span class="comment">//        【阶段性任务】</span></span><br><span class="line"><span class="comment">//        第一步 pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        第一步 pool-1-thread-3</span></span><br><span class="line"><span class="comment">//        第一步 pool-1-thread-1</span></span><br><span class="line"><span class="comment">//        第一步 pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        第2步 pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        第2步 pool-1-thread-1</span></span><br><span class="line"><span class="comment">//        第2步 pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        第2步 pool-1-thread-3</span></span><br><span class="line"><span class="comment">//        第三步 pool-1-thread-1</span></span><br><span class="line"><span class="comment">//        第三步 pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        第三步 pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        第三步 pool-1-thread-3</span></span><br><span class="line"><span class="comment">//        Done</span></span><br><span class="line"><span class="comment">//        Done</span></span><br><span class="line"><span class="comment">//        Done</span></span><br><span class="line"><span class="comment">//        Done</span></span><br><span class="line"><span class="comment">//       【计数任务】</span></span><br><span class="line"><span class="comment">//        计数完成</span></span><br><span class="line"><span class="comment">//        已经完成 pool-1-thread-2</span></span><br><span class="line"><span class="comment">//        已经完成 pool-1-thread-4</span></span><br><span class="line"><span class="comment">//        已经完成 pool-1-thread-3</span></span><br><span class="line"><span class="comment">//        已经完成 pool-1-thread-1</span></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;关于Java多线程-几个辅助类，后期继续整理&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="多线程" scheme="https://hocg.in/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>关于Java多线程-可见性、CAS、AQS、锁</title>
    <link href="https://hocg.in/2018/03/03/%E5%85%B3%E4%BA%8EJava%E5%A4%9A%E7%BA%BF%E7%A8%8B-%E5%8F%AF%E8%A7%81%E6%80%A7%E3%80%81CAS%E3%80%81AQS%E3%80%81%E9%94%81/"/>
    <id>https://hocg.in/2018/03/03/%E5%85%B3%E4%BA%8EJava%E5%A4%9A%E7%BA%BF%E7%A8%8B-%E5%8F%AF%E8%A7%81%E6%80%A7%E3%80%81CAS%E3%80%81AQS%E3%80%81%E9%94%81/</id>
    <published>2018-03-03T09:13:39.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>关于Java多线程-可见性、CAS、AQS、锁</p><span id="more"></span><h2 id="前提"><a href="#前提" class="headerlink" title="前提"></a>前提</h2><blockquote><p>解决多线程操作出现的脏读和数据、操作不一致问题。</p></blockquote><h3 id="volatile可见性"><a href="#volatile可见性" class="headerlink" title="volatile可见性"></a>volatile<code>可见性</code></h3><blockquote><p>Java 内存分为主内存和工作内存。<br>正常情况每个线程都拥有自己的工作内存，然后每隔一段时间会同步到主内存上，因此会存在不一致的情况。而<code>volatile</code>则是为了让标记字段的读取和写入都是在主内存中，保证其一致性。<br><code>注意:</code>但其仍不能保证写入操作的原子性。</p></blockquote><h3 id="CAS"><a href="#CAS" class="headerlink" title="CAS"></a>CAS</h3><blockquote><p><code>Compare And Swap</code>, 比较并交换。用于解决多线程使用锁造成的性能损耗。<br>Java 是利用<code>Unsafe</code>来实现CAS，进行硬件级别的原子性操作。</p></blockquote><h3 id="AQS"><a href="#AQS" class="headerlink" title="AQS"></a>AQS</h3><blockquote><p><code>AbstractQueuedSynchronizer</code>, 这个为 Java 类, 公平锁<code>FairSync</code>和非公平锁<code>NonfairSync</code>均是通过此实现的。<br>其利用队列来实现阻塞锁和同步。</p></blockquote><h4 id="ABA-问题"><a href="#ABA-问题" class="headerlink" title="ABA 问题"></a>ABA 问题</h4><blockquote><p>情景: 初始值为A[线程1获取的值为A][线程2获取的值为A,并更改值A为值B,再更改值B为值A][线程1更改值A为值B]。<br>出现问题: 线程1感觉不到值有一段变化的过程，这是<code>乐观锁</code>出现的问题。<br>解决方案: <code>AtomicStampedReference</code>&#x2F;<code>AtomicMarkableReference</code>你值得拥有。</p></blockquote><ul><li>AtomicStampedReference 每次修改会存储版本号,版本号实现用int。</li><li>AtomicMarkableReference 每次修改会存储版本号,版本号实现用boolean。</li></ul><hr><h2 id="锁的名词"><a href="#锁的名词" class="headerlink" title="锁的名词"></a>锁的名词</h2><h3 id="可重入锁"><a href="#可重入锁" class="headerlink" title="可重入锁"></a>可重入锁</h3><ul><li>已获取的锁可以不必去重新申请。  </li><li>synchronized&#x2F;ReentrantLock 是可重入锁.</li></ul><h3 id="可中断锁"><a href="#可中断锁" class="headerlink" title="可中断锁"></a>可中断锁</h3><ul><li>可以取消申请锁的操作。</li><li>synchronized 不是可中断锁。</li></ul><h3 id="公平锁"><a href="#公平锁" class="headerlink" title="公平锁"></a>公平锁</h3><ul><li>公平锁是根据请求顺序分发锁, 唤醒需要时间，能保- 证操作的顺序。  </li><li>非公平锁会出现插队情况，性能高，但是不能保证操作的顺序。  </li><li>synchronized 不是公平锁。</li><li><code>ReentrantLock</code>&#x2F;<code>ReentrantReadWriteLock</code>默认情况是非公平锁<code>NonfairSync</code>,但可以设置为公平锁<code>FairSync</code></li></ul><h3 id="乐观锁"><a href="#乐观锁" class="headerlink" title="乐观锁"></a>乐观锁</h3><blockquote><p>每次不加锁，假设没有冲突去完成某项操作，如果因为冲突失败就重试，直到成功为止。</p></blockquote><h4 id="Atomic-乐观锁"><a href="#Atomic-乐观锁" class="headerlink" title="Atomic* 乐观锁"></a>Atomic* <code>乐观锁</code></h4><blockquote><p>由于在多线程操作中无法保证操作的原子性，因此引入了锁和CAS。<br><code>AtomicStampedReference</code>&#x2F;<code>AtomicMarkableReference</code> 用于解决 CAS 的 ABA 问题</p></blockquote><h5 id="单"><a href="#单" class="headerlink" title="单"></a>单</h5><ul><li>AtomicInteger <code>Integer类型</code></li><li>AtomicLong <code>Long类型</code></li><li>AtomicBoolean <code>Boolean类型</code>,内部使用int实现。</li><li>AtomicReference <code>对象类型</code></li></ul><h5 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h5><ul><li>AtomicIntegerArray <code>Integer数组</code></li><li>AtomicLongArray <code>Long数组</code></li><li>AtomicReferenceArray <code>对象数组</code></li></ul><h5 id="对象内字段"><a href="#对象内字段" class="headerlink" title="对象内字段"></a>对象内字段</h5><ul><li>AtomicIntegerFieldUpdater <code>对象内Integer类型字段</code></li><li>AtomicLongFieldUpdater <code>对象内Long类型字段</code></li><li>AtomicReferenceFieldUpdater <code>对象内对象类型字段</code></li></ul><h5 id="根据版本号进行操作"><a href="#根据版本号进行操作" class="headerlink" title="根据版本号进行操作"></a>根据版本号进行操作</h5><ul><li>AtomicStampedReference 每次修改会存储版本号,版本号实现用int。</li><li>AtomicMarkableReference 每次修改会存储版本号,版本号实现用boolean。</li></ul><hr><h2 id="锁和同步"><a href="#锁和同步" class="headerlink" title="锁和同步"></a>锁和同步</h2><ol><li><p>锁和同步的作用<br>保证代码区域在同一时间只运行一个线程去执行,<code>其余线程处于阻塞状态(BLOCKED)</code>。</p></li><li><p>锁和同步的差异。</p></li></ol><ul><li>作用范围, Lock 可以跨方法，synchronized 只能在同一个方法中。</li><li>公平锁, Lock 使用公平锁，synchronized 使用非公平锁。</li><li>可中断，Lock 可以使用<code>lockInterruptibly()</code>中断锁，synchronized 无法中断。</li><li>当 synchronized 无法访问时会被阻塞，Lock 提供<code>tryLock()</code>减少阻塞时间。</li></ul><ol start="3"><li>不释放锁操作</li></ol><ul><li>同步代码中使用<code>Thread.sleep</code>&#x2F;<code>Thread.yield</code>, 线程处于<code>WAITING</code>&#x2F;<code>TIMED_WAITING</code>状态</li><li>同步代码中线程被<code>suspend()</code></li></ul><ol start="4"><li>会释放锁操作</li></ol><ul><li>同步代码被break、return</li><li>同步代码被异常或错误终止</li><li>同步代码块执行结束</li><li>同步代码块被 wait(), 线程处于<code>WAITING</code>&#x2F;<code>TIMED_WAITING</code>状态</li></ul><hr><h2 id="锁Lock的相关实现"><a href="#锁Lock的相关实现" class="headerlink" title="锁Lock的相关实现"></a>锁<code>Lock</code>的相关实现</h2><blockquote><p><code>NonfairSync</code>、<code>FairSync</code></p></blockquote><h3 id="ReentrantLock"><a href="#ReentrantLock" class="headerlink" title="ReentrantLock"></a>ReentrantLock</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 可重入锁</span></span><br><span class="line"><span class="comment"> * 已获取的锁可以不必去重新申请。</span></span><br><span class="line"><span class="comment"> * 例如：</span></span><br><span class="line"><span class="comment"> * synchronized(lock)&#123;</span></span><br><span class="line"><span class="comment"> *     synchronized(lock)&#123;</span></span><br><span class="line"><span class="comment"> *         //..</span></span><br><span class="line"><span class="comment"> *     &#125;</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">reentrantLock</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ReentrantLock</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ReentrantLock</span>();</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;是否公平锁 %b&quot;</span>, lock.isFair())); <span class="comment">// 是否公平锁 false</span></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 可重入锁, 在同一个线程内不用反复申请锁(只是计数+1)。</span></span><br><span class="line"><span class="comment">     * 如果不同线程会尝试关掉当前线程(interrupt)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    lock.lock();</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;该锁是否已被获取 %b&quot;</span>, lock.isHeldByCurrentThread())); <span class="comment">// 该锁是否已被获取 true</span></span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;是否有线程在等待获取该锁 %b&quot;</span>, lock.hasQueuedThreads())); <span class="comment">// 是否有线程在等待获取该锁 false</span></span><br><span class="line">    lock.lock();</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;该锁是否已被获取 %b&quot;</span>, lock.isHeldByCurrentThread())); <span class="comment">// 该锁是否已被获取 true</span></span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;是否有线程在等待获取该锁 %b&quot;</span>, lock.hasQueuedThreads())); <span class="comment">// 是否有线程在等待获取该锁 false</span></span><br><span class="line">    lock.unlock();</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;该锁是否已被获取 %b&quot;</span>, lock.isHeldByCurrentThread())); <span class="comment">// 该锁是否已被获取 true</span></span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;是否有线程在等待获取该锁 %b&quot;</span>, lock.hasQueuedThreads())); <span class="comment">// 是否有线程在等待获取该锁 false</span></span><br><span class="line">    lock.unlock();</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;该锁是否已被获取 %b&quot;</span>, lock.isHeldByCurrentThread())); <span class="comment">// 该锁是否已被获取 false</span></span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;是否有线程在等待获取该锁 %b&quot;</span>, lock.hasQueuedThreads())); <span class="comment">// 是否有线程在等待获取该锁 false</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="ReentrantReadWriteLock"><a href="#ReentrantReadWriteLock" class="headerlink" title="ReentrantReadWriteLock"></a>ReentrantReadWriteLock</h3><blockquote><p>读写锁</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><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></pre></td><td class="code"><pre><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 读写锁</span></span><br><span class="line"><span class="comment">     * 读锁 &amp; 读锁 之间不会堵塞</span></span><br><span class="line"><span class="comment">     * 写锁 &amp; 读锁/写锁 都会发生堵塞</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">reentrantReadWriteLock</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">ReentrantReadWriteLock</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ReentrantReadWriteLock</span>();</span><br><span class="line">    </span><br><span class="line">        <span class="type">Runnable</span> <span class="variable">rRunable</span> <span class="operator">=</span> () -&gt; &#123;</span><br><span class="line">            lock.readLock().lock();</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;获取 %s锁 %s&quot;</span>, lock.isWriteLocked()?<span class="string">&quot;写&quot;</span>:<span class="string">&quot;读&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;关掉 %s锁 %s&quot;</span>, lock.isWriteLocked()?<span class="string">&quot;写&quot;</span>:<span class="string">&quot;读&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">            lock.readLock().unlock();</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="type">Runnable</span> <span class="variable">wRunable</span> <span class="operator">=</span> () -&gt; &#123;</span><br><span class="line">            lock.writeLock().lock();</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;获取 %s锁 %s&quot;</span>, lock.isWriteLocked()?<span class="string">&quot;写&quot;</span>:<span class="string">&quot;读&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;关掉 %s锁 %s&quot;</span>, lock.isWriteLocked()?<span class="string">&quot;写&quot;</span>:<span class="string">&quot;读&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">            lock.writeLock().unlock();</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">rthread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(rRunable);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">rthread2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(rRunable);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">wthread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(wRunable);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">wthread2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(wRunable);</span><br><span class="line">    </span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 读-&gt;写-&gt;读</span></span><br><span class="line"><span class="comment">         *</span></span><br><span class="line"><span class="comment">         * 获取 读锁 Thread-1</span></span><br><span class="line"><span class="comment">         * 关掉 读锁 Thread-1</span></span><br><span class="line"><span class="comment">         * 获取 写锁 Thread-3</span></span><br><span class="line"><span class="comment">         * 关掉 写锁 Thread-3</span></span><br><span class="line"><span class="comment">         * 获取 读锁 Thread-2</span></span><br><span class="line"><span class="comment">         * 关掉 读锁 Thread-2</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line"><span class="comment">//        System.out.println(&quot;读-&gt;写-&gt;读&quot;);</span></span><br><span class="line"><span class="comment">//        rthread.start();</span></span><br><span class="line"><span class="comment">//        Thread.sleep(100);</span></span><br><span class="line"><span class="comment">//        wthread.start();</span></span><br><span class="line"><span class="comment">//        Thread.sleep(100);</span></span><br><span class="line"><span class="comment">//        rthread2.start();</span></span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 读-&gt;读-&gt;写</span></span><br><span class="line"><span class="comment">         * 获取 读锁 Thread-1</span></span><br><span class="line"><span class="comment">         * 获取 读锁 Thread-2</span></span><br><span class="line"><span class="comment">         * 关掉 读锁 Thread-1</span></span><br><span class="line"><span class="comment">         * 关掉 读锁 Thread-2</span></span><br><span class="line"><span class="comment">         * 获取 写锁 Thread-3</span></span><br><span class="line"><span class="comment">         * 关掉 写锁 Thread-3</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line"><span class="comment">//        System.out.println(&quot;读-&gt;读-&gt;写&quot;);</span></span><br><span class="line"><span class="comment">//        rthread.start();</span></span><br><span class="line"><span class="comment">//        Thread.sleep(100);</span></span><br><span class="line"><span class="comment">//        rthread2.start();</span></span><br><span class="line"><span class="comment">//        Thread.sleep(100);</span></span><br><span class="line"><span class="comment">//        wthread.start();</span></span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 写-&gt;写-&gt;读</span></span><br><span class="line"><span class="comment">         * 获取 写锁 Thread-3</span></span><br><span class="line"><span class="comment">         * 关掉 写锁 Thread-3</span></span><br><span class="line"><span class="comment">         * 获取 写锁 Thread-4</span></span><br><span class="line"><span class="comment">         * 关掉 写锁 Thread-4</span></span><br><span class="line"><span class="comment">         * 获取 读锁 Thread-1</span></span><br><span class="line"><span class="comment">         * 关掉 读锁 Thread-1</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        System.out.println(<span class="string">&quot;写-&gt;写-&gt;读&quot;</span>);</span><br><span class="line">        wthread.start();</span><br><span class="line">        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">        wthread2.start();</span><br><span class="line">        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">        rthread.start();</span><br><span class="line">    </span><br><span class="line"></span><br><span class="line">        Thread.sleep(<span class="number">5000</span>);</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><h3 id="StampedLock"><a href="#StampedLock" class="headerlink" title="StampedLock"></a>StampedLock</h3><blockquote><p>邮票锁, ReentrantReadWriteLock 的升级版<br>写锁、读锁、新增(乐观读锁、锁的转换)</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 邮票锁</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">stampedLock</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    <span class="type">StampedLock</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StampedLock</span>();</span><br><span class="line">    <span class="type">int</span> <span class="variable">demo</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 写锁</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">long</span> <span class="variable">stamp</span> <span class="operator">=</span> lock.writeLock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        demo = <span class="number">1</span>;</span><br><span class="line">    &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">        lock.unlockWrite(stamp);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 读锁</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    stamp = lock.readLock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        System.out.println(demo);</span><br><span class="line">    &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">        lock.unlockRead(stamp);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 乐观读锁</span></span><br><span class="line"><span class="comment">     * 一般情况读写并不冲突，但也可以通过检测申请乐观读锁后是否有写锁被申请，如果有可以再进行重新申请为读锁。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    stamp = lock.tryOptimisticRead();</span><br><span class="line">    <span class="keyword">if</span> (!lock.validate(stamp)) &#123;</span><br><span class="line">        stamp = lock.readLock();</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            System.out.println(demo);</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            lock.unlockRead(stamp);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        System.out.println(demo);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="Synchronized"><a href="#Synchronized" class="headerlink" title="Synchronized"></a>Synchronized</h2><h3 id="使用级别"><a href="#使用级别" class="headerlink" title="使用级别"></a>使用级别</h3><ul><li>实例对象函数<code>this锁</code></li><li>静态函数<code>class锁</code></li><li>代码块<code>指定的锁</code></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SynchronizedTest</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 当线程1同步块正在执行，线程2处于阻塞状态(BLOCKED)</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">state</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">Runnable</span> <span class="variable">runnable</span> <span class="operator">=</span> () -&gt; &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (SynchronizedTest.class) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    <span class="comment">// 不会让出锁</span></span><br><span class="line">                    Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(runnable);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(runnable);</span><br><span class="line">        thread.start();</span><br><span class="line">        thread2.start();</span><br><span class="line">        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;阻塞的线程2(%s) 状态: %s&quot;</span>, thread2.getName(), thread2.getState())); <span class="comment">// 阻塞的线程2(Thread-2) 状态: BLOCKED</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 多个同步块共用一把锁, 当线程1同步块1正在执行，线程2在同步块2处于阻塞状态(BLOCKED)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">multiSync</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="keyword">class</span> <span class="title class_">Demo</span> &#123;</span><br><span class="line">            <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">Object</span> <span class="variable">LOCK</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line">            </span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sync1</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">                <span class="keyword">synchronized</span> (LOCK) &#123;</span><br><span class="line">                    Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sync2</span><span class="params">()</span> &#123;</span><br><span class="line">                <span class="keyword">synchronized</span> (LOCK) &#123;</span><br><span class="line">                    System.out.println(<span class="string">&quot;执行中..&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="type">Demo</span> <span class="variable">demo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Demo</span>();</span><br><span class="line">        </span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                demo.sync1();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(demo::sync2);</span><br><span class="line">        thread.start();</span><br><span class="line">        thread2.start();</span><br><span class="line">        </span><br><span class="line">        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;阻塞的线程2(%s) 状态: %s&quot;</span>, thread2.getName(), thread2.getState())); <span class="comment">// 阻塞的线程2(Thread-2) 状态: BLOCKED</span></span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 死锁</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">deadlock</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">Object</span> <span class="variable">LOCK</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line">        <span class="type">Object</span> <span class="variable">LOCK2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line">        </span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (LOCK) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    Thread.sleep(<span class="number">10</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">synchronized</span> (LOCK2) &#123;</span><br><span class="line">                    ;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (LOCK2) &#123;</span><br><span class="line">                <span class="keyword">synchronized</span> (LOCK) &#123;</span><br><span class="line">                    ;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        thread.start();</span><br><span class="line">        thread2.start();</span><br><span class="line">        </span><br><span class="line">        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="type">boolean</span> <span class="variable">b</span> <span class="operator">=</span> thread.getState().equals(Thread.State.BLOCKED) &amp;&amp; thread2.getState().equals(Thread.State.BLOCKED);</span><br><span class="line">        <span class="keyword">if</span> (b) &#123;</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;%s 和 %s 死锁&quot;</span>, thread.getName(), thread2.getName()));</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;未发生死锁&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// Thread-1 和 Thread-2 死锁</span></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;关于Java多线程-可见性、CAS、AQS、锁&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="多线程" scheme="https://hocg.in/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>关于Java-Unsafe/LockSupport</title>
    <link href="https://hocg.in/2018/03/02/%E5%85%B3%E4%BA%8EJava-Unsafe:LockSupport/"/>
    <id>https://hocg.in/2018/03/02/%E5%85%B3%E4%BA%8EJava-Unsafe:LockSupport/</id>
    <published>2018-03-02T10:02:39.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>关于Java Unsafe&#x2F;LockSupport</p><span id="more"></span><h2 id="Unsafe"><a href="#Unsafe" class="headerlink" title="Unsafe"></a>Unsafe</h2><blockquote><p>一个高效底层函数，可以实现内存管理、对象实例化(不通过构造函数)、操作函数+类+变量(通过使用地址)、多线程同步(挂起<code>锁</code>、CAS)、挂起和恢复、数组、内存屏障。</p></blockquote><h3 id="具体实践代码"><a href="#具体实践代码" class="headerlink" title="具体实践代码"></a>具体实践代码</h3><blockquote><p>Unsafe 中在高并发和高性能的场景下具有显著的效果。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> in.hocg.lock;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.junit.jupiter.api.Test;</span><br><span class="line"><span class="keyword">import</span> sun.misc.Unsafe;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Field;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Created by hocgin on 2018/3/2.</span></span><br><span class="line"><span class="comment"> * email: hocgin@gmail.com</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UnsafeTest</span> &#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">Demo</span> &#123;</span><br><span class="line">        <span class="keyword">private</span> Integer integer;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">static</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;static&#123;&#125;&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;&#123;&#125;&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">public</span> <span class="title function_">Demo</span><span class="params">()</span> &#123;</span><br><span class="line">            integer = <span class="number">0</span>;</span><br><span class="line">            System.out.println(<span class="string">&quot;Demo()&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">public</span> Integer <span class="title function_">getInteger</span><span class="params">()</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;getInteger()&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> integer;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setInteger</span><span class="params">(Integer integer)</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;setInteger()&quot;</span>);</span><br><span class="line">            <span class="built_in">this</span>.integer = integer;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使用 Unsafe 创建对象，不会调用构造函数。</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> NoSuchFieldException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalAccessException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InstantiationException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">instantiation</span><span class="params">()</span> <span class="keyword">throws</span> NoSuchFieldException, IllegalAccessException, InstantiationException &#123;</span><br><span class="line">        <span class="type">Demo</span> <span class="variable">o</span> <span class="operator">=</span> ((Demo) getUnsafe().allocateInstance(Demo.class));</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;hashCode:: %d&quot;</span>, o.hashCode()));</span><br><span class="line">        <span class="comment">// 此处会打印 &quot;static&#123;&#125;&quot; 因此仍然会执行静态代码块内容</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使用 Unsafe 修改私有字段</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">altering</span><span class="params">()</span> <span class="keyword">throws</span> NoSuchFieldException, IllegalAccessException &#123;</span><br><span class="line">        <span class="type">Demo</span> <span class="variable">demo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Demo</span>();</span><br><span class="line">        <span class="type">Field</span> <span class="variable">field</span> <span class="operator">=</span> demo.getClass().getDeclaredField(<span class="string">&quot;integer&quot;</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="type">Unsafe</span> <span class="variable">unsafe</span> <span class="operator">=</span> getUnsafe();</span><br><span class="line">        unsafe.putObject(demo, unsafe.objectFieldOffset(field), <span class="number">1</span>);</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;getInteger() = %d&quot;</span>, demo.getInteger()));</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使用 Unsafe 抛出异常</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> NoSuchFieldException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalAccessException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">throwing</span><span class="params">()</span> <span class="keyword">throws</span> NoSuchFieldException, IllegalAccessException &#123;</span><br><span class="line">        getUnsafe().throwException(<span class="keyword">new</span> <span class="title class_">NullPointerException</span>());</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 分配一块GC无法管理的内存区域</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">memory</span><span class="params">()</span> <span class="keyword">throws</span> NoSuchFieldException, IllegalAccessException &#123;</span><br><span class="line">        <span class="type">Unsafe</span> <span class="variable">unsafe</span> <span class="operator">=</span> getUnsafe();</span><br><span class="line">        </span><br><span class="line">        <span class="type">int</span> <span class="variable">size</span> <span class="operator">=</span> <span class="number">1024</span>;</span><br><span class="line">        <span class="comment">// 分配内存地址</span></span><br><span class="line">        <span class="type">long</span> <span class="variable">address</span> <span class="operator">=</span> unsafe.allocateMemory(size * <span class="number">1</span>);</span><br><span class="line">        <span class="comment">// 写入</span></span><br><span class="line">        unsafe.putInt(address + <span class="number">4</span> * <span class="number">1</span>, <span class="number">100</span>);</span><br><span class="line">        <span class="comment">// 读取</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> unsafe.getInt(address + <span class="number">4</span> * <span class="number">1</span>);</span><br><span class="line">        System.out.println(i);</span><br><span class="line">    </span><br><span class="line">        <span class="comment">// 释放内存</span></span><br><span class="line">        unsafe.freeMemory(address);</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 进行CAS操作，单纯使用 Java 并不能有效的解决CAS操作, 其主要通过 Unsafe 使用硬件级别来解决CAS操作</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> NoSuchFieldException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalAccessException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">cas</span><span class="params">()</span> <span class="keyword">throws</span> NoSuchFieldException, IllegalAccessException &#123;</span><br><span class="line">        <span class="type">Unsafe</span> <span class="variable">unsafe</span> <span class="operator">=</span> getUnsafe();</span><br><span class="line">        <span class="type">Demo</span> <span class="variable">demo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Demo</span>();</span><br><span class="line">        <span class="type">Field</span> <span class="variable">field</span> <span class="operator">=</span> demo.getClass().getDeclaredField(<span class="string">&quot;integer&quot;</span>);</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * compareAndSwapXXX</span></span><br><span class="line"><span class="comment">         * 参数</span></span><br><span class="line"><span class="comment">         * 1. 指定对象</span></span><br><span class="line"><span class="comment">         * 2. 字段的偏移地址</span></span><br><span class="line"><span class="comment">         * 3. 当前值</span></span><br><span class="line"><span class="comment">         * 4. 期望值</span></span><br><span class="line"><span class="comment">         * 返回值</span></span><br><span class="line"><span class="comment">         *   &quot;认为的旧值&quot;==&quot;实际旧值&quot;,修改成&quot;期望值&quot;再返回 True: 修改成功</span></span><br><span class="line"><span class="comment">         *   &quot;认为的旧值&quot;!=&quot;实际旧值&quot;,直接返回 False: 修改失败</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="type">boolean</span> state; <span class="comment">// CAS 状态</span></span><br><span class="line">        <span class="type">Integer</span> <span class="variable">integer1</span> <span class="operator">=</span> <span class="number">0</span>; <span class="comment">// 认为的旧值</span></span><br><span class="line">        <span class="type">Integer</span> <span class="variable">integer2</span> <span class="operator">=</span> demo.getInteger(); <span class="comment">// 实际旧值</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">o1</span> <span class="operator">=</span> <span class="number">1</span>; <span class="comment">// 期望值</span></span><br><span class="line">        <span class="keyword">while</span> (!(state = unsafe.compareAndSwapObject(demo, unsafe.objectFieldOffset(field), integer1, o1))) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;再次尝试修改&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;1 .CAS State: %b, 认为的旧值 %d, 实际旧值 %d, 期望值 %d&quot;</span>, state, integer1, integer2, o1));</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">        integer2 = demo.getInteger(); <span class="comment">// 实际旧值</span></span><br><span class="line">        state = unsafe.compareAndSwapObject(demo, unsafe.objectFieldOffset(field), integer1, o1);</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;2 .CAS State: %b, 认为的旧值 %d, 实际旧值 %d, 期望值 %d&quot;</span>, state, integer1, integer2, o1));</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 利用OS底层的方式来实现挂起，相较于Object.wait()拥有更好的性能</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> NoSuchFieldException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalAccessException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">park</span><span class="params">()</span> <span class="keyword">throws</span> NoSuchFieldException, IllegalAccessException, InterruptedException &#123;</span><br><span class="line">        <span class="type">Unsafe</span> <span class="variable">unsafe</span> <span class="operator">=</span> getUnsafe();</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="comment">/**</span></span><br><span class="line"><span class="comment">             * 参数</span></span><br><span class="line"><span class="comment">             * 1. isAbsolute, 是否为绝对时间。</span></span><br><span class="line"><span class="comment">             * 2. time, 第一个参数(isAbsolute)为 True 时该参数应为纳秒, False 时该参数应为毫秒。0为无线等待，直到unpark。</span></span><br><span class="line"><span class="comment">             */</span></span><br><span class="line">            unsafe.park(<span class="literal">false</span>, <span class="number">0</span>); <span class="comment">// 挂起 -&gt; WAITING</span></span><br><span class="line">        &#125;);</span><br><span class="line">    </span><br><span class="line">        thread.start();</span><br><span class="line">        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;线程 %s 状态 %s&quot;</span>, thread.getName(), thread.getState()));</span><br><span class="line">    </span><br><span class="line">        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">        unsafe.unpark(thread);</span><br><span class="line">        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;线程 %s 状态 %s&quot;</span>, thread.getName(), thread.getState()));</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Basic</span></span><br><span class="line"><span class="comment">     * Unsafe unsafe = Unsafe.getUnsafe();</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalAccessException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> NoSuchFieldException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Unsafe <span class="title function_">getUnsafe</span><span class="params">()</span> <span class="keyword">throws</span> IllegalAccessException, NoSuchFieldException &#123;</span><br><span class="line">        <span class="type">Field</span> <span class="variable">f</span> <span class="operator">=</span> Unsafe.class.getDeclaredField(<span class="string">&quot;theUnsafe&quot;</span>);</span><br><span class="line">        f.setAccessible(<span class="literal">true</span>);</span><br><span class="line">        <span class="keyword">return</span> (Unsafe) f.get(<span class="literal">null</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="LockSupport"><a href="#LockSupport" class="headerlink" title="LockSupport"></a>LockSupport</h2><blockquote><p>其本质是<code>Unsafe</code>的薄封装。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">park</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    <span class="type">Thread</span> <span class="variable">thread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 进行挂起</span></span><br><span class="line"><span class="comment">         * 本质使用 UNSAFE.park(false, 0L);</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        LockSupport.park();</span><br><span class="line">    &#125;);</span><br><span class="line">    thread.start();</span><br><span class="line"></span><br><span class="line">    </span><br><span class="line">    Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;挂起线程状态 %s&quot;</span>, thread.getState())); <span class="comment">// WAITING</span></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 进行解除</span></span><br><span class="line"><span class="comment">     * 本质使用 UNSAFE.unpark(thread)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    LockSupport.unpark(thread);</span><br><span class="line">    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;解除挂起线程状态 %s&quot;</span>, thread.getState())); <span class="comment">// TERMINATED</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">blocker</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    <span class="type">Thread</span> <span class="variable">thread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(()-&gt;&#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 线程内部有个 parkBlocker 字段, LockSupport 本质上使用 Unsafe 进行内存修改。</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        LockSupport.park(<span class="string">&quot;sdas&quot;</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">    thread.start();</span><br><span class="line">    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;挂起 %s&quot;</span>, LockSupport.getBlocker(thread))); <span class="comment">// 挂起 sdas</span></span><br><span class="line">    </span><br><span class="line">    LockSupport.unpark(thread);</span><br><span class="line">    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;解除挂起 %s&quot;</span>, LockSupport.getBlocker(thread))); <span class="comment">// 解除挂起 null</span></span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="阻塞和解除阻塞"><a href="#阻塞和解除阻塞" class="headerlink" title="阻塞和解除阻塞"></a>阻塞和解除阻塞</h3><blockquote><p>总结: 使用<code>LockSupport</code>更具有灵活性。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Object</span> <span class="variable">LOCK</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * notifyAll 实现</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">notifyAll2</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    <span class="type">Runnable</span> <span class="variable">runnable</span> <span class="operator">=</span> () -&gt; &#123;</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;开始运行 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">        <span class="keyword">synchronized</span> (LOCK) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                LOCK.wait();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;解除锁 %s&quot;</span>, Thread.currentThread().getName()));</span><br><span class="line">    &#125;;</span><br><span class="line">    CompletableFuture.allOf(CompletableFuture.runAsync(runnable),</span><br><span class="line">            CompletableFuture.runAsync(runnable), CompletableFuture.runAsync(runnable), CompletableFuture.runAsync(runnable));</span><br><span class="line">    </span><br><span class="line">    Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">    <span class="keyword">synchronized</span> (LOCK) &#123;</span><br><span class="line">        LOCK.notify();</span><br><span class="line">        System.out.println(<span class="string">&quot;通知完毕&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * unpark 通知所有需自己实现</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> InterruptedException</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">unparkAll</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    List&lt;Thread&gt; threads = Collections.synchronizedList(<span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;());</span><br><span class="line">    </span><br><span class="line">    <span class="type">Runnable</span> <span class="variable">runnable</span> <span class="operator">=</span> () -&gt; &#123;</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread</span> <span class="operator">=</span> Thread.currentThread();</span><br><span class="line">        threads.add(thread);</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;开始运行 %s&quot;</span>, thread.getName()));</span><br><span class="line">        LockSupport.park();</span><br><span class="line">        System.out.println(String.format(<span class="string">&quot;解除锁 %s&quot;</span>, thread.getName()));</span><br><span class="line">    &#125;;</span><br><span class="line">    CompletableFuture&lt;Void&gt; future = CompletableFuture.allOf(CompletableFuture.runAsync(runnable),</span><br><span class="line">            CompletableFuture.runAsync(runnable), CompletableFuture.runAsync(runnable), CompletableFuture.runAsync(runnable));</span><br><span class="line"></span><br><span class="line">    Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">    <span class="keyword">for</span> (Thread thread : threads) &#123;</span><br><span class="line">        LockSupport.unpark(thread);</span><br><span class="line">    &#125;</span><br><span class="line">    System.out.println(<span class="string">&quot;通知完毕&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="park-x2F-unpark-与-wait-x2F-notify-总结"><a href="#park-x2F-unpark-与-wait-x2F-notify-总结" class="headerlink" title="park&#x2F;unpark 与 wait&#x2F;notify 总结"></a>park&#x2F;unpark 与 wait&#x2F;notify 总结</h3><p>相比于使用 <code>Object.wait</code>&#x2F;<code>Object.notify</code>,<code>LockSupport.unpark</code>&#x2F;<code>LockSupport.park</code> 更具有灵活性。</p><ol><li>不局限于同步块内</li><li>灵活的 API(例如时间)</li><li>可指定唤醒(当多个进入wait时Object.notify是随机唤醒其中一个)。</li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;关于Java Unsafe&amp;#x2F;LockSupport&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="多线程" scheme="https://hocg.in/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
    
    <category term="锁" scheme="https://hocg.in/tags/%E9%94%81/"/>
    
  </entry>
  
  <entry>
    <title>关于Java并发-线程</title>
    <link href="https://hocg.in/2018/02/27/%E5%85%B3%E4%BA%8EJava%E5%A4%9A%E7%BA%BF%E7%A8%8B-%E7%BA%BF%E7%A8%8B/"/>
    <id>https://hocg.in/2018/02/27/%E5%85%B3%E4%BA%8EJava%E5%A4%9A%E7%BA%BF%E7%A8%8B-%E7%BA%BF%E7%A8%8B/</id>
    <published>2018-02-27T01:13:39.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>关于Java并发-线程</p><span id="more"></span><h2 id="并发和并行"><a href="#并发和并行" class="headerlink" title="并发和并行"></a>并发和并行</h2><p>并行: 多核同时执行<br>并发: 单核切换执行</p><p><img src="http://cdn.hocgin.top/v2-674f0d37fca4fac1bd2df28a2b78e633_hd.jpg" alt="v2-674f0d37fca4fac1bd2df28a2b78e633_hd.jpg"></p><hr><h2 id="线程"><a href="#线程" class="headerlink" title="线程"></a>线程</h2><h3 id="线程状态Thread-State"><a href="#线程状态Thread-State" class="headerlink" title="线程状态Thread.State"></a>线程状态<code>Thread.State</code></h3><blockquote><p><code>@since 1.5</code><br>关于 Java Thread 状态不得不说的故事(网络上各种版本)..</p></blockquote><p><strong>线程的状态</strong><br><img src="http://www.baeldung.com/wp-content/uploads/2018/02/Life_cycle_of_a_Thread_in_Java.jpg" alt="线程状态图片"><br><a href="http://www.baeldung.com/java-thread-lifecycle">原文URL</a></p><h3 id="多线程操作"><a href="#多线程操作" class="headerlink" title="多线程操作"></a>多线程操作</h3><blockquote><p>关于<code>wait</code>和<code>notify</code>此处涉及到线程中的几个状态，请勿混淆。</p></blockquote><p><strong>使用<code>wait</code>&#x2F;<code>notify</code>对线程进行操作</strong><br><img src="http://www.baeldung.com/wp-content/uploads/2018/02/Java_-_Wait_and_Notify.png" alt="使用wait/notify对线程进行操作"><br><a href="http://www.baeldung.com/java-wait-notify">使用wait&#x2F;notify对线程进行操作</a></p><h3 id="可能的误区"><a href="#可能的误区" class="headerlink" title="可能的误区"></a>可能的误区</h3><ol><li><p>子线程被关闭，子线程所开启的子线程(子子线程)会不会被关闭？<br>答案: 不会的, 子线程的子线程本质上和子线程是同一等级的并不会被其影响。</p></li><li><p>守护线程什么情况会被关闭？<br>答案: 1. 守护线程执行完(自然关闭)。 2.所有用户线程的关闭(强行关闭)</p></li><li><p>什么是守护线程？<br>答案: 当线程<code>t.setDaemon(true)</code>该线程即为守护线程。铛铛铛，最出名的守护线程GC。</p></li><li><p>用户线程 和 守护线程 的区别？<br>答案: <code>守护线程[setDaemon(true)]</code>和<code>用户线程</code>大体并没啥区别, 但是守护线程的生命周期是随着所有用户线程的关闭而退出的。</p></li><li><p>如何杀死一个Java线程？<br>答案: Java已经不推荐使用<code>stop</code>进行线程的关闭了。如果线程是那种持久型操作类型的，建议开辟一个守护类型的线程进行回收(想法参照Go)。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">interrupt</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    <span class="type">Thread</span> <span class="variable">thread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">while</span> (!Thread.currentThread().isInterrupted()) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;Do something&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    thread.start();</span><br><span class="line">    </span><br><span class="line">    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;线程 %s 状态 %s&quot;</span>, thread.getName(), thread.getState()));</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 线程 RUNNABLE 状态会标记为关闭，并不进行关闭。</span></span><br><span class="line"><span class="comment">     * 线程 其他 状态会标记并进行关闭。</span></span><br><span class="line"><span class="comment">     * - 已经不推荐使用 thread.stop(); 可能会引起资源问题。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    thread.interrupt();</span><br><span class="line">    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">    System.out.println(String.format(<span class="string">&quot;线程 %s 状态 %s&quot;</span>, thread.getName(), thread.getState()));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><hr><h2 id="线程池"><a href="#线程池" class="headerlink" title="线程池"></a>线程池</h2><h3 id="前置"><a href="#前置" class="headerlink" title="前置"></a>前置</h3><ul><li>Runable 无返回值</li><li>Callable 有返回值</li><li>Future 返回结果</li></ul><h3 id="newCachedThreadPool"><a href="#newCachedThreadPool" class="headerlink" title="newCachedThreadPool()"></a>newCachedThreadPool()</h3><blockquote><p>创建一个可缓存的线程池，其指定线程池中线程的存活时间，默认为 60s。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> ExecutorService <span class="title function_">newCachedThreadPool</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(<span class="number">0</span>, Integer.MAX_VALUE,</span><br><span class="line">                                  <span class="number">60L</span>, TimeUnit.SECONDS,</span><br><span class="line">                                  <span class="keyword">new</span> <span class="title class_">SynchronousQueue</span>&lt;Runnable&gt;());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>这边源码有注释:当你想实现一些缓存相关的细节(如超时时间)，应该自己使用<code>ThreadPoolExecutor</code>的构造函数来创建。</p></blockquote><h3 id="newSingleThreadExecutor"><a href="#newSingleThreadExecutor" class="headerlink" title="newSingleThreadExecutor"></a>newSingleThreadExecutor</h3><blockquote><p>创建一个新的单线程Executor，其指定线程池中线程最大数量为1。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> ExecutorService <span class="title function_">newSingleThreadExecutor</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">FinalizableDelegatedExecutorService</span></span><br><span class="line">        (<span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(<span class="number">1</span>, <span class="number">1</span>,</span><br><span class="line">                                <span class="number">0L</span>, TimeUnit.MILLISECONDS,</span><br><span class="line">                                <span class="keyword">new</span> <span class="title class_">LinkedBlockingQueue</span>&lt;Runnable&gt;()));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><ol><li>此处为何使用<code>门面模式</code>呢？注释写明只暴露<code>ExecutorService</code>接口的方法, 应该是为了防止强制使用<code>ThreadPoolExecutor</code>相关函数。</li><li>相比于<code>newFixedThreadPool(1)</code>, 该函数保证不会被重新分配到其他的线程。</li></ol></blockquote><h3 id="newFixedThreadPool"><a href="#newFixedThreadPool" class="headerlink" title="newFixedThreadPool"></a>newFixedThreadPool</h3><blockquote><p>创建一个固定大小的线程池</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> ExecutorService <span class="title function_">newFixedThreadPool</span><span class="params">(<span class="type">int</span> nThreads)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(nThreads, nThreads,</span><br><span class="line">                                  <span class="number">0L</span>, TimeUnit.MILLISECONDS,</span><br><span class="line">                                  <span class="keyword">new</span> <span class="title class_">LinkedBlockingQueue</span>&lt;Runnable&gt;());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注释中说明: 提交的任务线程将一直存在，直到使用 ExecutorService#shutdown 进行退出</p></blockquote><h3 id="newScheduledThreadPool"><a href="#newScheduledThreadPool" class="headerlink" title="newScheduledThreadPool"></a>newScheduledThreadPool</h3><blockquote><p>创建一个固定大小且可定时的线程池</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> ScheduledExecutorService <span class="title function_">newScheduledThreadPool</span><span class="params">(<span class="type">int</span> corePoolSize)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ScheduledThreadPoolExecutor</span>(corePoolSize);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="newSingleThreadScheduledExecutor"><a href="#newSingleThreadScheduledExecutor" class="headerlink" title="newSingleThreadScheduledExecutor"></a>newSingleThreadScheduledExecutor</h3><blockquote><p>创建一个大小为1且可定时的线程池</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> ScheduledExecutorService <span class="title function_">newSingleThreadScheduledExecutor</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">DelegatedScheduledExecutorService</span></span><br><span class="line">        (<span class="keyword">new</span> <span class="title class_">ScheduledThreadPoolExecutor</span>(<span class="number">1</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>同样使用了<code>门面模式</code></p></blockquote><h3 id="newWorkStealingPool-并行"><a href="#newWorkStealingPool-并行" class="headerlink" title="newWorkStealingPool 并行"></a>newWorkStealingPool <code>并行</code></h3><blockquote><p>创建一个并行线程池(并行数目默认为:系统可用线程数目)<br><code>@since 1.8</code></p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> ExecutorService <span class="title function_">newWorkStealingPool</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ForkJoinPool</span></span><br><span class="line">        (Runtime.getRuntime().availableProcessors(),</span><br><span class="line">         ForkJoinPool.defaultForkJoinWorkerThreadFactory,</span><br><span class="line">         <span class="literal">null</span>, <span class="literal">true</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="Fork-x2F-Join-并行"><a href="#Fork-x2F-Join-并行" class="headerlink" title="Fork&#x2F;Join 并行"></a>Fork&#x2F;Join <code>并行</code></h2><blockquote><p>使用并行进行操作<br><code>@since 1.7</code></p></blockquote><h3 id="相关类-x2F-接口说明"><a href="#相关类-x2F-接口说明" class="headerlink" title="相关类&#x2F;接口说明"></a>相关类&#x2F;接口说明</h3><ul><li>ForkJoinTask 顶层接口, 其实现了<code>Future</code>。<ul><li>RecursiveTask 有返回值</li><li>RecursiveAction 无返回值</li></ul></li><li>ForkJoinPool 类似<code>Executor</code></li></ul><h4 id="案例"><a href="#案例" class="headerlink" title="案例"></a>案例</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* Main.java</span></span><br><span class="line"><span class="comment">* 响应结果:</span></span><br><span class="line"><span class="comment">*   TASK:ForkJoinPool.commonPool-worker-1</span></span><br><span class="line"><span class="comment">*   TASK:ForkJoinPool.commonPool-worker-1</span></span><br><span class="line"><span class="comment">*   TASK:ForkJoinPool.commonPool-worker-2</span></span><br><span class="line"><span class="comment">*   TASK:ForkJoinPool.commonPool-worker-1</span></span><br><span class="line"><span class="comment">*   有效值 4</span></span><br><span class="line"><span class="comment">*   TASK:ForkJoinPool.commonPool-worker-2</span></span><br><span class="line"><span class="comment">*   有效值 5</span></span><br><span class="line"><span class="comment">*   TASK:ForkJoinPool.commonPool-worker-1</span></span><br><span class="line"><span class="comment">*   有效值 6</span></span><br><span class="line"><span class="comment">*   TASK:ForkJoinPool.commonPool-worker-1</span></span><br><span class="line"><span class="comment">*   有效值 7</span></span><br><span class="line"><span class="comment">*   22</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">forkJoinPool</span><span class="params">()</span> <span class="keyword">throws</span> ExecutionException, InterruptedException &#123;</span><br><span class="line">        <span class="type">ForkJoinPool</span> <span class="variable">forkJoinPool</span> <span class="operator">=</span> ForkJoinPool.commonPool();</span><br><span class="line">        <span class="type">IRecursiveTask</span> <span class="variable">iRecursiveTask</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">IRecursiveTask</span>();</span><br><span class="line">        ForkJoinTask&lt;Integer&gt; task = forkJoinPool.submit(iRecursiveTask);</span><br><span class="line">        System.out.println(task.get());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* IRecursiveTask.java</span></span><br><span class="line"><span class="comment">* .fork() 进行任务分裂，并使用线程进行执行</span></span><br><span class="line"><span class="comment">* .join() 等待执行完成并获取结果</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">IRecursiveTask</span> <span class="keyword">extends</span> <span class="title class_">RecursiveTask</span>&lt;Integer&gt; &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">AtomicInteger</span> <span class="variable">FLAG</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AtomicInteger</span>(<span class="number">0</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> Integer <span class="title function_">compute</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;TASK:&quot;</span> + Thread.currentThread().getName());</span><br><span class="line">        FLAG.addAndGet(<span class="number">1</span>);</span><br><span class="line">        <span class="keyword">if</span> (FLAG.get() &gt; <span class="number">3</span>) &#123;</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;有效值 %d&quot;</span>, FLAG.get()));</span><br><span class="line">            <span class="keyword">return</span> FLAG.get();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 为什么不用 this.fork()？</span></span><br><span class="line">        <span class="comment">// this.fork() 返回的是 this</span></span><br><span class="line">        <span class="type">Integer</span> <span class="variable">join1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">IRecursiveTask</span>().fork().join();</span><br><span class="line">        <span class="type">Integer</span> <span class="variable">join2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">IRecursiveTask</span>().fork().join();</span><br><span class="line">        <span class="keyword">return</span> join1 + join2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><h2 id="CompletableFuture-x2F-CompletionStage-异步-并行"><a href="#CompletableFuture-x2F-CompletionStage-异步-并行" class="headerlink" title="CompletableFuture&#x2F;CompletionStage 异步+并行"></a>CompletableFuture&#x2F;CompletionStage <code>异步+并行</code></h2><blockquote><p>相比于<code>1.7</code>进行了更简便、友好的封装，并增加了异步通知的功能，摆脱了阻塞问题。<br><code>@since 1.8</code></p></blockquote><h3 id="CompletableFuture"><a href="#CompletableFuture" class="headerlink" title="CompletableFuture"></a>CompletableFuture</h3><blockquote><ol><li><code>CompletableFuture</code>实现了<code>CompletionStage</code>用于进行异步并行,并提供函数让多个<code>CompletionStage</code>可以进行组合操作和或操作。</li></ol></blockquote><h3 id="静态函数-返回CompletionStage"><a href="#静态函数-返回CompletionStage" class="headerlink" title="静态函数, 返回CompletionStage"></a>静态函数, 返回<code>CompletionStage</code></h3><ul><li>CompletableFuture.anyOf 任意一个执行完成</li><li>CompletableFuture.allOf 所有执行完成</li><li>CompletableFuture.supplyAsync 执行单个异步,有返回值(默认使用:ForkJoinPool#commonPool())。</li><li>CompletableFuture.runAsync 执行单个异步,无返回值</li><li>CompletableFuture.completedFuture 设定结果</li></ul><h3 id="CompletionStage-函数"><a href="#CompletionStage-函数" class="headerlink" title="CompletionStage 函数"></a>CompletionStage 函数</h3><ul><li>thenXXX 流的流向(等待上一步执行完成)<ul><li>thenApplyXXX 进行输入的转换(Apply：<code>有输入有输出</code>)</li><li>thenRunXXX 对上一个结果不关心，也没有返回值(Run：<code>无输入无输出</code>)</li><li>thenAcceptXXX 进行输入对处理(Accept：<code>有输入无输出</code>)</li><li>thenAcceptBothXXX(CompletionStage,BiConsumer) 加入CompletionStage, 进行指定处理(<code>组合操作</code>，<code>有输入无输出</code>)。</li><li>thenCombineXXX(CompletionStage,BiFunction) 加入CompletionStage, 进行指定处理(<code>组合操作</code>，<code>有输入有输出</code>)。</li></ul></li><li>runAfterXXX 运行之后<ul><li>runAfterBothXXX(CompletionStage, Runnable) 加入CompletionStage, 并在其运行后指定执行(<code>组合操作</code>，<code>无输入无输出</code>)。</li><li>runAfterEither(CompletionStage, Runnable) (<code>或操作</code>)</li></ul></li><li>完成<ul><li>whenCompleteXXX 完成之后处理。(有输入无输出)</li><li>handleXXX 完成之后处理。(有输入有输出)</li></ul></li><li>异常处理<ul><li>exceptionally 异常处理。</li></ul></li><li>其他<ul><li>.complete() &#x2F;&#x2F; 立即结束并返回指定的结果</li><li>.completeExceptionally() &#x2F;&#x2F;立即异常结束</li></ul></li></ul><blockquote><p>说明: </p><ol><li><code>xxxEither</code> 加入CompletionStage进行OR操作(与之前的进行对比),取最先返回的结果取其结果值。  </li><li><code>xxxAsync</code> 都是异步执行</li></ol></blockquote><hr><h2 id="稍微提一下-线程组"><a href="#稍微提一下-线程组" class="headerlink" title="稍微提一下,线程组"></a>稍微提一下,线程组</h2><blockquote><p>为管理 Thread 而存在的，可以进行批量标记、检查。</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;关于Java并发-线程&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="多线程" scheme="https://hocg.in/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>日志系统ELK在Spring Boot上的初步集成</title>
    <link href="https://hocg.in/2018/01/22/%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F%20ELK%20%E5%9C%A8%20Spring%20Boot%20%E4%B8%8A%E7%9A%84%E5%88%9D%E6%AD%A5%E9%9B%86%E6%88%90/"/>
    <id>https://hocg.in/2018/01/22/%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F%20ELK%20%E5%9C%A8%20Spring%20Boot%20%E4%B8%8A%E7%9A%84%E5%88%9D%E6%AD%A5%E9%9B%86%E6%88%90/</id>
    <published>2018-01-22T16:53:00.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>日志系统 ELK 在 Spring Boot 上的初步集成 😋</p><span id="more"></span><h2 id="ELK"><a href="#ELK" class="headerlink" title="ELK"></a>ELK</h2><blockquote><p>Elasticsearch + Logstash + Kibana，一个比较流行的日志系统。当然，你也可以尝试使用阿里云。如果钱多的话:)</p></blockquote><h3 id="Logstash"><a href="#Logstash" class="headerlink" title="Logstash"></a>Logstash</h3><blockquote><p>日志搬运, 可以指定从 Redis&#x2F;Log4j..处获取日志信息，然后进行过滤，再提交给 <code>Elasticsearch</code> 进行分析。</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 &amp; 启动</span></span><br><span class="line">brew install logstash</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">brew services restart logstash</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./bin/logstash -f config/logstash.conf</span></span><br></pre></td></tr></table></figure><h3 id="Elasticsearch"><a href="#Elasticsearch" class="headerlink" title="Elasticsearch"></a>Elasticsearch</h3><blockquote><p>日志存储 &#x2F; 查询 &#x2F; 分析</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 &amp; 启动</span></span><br><span class="line">brew install elasticsearch</span><br><span class="line">brew services restart elasticsearch</span><br></pre></td></tr></table></figure><p>如果你想直接查看、操作或者研究 <code>elasticsearch</code> 存储的内容，可以考虑使用 <code>elasticsearch-head</code> 进行操作。</p><h4 id="UI-操作界面"><a href="#UI-操作界面" class="headerlink" title="UI 操作界面"></a>UI 操作界面</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">git clone git://github.com/mobz/elasticsearch-head.git</span><br><span class="line">cd elasticsearch-head</span><br><span class="line">npm install</span><br><span class="line">npm run start</span><br><span class="line">open http://localhost:9100</span><br></pre></td></tr></table></figure><p>如果 Elasticsearch 安装了 X-Path 那么需要在配置文件中(<code>elasticsearch.yml</code>), 加入:</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">http.cors.enabled:</span> <span class="literal">true</span> </span><br><span class="line"><span class="attr">http.cors.allow-origin:</span> <span class="string">&#x27;*&#x27;</span> </span><br><span class="line"><span class="attr">http.cors.allow-headers:</span> <span class="string">&quot;Authorization&quot;</span></span><br></pre></td></tr></table></figure><p>对了, 这里有一款<a href="https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm/related">elasticsearch-head Chrome Plug-in</a> 推荐。</p><h3 id="Kibana"><a href="#Kibana" class="headerlink" title="Kibana"></a>Kibana</h3><blockquote><p>UI 界面</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">wget https://www.elastic.co/downloads/kibana</span><br><span class="line">tar -xvf kibana.tar.gz</span><br><span class="line">./kibana/bin/kibana</span><br><span class="line">open http://localhost:5601/</span><br></pre></td></tr></table></figure><h3 id="Spring-Boot-集成"><a href="#Spring-Boot-集成" class="headerlink" title="Spring Boot 集成"></a>Spring Boot 集成</h3><ol><li><p><code>pom.xml</code> 引入 <code>logback</code> 支持。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>net.logstash.logback<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>logstash-logback-encoder<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.11<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>在 <code>resources/</code> 文件夹内创建 <code>logback-spring.xml</code> 文件。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">appender</span> <span class="attr">name</span>=<span class="string">&quot;LOGSTASH&quot;</span> <span class="attr">class</span>=<span class="string">&quot;net.logstash.logback.appender.LogstashTcpSocketAppender&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">destination</span>&gt;</span>dev.local:4560<span class="tag">&lt;/<span class="name">destination</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">encoder</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> <span class="attr">class</span>=<span class="string">&quot;net.logstash.logback.encoder.LogstashEncoder&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">appender</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">include</span> <span class="attr">resource</span>=<span class="string">&quot;org/springframework/boot/logging/logback/base.xml&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">root</span> <span class="attr">level</span>=<span class="string">&quot;INFO&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">&quot;LOGSTASH&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">&quot;CONSOLE&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">root</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>配置 logstash, 创建 <code>logstash.conf</code>。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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">        port =&gt; 4560</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">output &#123;</span><br><span class="line">    elasticsearch &#123;</span><br><span class="line">        action =&gt; &quot;index&quot;</span><br><span class="line">        hosts =&gt; [&quot;127.0.0.1:9200&quot;]</span><br><span class="line">        index =&gt; &quot;applog&quot;</span><br><span class="line">    ;    user =&gt; &quot;elastic&quot;</span><br><span class="line">    ;    password =&gt; &quot;changeme&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>启动logstash <code>./bin/logstash -f logstash.conf</code></p></li><li><p>使用。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestControllerTest</span> &#123;</span><br><span class="line">    <span class="type">Random</span> <span class="variable">random</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Random</span>();</span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testList</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">            log.info(<span class="string">&quot;Hello world form hocgin&quot;</span>);</span><br><span class="line">            <span class="keyword">if</span> (random.nextBoolean()) &#123;</span><br><span class="line">                log.info(<span class="string">&quot;sksdjkf &quot;</span> + random.nextInt(<span class="number">1000</span>));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><h2 id="关于-Kibana-安全配置"><a href="#关于-Kibana-安全配置" class="headerlink" title="关于 Kibana 安全配置"></a>关于 Kibana 安全配置</h2><ul><li><a href="https://www.elastic.co/guide/en/kibana/current/using-kibana-with-security.html">Configuring Security in Kibana</a></li></ul><ol><li><p>安装 x-pack.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">logstash-plugin install x-pack</span><br><span class="line"></span><br><span class="line">elasticsearch-plugin install x-pack</span><br><span class="line"></span><br><span class="line">kibana-plugin install x-pack</span><br></pre></td></tr></table></figure></li><li><p>修改 <code>config/kibana.yml</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">elasticsearch.username: &quot;elastic&quot; </span><br><span class="line">elasticsearch.password: &quot;changeme&quot;</span><br></pre></td></tr></table></figure></li><li><p>修改 <code>logstash.conf</code>。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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">        port =&gt; 4560</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">output &#123;</span><br><span class="line">    elasticsearch &#123;</span><br><span class="line">        action =&gt; &quot;index&quot;</span><br><span class="line">        hosts =&gt; [&quot;127.0.0.1:9200&quot;]</span><br><span class="line">        index =&gt; &quot;applog&quot;</span><br><span class="line">        user =&gt; &quot;elastic&quot;</span><br><span class="line">        password =&gt; &quot;changeme&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><h3 id="如果忘记-ElasticSearch-密码"><a href="#如果忘记-ElasticSearch-密码" class="headerlink" title="如果忘记 ElasticSearch 密码"></a>如果忘记 ElasticSearch 密码</h3><ol><li>停止 <code>ElasticSearch</code> 服务</li><li>创建一个管理员用户<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x-pack/users useradd my_admin -p my_password -r superuser</span><br></pre></td></tr></table></figure></li><li>启动 <code>ElasticSearch</code> 服务</li><li>使用 API 修改密码<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">curl -u my_admin -XPUT &#x27;http://localhost:9200/_xpack/security/user/elastic/_password?pretty&#x27; -H &#x27;Content-Type: application/json&#x27; -d&#x27;</span><br><span class="line">&#123;</span><br><span class="line">  &quot;password&quot; : &quot;new_password&quot;</span><br><span class="line">&#125;&#x27;</span><br><span class="line">``</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment"># ELK Docker</span></span></span><br><span class="line">- [ELK Docker](https://github.com/spujadas/elk-docker)</span><br><span class="line">简而言之:</span><br><span class="line">```shell</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">:5601 - Kibana</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">:9200 - Elasticsearch</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">:5044 - Logstash</span></span><br><span class="line">sudo docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -it --name elk sebp/elk</span><br></pre></td></tr></table></figure></li></ol><hr><blockquote><p>:2019年3月23日，星期六 补充</p></blockquote><h2 id="ELK-1"><a href="#ELK-1" class="headerlink" title="ELK"></a>ELK</h2><h3 id="L"><a href="#L" class="headerlink" title="L"></a>L</h3><p>配置文件位置: <code>&#123;&#125;/config/</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br></pre></td><td class="code"><pre><span class="line">; 输入</span><br><span class="line">input &#123;</span><br><span class="line">    file &#123;</span><br><span class="line">        path =&gt; [&quot;&#123;path&#125;&quot;]</span><br><span class="line">        ; 设置类型</span><br><span class="line">        type =&gt; &quot;nginx_access&quot;</span><br><span class="line">        ; 起点位置</span><br><span class="line">        start_position =&gt; &quot;beginning&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">; 数据清洗</span><br><span class="line">filter &#123;</span><br><span class="line">    if [type] == &quot;nginx_access&quot; &#123;</span><br><span class="line">        grok &#123;</span><br><span class="line">            patterns_dir =&gt; &quot;&#123;path&#125;&quot;</span><br><span class="line">            match =&gt; &#123;</span><br><span class="line">                &quot;message&quot; =&gt; &quot;%&#123;NGINXACCESS&#125;&quot;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        ; 格式化date字段时间格式</span><br><span class="line">        date &#123;</span><br><span class="line">            match =&gt; [&quot;timestamp&quot;, &quot;dd/MMM/YYYY:HH:mm:ss Z&quot;]</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        ; 解析param字段</span><br><span class="line">        if[param] &#123;</span><br><span class="line">            ruby &#123;</span><br><span class="line">                init =&gt; &quot;@kname = [&#x27;quote&#x27;, &#x27;url_args&#x27;]&quot;</span><br><span class="line">                code =&gt; &quot;</span><br><span class="line">                    new_event = LogStash::Event.new(Hash[@kname.zip(event.get(&#x27;param&#x27;).split(&#x27;?&#x27;))])</span><br><span class="line">                    new_event.remove(&#x27;@timestamp&#x27;)</span><br><span class="line">                    event.append(new_event)</span><br><span class="line">                &quot;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        if[url_args] &#123;</span><br><span class="line">            ruby &#123;</span><br><span class="line">                init =&gt; &quot;@kname = [&#x27;key&#x27;, &#x27;value&#x27;]&quot;</span><br><span class="line">                code =&gt; &quot;</span><br><span class="line">                    event.set(</span><br><span class="line">                        &#x27;nested_args&#x27;, </span><br><span class="line">                        event.get(&#x27;url_args&#x27;).split(&#x27;&amp;&#x27;).collect &#123;|i| Hash[@kname.zip(i.split(&#x27;=&#x27;))]&#125;</span><br><span class="line">                    )</span><br><span class="line">                &quot;</span><br><span class="line">                remove_field =&gt; [&quot;url_args&quot;, &quot;param&quot;, &quot;quote&quot;]</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        ;修改指定字段的内容 </span><br><span class="line">        mutate &#123;</span><br><span class="line">            ; 转换类型</span><br><span class="line">            convert =&gt; [&quot;response&quot;, &quot;integer&quot;]</span><br><span class="line">            remove_field =&gt; [&quot;timestamp&quot;]</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></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">    stdout &#123;</span><br><span class="line">        codec =&gt; rubydebug</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    elasticsearch &#123;</span><br><span class="line">        ; 位置</span><br><span class="line">        hosts =&gt; [&quot;&#123;url&#125;&quot;]</span><br><span class="line">        ; 索引格式</span><br><span class="line">        index =&gt; &quot;logstash-%&#123;type&#125;-%&#123;+YYYY.MM.dd&#125;&quot;</span><br><span class="line">        document_type =&gt; &quot;%&#123;type&#125;&quot;</span><br><span class="line">        ; 每次多少数量</span><br><span class="line">        flush_size =&gt; 200</span><br><span class="line">        ; 发送间隔时间</span><br><span class="line">        idle_flush_time =&gt; 1</span><br><span class="line">        ; 是否重新清洗</span><br><span class="line">        sniffing = true</span><br><span class="line">        ; 用户名</span><br><span class="line">        user =&gt; &quot;&#123;user&#125;&quot;</span><br><span class="line">        ; 密码</span><br><span class="line">        password =&gt; &quot;&#123;password&#125;&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>解析器文件位置: <code>&#123;&#125;/config/patterns/</code></p><hr><h3 id="K"><a href="#K" class="headerlink" title="K"></a>K</h3><p>配置文件位置: <code>&#123;&#125;/config/kibana.yml</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">elasticsearch.url:</span> <span class="string">&#x27;&#123;url&#125;&#x27;</span></span><br><span class="line"><span class="attr">elasticsearch.username:</span> <span class="string">&#x27;&#123;username&#125;&#x27;</span></span><br><span class="line"><span class="attr">elasticsearch.password:</span> <span class="string">&#x27;&#123;password&#125;&#x27;</span></span><br></pre></td></tr></table></figure><p>默认端口: <code>8601</code></p><hr>]]></content>
    
    
    <summary type="html">&lt;p&gt;日志系统 ELK 在 Spring Boot 上的初步集成 😋&lt;/p&gt;</summary>
    
    
    
    <category term="服务端" scheme="https://hocg.in/categories/%E6%9C%8D%E5%8A%A1%E7%AB%AF/"/>
    
    
    <category term="ELK" scheme="https://hocg.in/tags/ELK/"/>
    
  </entry>
  
  <entry>
    <title>Spring Boot启动过程和Bean的创建过程</title>
    <link href="https://hocg.in/2018/01/15/Spring%20Boot%20%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E5%92%8C%20Bean%20%E7%9A%84%E5%88%9B%E5%BB%BA%E8%BF%87%E7%A8%8B/"/>
    <id>https://hocg.in/2018/01/15/Spring%20Boot%20%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E5%92%8C%20Bean%20%E7%9A%84%E5%88%9B%E5%BB%BA%E8%BF%87%E7%A8%8B/</id>
    <published>2018-01-15T17:10:20.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>这几天分析了一下 Spring Boot 启动过程和 Bean 的创建过程，在此记录下来。<br>如果有什么不对的地方，欢迎提出🙏。</p><span id="more"></span><h2 id="启动过程"><a href="#启动过程" class="headerlink" title="启动过程"></a>启动过程</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 将 new SpringApplicationBuilder(sources...) 加入 sources 列表。</span></span><br><span class="line"><span class="comment">// ---------------推断是否是Web环境------------</span></span><br><span class="line"><span class="comment">// SpringApplication.deduceMainApplicationClass#248</span></span><br><span class="line"><span class="comment">// 主要是否包含 javax.servlet.Servlet ..</span></span><br><span class="line"><span class="comment">// ---------------Initializer------------</span></span><br><span class="line"><span class="comment">// 使用 ClassLoader</span></span><br><span class="line"><span class="comment">// 分析引入所有包的: META-INF/spring.factories 文件</span></span><br><span class="line"><span class="comment">// - spring-boot-actuator-1.5.8.RELEASE.jar</span></span><br><span class="line"><span class="comment">// - spring-data-redis-1.8.8.RELEASE.jar</span></span><br><span class="line"><span class="comment">// - ..</span></span><br><span class="line"><span class="comment">// 获得 Key 为`org.springframework.context.ApplicationContextInitializer`的所有节点(Class), 实例化并通过 @Order 进行排序。</span></span><br><span class="line"><span class="comment">// ---------------Listener------------</span></span><br><span class="line"><span class="comment">// 使用 ClassLoader</span></span><br><span class="line"><span class="comment">// 分析引入所有包的: META-INF/spring.factories 文件</span></span><br><span class="line"><span class="comment">// - spring-boot-actuator-1.5.8.RELEASE.jar</span></span><br><span class="line"><span class="comment">// - spring-data-redis-1.8.8.RELEASE.jar</span></span><br><span class="line"><span class="comment">// - ..</span></span><br><span class="line"><span class="comment">// 获得 Key 为`org.springframework.context.ApplicationListener`的所有节点(Class), 实例化并通过 @Order 进行排序。</span></span><br><span class="line"><span class="comment">// ---------------推断Main类------------</span></span><br><span class="line"><span class="comment">// SpringApplication.deduceMainApplicationClass#252</span></span><br><span class="line"><span class="comment">// 推断当前应用的入口函数(方法名为main)。</span></span><br><span class="line">    <span class="keyword">new</span> <span class="title class_">SpringApplicationBuilder</span>()</span><br><span class="line">        .sources(Application.class)</span><br><span class="line">        <span class="comment">// -------判断是否热部署状态---------</span></span><br><span class="line">        <span class="comment">// ---如果设置了 parent() 进行配置-----</span></span><br><span class="line">        <span class="comment">// configureAsChildIfNecessary(args);如果配置了会加入一个 ParentContextApplicationContextInitializer</span></span><br><span class="line">        <span class="comment">// ---------初始化当前应用----------</span></span><br><span class="line">        <span class="comment">// SpringApplication.run(args)</span></span><br><span class="line">        .run(args);</span><br></pre></td></tr></table></figure><h3 id="分析-SpringApplication-run-args"><a href="#分析-SpringApplication-run-args" class="headerlink" title="分析 SpringApplication.run(args)"></a>分析 SpringApplication.run(args)</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 计时器, 用于记录启动时间</span></span><br><span class="line"><span class="type">StopWatch</span> <span class="variable">stopWatch</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StopWatch</span>();</span><br><span class="line">stopWatch.start();</span><br><span class="line"><span class="type">ConfigurableApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"><span class="type">FailureAnalyzers</span> <span class="variable">analyzers</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"><span class="comment">// 设置为无输入/输出设备模式</span></span><br><span class="line">configureHeadlessProperty();</span><br><span class="line"><span class="comment">// 使用 ClassLoader</span></span><br><span class="line"><span class="comment">// 分析引入所有包的: META-INF/spring.factories 文件</span></span><br><span class="line"><span class="comment">// 获得 Key 为`org.springframework.boot.SpringApplicationRunListener`的所有节点(Class), 实例化并通过 @Order 进行排序。</span></span><br><span class="line"><span class="comment">// 并封装进入 SpringApplicationRunListeners 类。</span></span><br><span class="line"><span class="type">SpringApplicationRunListeners</span> <span class="variable">listeners</span> <span class="operator">=</span> getRunListeners(args);</span><br><span class="line"><span class="comment">// 由 SpringApplicationRunListeners 控制类的启动。</span></span><br><span class="line">listeners.starting();</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="comment">// 封装我们提供的 args 参数</span></span><br><span class="line">    <span class="type">ApplicationArguments</span> <span class="variable">applicationArguments</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultApplicationArguments</span>(args);</span><br><span class="line">    <span class="comment">// 根据是否 Web 环境(webEnvironment) 获得环境(StandardServletEnvironment/StandardEnvironment)</span></span><br><span class="line">    <span class="comment">// - 加载默认的参数源(StandardServletEnvironment.customizePropertySources)</span></span><br><span class="line">    <span class="comment">// - 加载我们提供的启动参数(args)作为参数源。当然，前提是 addCommandLineProperties 为 true。</span></span><br><span class="line">    <span class="comment">// 通过 SpringApplicationRunListeners.environmentPrepared(..) 处理上面提供的应用环境参数。</span></span><br><span class="line">    <span class="type">ConfigurableEnvironment</span> <span class="variable">environment</span> <span class="operator">=</span> prepareEnvironment(listeners, applicationArguments);</span><br><span class="line">    <span class="comment">// 打印 banner。本身是由 Banner 类实现的</span></span><br><span class="line">    <span class="type">Banner</span> <span class="variable">printedBanner</span> <span class="operator">=</span> printBanner(environment);</span><br><span class="line">    <span class="comment">// 实例化一个应用的当前环境, Spring Boot 提供了2种环境根据是否是web环境进行动态实例化(webEnvironment), 分别是(AnnotationConfigEmbeddedWebApplicationContext/ConfigurableWebApplicationContext)</span></span><br><span class="line">    <span class="comment">// 这是会创建两个用于扫描注解的重要对象</span></span><br><span class="line">    <span class="comment">// - AnnotatedBeanDefinitionReader  读取器, 设置环境参数，创建时注册了一系列的用于 Bean 的解析器(AnnotatedBeanDefinitionReader#65)</span></span><br><span class="line">    <span class="comment">// - ClassPathBeanDefinitionScanner 扫描器, 设置路径 &amp; 环境 &amp; 拦截器(Component.class)</span></span><br><span class="line">    context = createApplicationContext();</span><br><span class="line">    <span class="comment">// ----------创建失败解析器------------</span></span><br><span class="line">    <span class="comment">// 当初始化出现错误时进行错误分析器</span></span><br><span class="line">    <span class="comment">// 使用 ClassLoader</span></span><br><span class="line">    <span class="comment">// 分析引入所有包的: META-INF/spring.factories 文件</span></span><br><span class="line">    <span class="comment">// - spring-boot-actuator-1.5.8.RELEASE.jar</span></span><br><span class="line">    <span class="comment">// - spring-data-redis-1.8.8.RELEASE.jar</span></span><br><span class="line">    <span class="comment">// - ..</span></span><br><span class="line">    <span class="comment">// 获得 Key 为`org.springframework.boot.diagnostics.FailureAnalyzer`的所有节点(Class), 实例化并通过 @Order 进行排序。</span></span><br><span class="line">    <span class="comment">// 并加入 FailureAnalyzers 管理。</span></span><br><span class="line">    analyzers = <span class="keyword">new</span> <span class="title class_">FailureAnalyzers</span>(context);</span><br><span class="line">    <span class="comment">// 详情见下方【SpringApplication.prepareContext(..)】</span></span><br><span class="line">    prepareContext(context, environment, listeners, applicationArguments, printedBanner);</span><br><span class="line">    <span class="comment">// 详情见下方【分析 AbstractApplicationContext.refreshContext(context);】</span></span><br><span class="line">    refreshContext(context);</span><br><span class="line">    <span class="comment">// ApplicationRunner &amp; CommandLineRunner.run 按类型从 Bean 容器中取出，并调用 run(..)</span></span><br><span class="line">    afterRefresh(context, applicationArguments);</span><br><span class="line">    <span class="comment">// 广播通知 SpringApplicationRunListener.finished</span></span><br><span class="line">    listeners.finished(context, <span class="literal">null</span>);</span><br><span class="line">    <span class="comment">// 关闭计时器，记录启动时间</span></span><br><span class="line">    stopWatch.stop();</span><br><span class="line">    <span class="comment">// 是否启动日志</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">this</span>.logStartupInfo) &#123;</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">StartupInfoLogger</span>(<span class="built_in">this</span>.mainApplicationClass)</span><br><span class="line">                .logStarted(getApplicationLog(), stopWatch);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> context;</span><br><span class="line">&#125; <span class="keyword">catch</span> (Throwable ex) &#123;</span><br><span class="line">    <span class="comment">// 处理退出异常, 存储 ExitCodeEvent</span></span><br><span class="line">    <span class="comment">// 广播通知 listener(listener.finished(context, exception);)</span></span><br><span class="line">    <span class="comment">// 使用 analyzers 进行失败分析</span></span><br><span class="line">    handleRunFailure(context, listeners, analyzers, ex);</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalStateException</span>(ex);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="分析-SpringApplication-prepareContext"><a href="#分析-SpringApplication-prepareContext" class="headerlink" title="分析 SpringApplication.prepareContext(..)"></a>分析 SpringApplication.prepareContext(..)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">prepareContext</span><span class="params">(ConfigurableApplicationContext context,</span></span><br><span class="line"><span class="params">            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,</span></span><br><span class="line"><span class="params">            ApplicationArguments applicationArguments, Banner printedBanner)</span> &#123;</span><br><span class="line">        <span class="comment">// 设置环境参数</span></span><br><span class="line">    context.setEnvironment(environment);</span><br><span class="line">        <span class="comment">// </span></span><br><span class="line">        <span class="comment">// - 注册自定义 beanNameGenerator，如果有的话。</span></span><br><span class="line">        <span class="comment">// - 注册自定义 resourceLoader，如果有的话。</span></span><br><span class="line">        <span class="comment">// 其中, resourceLoader 分为两种类型</span></span><br><span class="line">        <span class="comment">//     - GenericApplicationContext(ResourceLoader)</span></span><br><span class="line">        <span class="comment">//     - DefaultResourceLoader(ClassLoader)</span></span><br><span class="line">    postProcessApplicationContext(context);</span><br><span class="line">        <span class="comment">// 初始化所有之前加载的 ApplicationContextInitializer 节点</span></span><br><span class="line">    applyInitializers(context);</span><br><span class="line">        <span class="comment">// 所有监听器通知进入 contextPrepared 阶段</span></span><br><span class="line">    listeners.contextPrepared(context);</span><br><span class="line">        <span class="comment">// 是否启动日志</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">this</span>.logStartupInfo) &#123;</span><br><span class="line">        <span class="comment">// 交由顶级打印日志信息</span></span><br><span class="line">        logStartupInfo(context.getParent() == <span class="literal">null</span>);</span><br><span class="line">        <span class="comment">// 打印配置文件信息</span></span><br><span class="line">        logStartupProfileInfo(context);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Add boot specific singleton beans</span></span><br><span class="line">    context.getBeanFactory().registerSingleton(<span class="string">&quot;springApplicationArguments&quot;</span>,</span><br><span class="line">        applicationArguments);</span><br><span class="line">    <span class="keyword">if</span> (printedBanner != <span class="literal">null</span>) &#123;</span><br><span class="line">        context.getBeanFactory().registerSingleton(<span class="string">&quot;springBootBanner&quot;</span>, printedBanner);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Load the sources</span></span><br><span class="line">    Set&lt;Object&gt; sources = getSources();</span><br><span class="line">    Assert.notEmpty(sources, <span class="string">&quot;Sources must not be empty&quot;</span>);</span><br><span class="line">        <span class="comment">// 创建 Bean 的加载器, BeanDefinitionLoader</span></span><br><span class="line">        <span class="comment">// ---------------解析器---------------</span></span><br><span class="line">        <span class="comment">// - 注解 AnnotatedBeanDefinitionReader</span></span><br><span class="line">        <span class="comment">// - xml XmlBeanDefinitionReader</span></span><br><span class="line">        <span class="comment">// - goovy GroovyBeanDefinitionReader</span></span><br><span class="line">        <span class="comment">// - 类路径 ClassPathBeanDefinitionScanner</span></span><br><span class="line">        <span class="comment">// ---------------自定义-----------------</span></span><br><span class="line">        <span class="comment">// - 加载自定义 beanNameGenerator，如果有的话。</span></span><br><span class="line">        <span class="comment">// - 加载自定义 resourceLoader，如果有的话。</span></span><br><span class="line">        <span class="comment">// - 加载自定义 environment，如果有的话。</span></span><br><span class="line">    load(context, sources.toArray(<span class="keyword">new</span> <span class="title class_">Object</span>[sources.size()]));</span><br><span class="line">        <span class="comment">// 通知环境加载结束</span></span><br><span class="line">    listeners.contextLoaded(context);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="分析-AbstractApplicationContext-refreshContext-context"><a href="#分析-AbstractApplicationContext-refreshContext-context" class="headerlink" title="分析 AbstractApplicationContext.refreshContext(context);"></a>分析 AbstractApplicationContext.refreshContext(context);</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">refresh</span><span class="params">()</span> <span class="keyword">throws</span> BeansException, IllegalStateException &#123;</span><br><span class="line">    <span class="keyword">synchronized</span> (<span class="built_in">this</span>.startupShutdownMonitor) &#123;</span><br><span class="line">        <span class="comment">// 设置为启动状态</span></span><br><span class="line">        <span class="comment">// 校验必须字段, 使用 ConfigurablePropertyResolver#setRequiredProperties 进行设置。</span></span><br><span class="line">        <span class="comment">// Prepare this context for refreshing.</span></span><br><span class="line">        prepareRefresh();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 刷新当前 beanFactory 的ID, 值得一提的是默认的 BeanFactory 是 org.springframework.beans.factory.support.DefaultListableBeanFactory。</span></span><br><span class="line">        <span class="comment">// Tell the subclass to refresh the internal bean factory.</span></span><br><span class="line">        <span class="type">ConfigurableListableBeanFactory</span> <span class="variable">beanFactory</span> <span class="operator">=</span> obtainFreshBeanFactory();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ----------BeanFactory重点初始化(AbstractApplicationContext.prepareBeanFactory#627)---------------</span></span><br><span class="line">        <span class="comment">// - 设置 BeanClassLoader</span></span><br><span class="line">        <span class="comment">// - 设置 字符解析器(SpelExpressionParser)</span></span><br><span class="line">        <span class="comment">// - 设置 资源位置</span></span><br><span class="line">        <span class="comment">// - 添加 处理器</span></span><br><span class="line">        <span class="comment">// - 忽略 某些接口</span></span><br><span class="line">        <span class="comment">// - 注册某些解析器解决依赖关系</span></span><br><span class="line">        <span class="comment">// - 添加一个监听器</span></span><br><span class="line">        <span class="comment">// - 注册 默认的 environment Bean(3个), 如果不存在的话。</span></span><br><span class="line">        <span class="comment">// Prepare the bean factory for use in this context.</span></span><br><span class="line">        prepareBeanFactory(beanFactory);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// AnnotationConfigEmbeddedWebApplicationContext.postProcessBeanFactory#182</span></span><br><span class="line">            <span class="comment">// - 加入 WebApplicationContextServletContextAwareProcessor 作为 BeanPostProcessor </span></span><br><span class="line">            <span class="comment">// - beanFactory.ignoreDependencyInterface(ServletContextAware.class);</span></span><br><span class="line">            <span class="comment">// 也会读取注册的注解类 和 配置要扫描的包位置。</span></span><br><span class="line">            <span class="comment">// Allows post-processing of the bean factory in context subclasses.</span></span><br><span class="line">            postProcessBeanFactory(beanFactory);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)</span></span><br><span class="line">            <span class="comment">// 通过 ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry#308 扫描所有应用文件。</span></span><br><span class="line">            <span class="comment">// - 扫描预制的配置文件</span></span><br><span class="line">            <span class="comment">// - 扫描应用的所有注解配置成 Bean 字典</span></span><br><span class="line">            <span class="comment">// Invoke factory processors registered as beans in the context.</span></span><br><span class="line">            invokeBeanFactoryPostProcessors(beanFactory);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 使用 BeanPostProcessor.class 获取 Bean(所有 Bean 均在beanDefinitionMap 内含有), 排序后, 注册为 Bean 处理器。</span></span><br><span class="line">            <span class="comment">// 加入 BeanPostProcessorChecker.class 用于监听Bean的创建周期。</span></span><br><span class="line">            <span class="comment">// - priorityOrderedPostProcessors</span></span><br><span class="line">            <span class="comment">// - orderedPostProcessors</span></span><br><span class="line">            <span class="comment">// - nonOrderedPostProcessors</span></span><br><span class="line">            <span class="comment">// - internalPostProcessors</span></span><br><span class="line">            <span class="comment">// 加入 ApplicationListenerDetector 作为兜底 BeanPostProcessor</span></span><br><span class="line">            <span class="comment">// Register bean processors that intercept bean creation.</span></span><br><span class="line">            registerBeanPostProcessors(beanFactory);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 初始化消息资源(MessageSource)</span></span><br><span class="line">            <span class="comment">// 一般是作为 i18 的资源文件。</span></span><br><span class="line">            <span class="comment">// Initialize message source for this context.</span></span><br><span class="line">            initMessageSource();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 初始化应用广播器(ApplicationEventMulticaster)</span></span><br><span class="line">            <span class="comment">// 一般用于管理 ApplicationListener</span></span><br><span class="line">            <span class="comment">// Initialize event multicaster for this context.</span></span><br><span class="line">            initApplicationEventMulticaster();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// EmbeddedWebApplicationContext.onRefresh#131</span></span><br><span class="line">            <span class="comment">// 创建嵌入式 Servlet 容器</span></span><br><span class="line">            <span class="comment">// Initialize other special beans in specific context subclasses.</span></span><br><span class="line">            onRefresh();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 注册 listener beans 到 ApplicationEventMulticaster。</span></span><br><span class="line">            <span class="comment">// 广播 (Set&lt;ApplicationEvent&gt; earlyEventsToProcess).multicastEvent</span></span><br><span class="line">            <span class="comment">// Check for listener beans and register them.</span></span><br><span class="line">            registerListeners();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// - 转化 BeanFactory 类型</span></span><br><span class="line">            <span class="comment">// - 提供默认的嵌入值解析器，如果需要的话。</span></span><br><span class="line">            <span class="comment">// - 装载 LoadTimeWeaverAware.class 类型的 Bean</span></span><br><span class="line">            <span class="comment">// - 停止临时的 ClassLoad</span></span><br><span class="line">            <span class="comment">// - 冻结配置</span></span><br><span class="line">            <span class="comment">// - 预先装载所有单例 Bean。</span></span><br><span class="line">            <span class="comment">//    - 初始化@Controller @RequestMapping 之类的过程, 基本上我们使用的注解都是该阶段进行设置的。</span></span><br><span class="line">            <span class="comment">// Instantiate all remaining (non-lazy-init) singletons.</span></span><br><span class="line">            finishBeanFactoryInitialization(beanFactory);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// ----------发布事件通知----------------</span></span><br><span class="line">            <span class="comment">// 注册 LifecycleProcessor，并发布 onRefresh() 事件。</span></span><br><span class="line">            <span class="comment">// earlyApplicationEvents.add(new ContextRefreshedEvent(this)) 加入 Context 刷新事件</span></span><br><span class="line">            <span class="comment">// 注册 LiveBean，如果有的话。..DevTool Debug 那个</span></span><br><span class="line">            <span class="comment">// Last step: publish corresponding event.</span></span><br><span class="line">            finishRefresh();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">catch</span> (BeansException ex) &#123;</span><br><span class="line">            <span class="keyword">if</span> (logger.isWarnEnabled()) &#123;</span><br><span class="line">                logger.warn(<span class="string">&quot;Exception encountered during context initialization - &quot;</span> +</span><br><span class="line">                        <span class="string">&quot;cancelling refresh attempt: &quot;</span> + ex);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// Destroy already created singletons to avoid dangling resources.</span></span><br><span class="line">            destroyBeans();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// Reset &#x27;active&#x27; flag.</span></span><br><span class="line">            cancelRefresh(ex);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// Propagate exception to caller.</span></span><br><span class="line">            <span class="keyword">throw</span> ex;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// Reset common introspection caches in Spring&#x27;s core, since we</span></span><br><span class="line">            <span class="comment">// might not ever need metadata for singleton beans anymore...</span></span><br><span class="line">            resetCommonCaches();</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></pre></td></tr></table></figure><h2 id="关于-Bean"><a href="#关于-Bean" class="headerlink" title="关于 Bean"></a>关于 Bean</h2><ul><li>BeanDefinitionRegistry, Bean 定义注册表，类似 Bean 的仓库。</li><li>BeanDefinition 存储 Bean 的信息。<ul><li>Bean 的 scope 种类, <ul><li>prototype, 每次获取时创建。</li><li>request, </li><li>session, </li><li>global session, </li><li>singleton(默认), 单例。</li></ul></li></ul></li><li>BeanFactory, Bean 工厂。<ul><li>用于 注册 Bean, 获得 Bean, 清除 Bean, 配置 Bean 的相关策略。</li></ul></li><li>DefaultListableBeanFactory 是 Spring 默认的 BeanFactory。<ul><li>registeredSingletons 已注册的 Bean 列表, 存储 BeanName。</li><li>singletonObjects 存储 Bean 对象, 使用 Map 结构。</li><li>earlySingletonObjects 存储由 ObjectFactory 创建的 Bean 对象。</li><li>singletonFactories 存储之前创建的 ObjectFactory 其本质是 Bean 对象。</li><li>beanDefinitionMap 扫描存储的记录，可以理解为 Bean 的总名单。</li><li>mergedBeanDefinitions</li></ul></li></ul><h3 id="获取-Bean-getBean"><a href="#获取-Bean-getBean" class="headerlink" title="获取 Bean getBean(..)"></a>获取 Bean <code>getBean(..)</code></h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// AbstractBeanFactory.class</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">getBean</span><span class="params">(String name)</span> <span class="keyword">throws</span> BeansException &#123;</span><br><span class="line">        <span class="keyword">return</span> doGetBean(name, <span class="literal">null</span>, <span class="literal">null</span>, <span class="literal">false</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@SuppressWarnings(&quot;unchecked&quot;)</span></span><br><span class="line">    <span class="keyword">protected</span> &lt;T&gt; T <span class="title function_">doGetBean</span><span class="params">(</span></span><br><span class="line"><span class="params">            <span class="keyword">final</span> String name, <span class="keyword">final</span> Class&lt;T&gt; requiredType, <span class="keyword">final</span> Object[] args, <span class="type">boolean</span> typeCheckOnly)</span></span><br><span class="line">            <span class="keyword">throws</span> BeansException &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 解析 BeanName</span></span><br><span class="line">        <span class="keyword">final</span> <span class="type">String</span> <span class="variable">beanName</span> <span class="operator">=</span> transformedBeanName(name);</span><br><span class="line">        Object bean;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 检查缓存中是否存在该 Bean, 如果存在则实例化。</span></span><br><span class="line">        <span class="comment">// Eagerly check singleton cache for manually registered singletons.</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">sharedInstance</span> <span class="operator">=</span> getSingleton(beanName);</span><br><span class="line">        <span class="keyword">if</span> (sharedInstance != <span class="literal">null</span> &amp;&amp; args == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">                <span class="keyword">if</span> (isSingletonCurrentlyInCreation(beanName)) &#123;</span><br><span class="line">                    logger.debug(<span class="string">&quot;Returning eagerly cached instance of singleton bean &#x27;&quot;</span> + beanName +</span><br><span class="line">                            <span class="string">&quot;&#x27; that is not fully initialized yet - a consequence of a circular reference&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">else</span> &#123;</span><br><span class="line">                    logger.debug(<span class="string">&quot;Returning cached instance of singleton bean &#x27;&quot;</span> + beanName + <span class="string">&quot;&#x27;&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            bean = getObjectForBeanInstance(sharedInstance, name, beanName, <span class="literal">null</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">else</span> &#123; <span class="comment">// Bean 不在缓存</span></span><br><span class="line"></span><br><span class="line">            <span class="comment">// 当正在创建的 Bean 的 Scope 为 Prototype 时，抛出异常。</span></span><br><span class="line">            <span class="comment">// 因为 Prototype 模式无法解决依赖问题。</span></span><br><span class="line">            <span class="comment">// Fail if we&#x27;re already creating this bean instance:</span></span><br><span class="line">            <span class="comment">// We&#x27;re assumably within a circular reference.</span></span><br><span class="line">            <span class="keyword">if</span> (isPrototypeCurrentlyInCreation(beanName)) &#123;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanCurrentlyInCreationException</span>(beanName);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">            <span class="comment">// 如果当前 BeanFactory 不包括该 BeanName 并且该 BeanFactory 有父 BeanFactory 时，尝试从父 BeanFactory 获取该 Bean。</span></span><br><span class="line">            <span class="comment">// Check if bean definition exists in this factory.</span></span><br><span class="line">            <span class="type">BeanFactory</span> <span class="variable">parentBeanFactory</span> <span class="operator">=</span> getParentBeanFactory();</span><br><span class="line">            <span class="keyword">if</span> (parentBeanFactory != <span class="literal">null</span> &amp;&amp; !containsBeanDefinition(beanName)) &#123;</span><br><span class="line">                <span class="comment">// Not found -&gt; check parent.</span></span><br><span class="line">                <span class="type">String</span> <span class="variable">nameToLookup</span> <span class="operator">=</span> originalBeanName(name);</span><br><span class="line">                <span class="keyword">if</span> (args != <span class="literal">null</span>) &#123;</span><br><span class="line">                    <span class="comment">// Delegation to parent with explicit args.</span></span><br><span class="line">                    <span class="keyword">return</span> (T) parentBeanFactory.getBean(nameToLookup, args);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">// No args -&gt; delegate to standard getBean method.</span></span><br><span class="line">                    <span class="keyword">return</span> parentBeanFactory.getBean(nameToLookup, requiredType);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 如果不只依靠类型进行获取, 进行标记。</span></span><br><span class="line">            <span class="keyword">if</span> (!typeCheckOnly) &#123;</span><br><span class="line">                markBeanAsCreated(beanName);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">// 将解析转化为 Bean 的信息，注册并获取其依赖的 Bean。</span></span><br><span class="line">                <span class="keyword">final</span> <span class="type">RootBeanDefinition</span> <span class="variable">mbd</span> <span class="operator">=</span> getMergedLocalBeanDefinition(beanName);</span><br><span class="line">                checkMergedBeanDefinition(mbd, beanName, args);</span><br><span class="line"></span><br><span class="line">                <span class="comment">// Guarantee initialization of beans that the current bean depends on.</span></span><br><span class="line">                String[] dependsOn = mbd.getDependsOn();</span><br><span class="line">                <span class="keyword">if</span> (dependsOn != <span class="literal">null</span>) &#123;</span><br><span class="line">                    <span class="keyword">for</span> (String dep : dependsOn) &#123;</span><br><span class="line">                        <span class="keyword">if</span> (isDependent(beanName, dep)) &#123;</span><br><span class="line">                            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanCreationException</span>(mbd.getResourceDescription(), beanName,</span><br><span class="line">                                    <span class="string">&quot;Circular depends-on relationship between &#x27;&quot;</span> + beanName + <span class="string">&quot;&#x27; and &#x27;&quot;</span> + dep + <span class="string">&quot;&#x27;&quot;</span>);</span><br><span class="line">                        &#125;</span><br><span class="line">                        registerDependentBean(dep, beanName);</span><br><span class="line">                        getBean(dep);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 当 Bean 的 Scope 为 Singleton 时</span></span><br><span class="line">                <span class="comment">// Create bean instance.</span></span><br><span class="line">                <span class="keyword">if</span> (mbd.isSingleton()) &#123;</span><br><span class="line">                    sharedInstance = getSingleton(beanName, <span class="keyword">new</span> <span class="title class_">ObjectFactory</span>&lt;Object&gt;() &#123;</span><br><span class="line">                        <span class="meta">@Override</span></span><br><span class="line">                        <span class="keyword">public</span> Object <span class="title function_">getObject</span><span class="params">()</span> <span class="keyword">throws</span> BeansException &#123;</span><br><span class="line">                            <span class="keyword">try</span> &#123;</span><br><span class="line">                                <span class="keyword">return</span> createBean(beanName, mbd, args);</span><br><span class="line">                            &#125;</span><br><span class="line">                            <span class="keyword">catch</span> (BeansException ex) &#123;</span><br><span class="line">                                <span class="comment">// Explicitly remove instance from singleton cache: It might have been put there</span></span><br><span class="line">                                <span class="comment">// eagerly by the creation process, to allow for circular reference resolution.</span></span><br><span class="line">                                <span class="comment">// Also remove any beans that received a temporary reference to the bean.</span></span><br><span class="line">                                destroySingleton(beanName);</span><br><span class="line">                                <span class="keyword">throw</span> ex;</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;);</span><br><span class="line">                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 当 Bean 的 Scope 为 Prototype 时</span></span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (mbd.isPrototype()) &#123;</span><br><span class="line">                    <span class="comment">// It&#x27;s a prototype -&gt; create a new instance.</span></span><br><span class="line">                    <span class="type">Object</span> <span class="variable">prototypeInstance</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        beforePrototypeCreation(beanName);</span><br><span class="line">                        prototypeInstance = createBean(beanName, mbd, args);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">finally</span> &#123;</span><br><span class="line">                        afterPrototypeCreation(beanName);</span><br><span class="line">                    &#125;</span><br><span class="line">                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 当 Bean 的 Scope 为 其他 时</span></span><br><span class="line">                <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="type">String</span> <span class="variable">scopeName</span> <span class="operator">=</span> mbd.getScope();</span><br><span class="line">                    <span class="keyword">final</span> <span class="type">Scope</span> <span class="variable">scope</span> <span class="operator">=</span> <span class="built_in">this</span>.scopes.get(scopeName);</span><br><span class="line">                    <span class="keyword">if</span> (scope == <span class="literal">null</span>) &#123;</span><br><span class="line">                        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalStateException</span>(<span class="string">&quot;No Scope registered for scope name &#x27;&quot;</span> + scopeName + <span class="string">&quot;&#x27;&quot;</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        <span class="type">Object</span> <span class="variable">scopedInstance</span> <span class="operator">=</span> scope.get(beanName, <span class="keyword">new</span> <span class="title class_">ObjectFactory</span>&lt;Object&gt;() &#123;</span><br><span class="line">                            <span class="meta">@Override</span></span><br><span class="line">                            <span class="keyword">public</span> Object <span class="title function_">getObject</span><span class="params">()</span> <span class="keyword">throws</span> BeansException &#123;</span><br><span class="line">                                beforePrototypeCreation(beanName);</span><br><span class="line">                                <span class="keyword">try</span> &#123;</span><br><span class="line">                                    <span class="keyword">return</span> createBean(beanName, mbd, args);</span><br><span class="line">                                &#125;</span><br><span class="line">                                <span class="keyword">finally</span> &#123;</span><br><span class="line">                                    afterPrototypeCreation(beanName);</span><br><span class="line">                                &#125;</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125;);</span><br><span class="line">                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">catch</span> (IllegalStateException ex) &#123;</span><br><span class="line">                        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanCreationException</span>(beanName,</span><br><span class="line">                                <span class="string">&quot;Scope &#x27;&quot;</span> + scopeName + <span class="string">&quot;&#x27; is not active for the current thread; consider &quot;</span> +</span><br><span class="line">                                <span class="string">&quot;defining a scoped proxy for this bean if you intend to refer to it from a singleton&quot;</span>,</span><br><span class="line">                                ex);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">catch</span> (BeansException ex) &#123;</span><br><span class="line">                cleanupAfterBeanCreationFailure(beanName);</span><br><span class="line">                <span class="keyword">throw</span> ex;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 检查获得的 Bean 类型是否符合预期结果。</span></span><br><span class="line">        <span class="comment">// Check if required type matches the type of the actual bean instance.</span></span><br><span class="line">        <span class="keyword">if</span> (requiredType != <span class="literal">null</span> &amp;&amp; bean != <span class="literal">null</span> &amp;&amp; !requiredType.isInstance(bean)) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> getTypeConverter().convertIfNecessary(bean, requiredType);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">catch</span> (TypeMismatchException ex) &#123;</span><br><span class="line">                <span class="keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">                    logger.debug(<span class="string">&quot;Failed to convert bean &#x27;&quot;</span> + name + <span class="string">&quot;&#x27; to required type &#x27;&quot;</span> +</span><br><span class="line">                            ClassUtils.getQualifiedName(requiredType) + <span class="string">&quot;&#x27;&quot;</span>, ex);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanNotOfRequiredTypeException</span>(name, requiredType, bean.getClass());</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> (T) bean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="创建-Bean-createBean"><a href="#创建-Bean-createBean" class="headerlink" title="创建 Bean createBean(..)"></a>创建 Bean <code>createBean(..)</code></h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// AbstractAutowireCapableBeanFactory.class</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> Object <span class="title function_">createBean</span><span class="params">(String beanName, RootBeanDefinition mbd, Object[] args)</span> <span class="keyword">throws</span> BeanCreationException &#123;</span><br><span class="line">        <span class="keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">            logger.debug(<span class="string">&quot;Creating instance of bean &#x27;&quot;</span> + beanName + <span class="string">&quot;&#x27;&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="type">RootBeanDefinition</span> <span class="variable">mbdToUse</span> <span class="operator">=</span> mbd;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 根据信息(mbd, beanName)获取 Bean 的类型</span></span><br><span class="line">        <span class="comment">// Make sure bean class is actually resolved at this point, and</span></span><br><span class="line">        <span class="comment">// clone the bean definition in case of a dynamically resolved Class</span></span><br><span class="line">        <span class="comment">// which cannot be stored in the shared merged bean definition.</span></span><br><span class="line">        Class&lt;?&gt; resolvedClass = resolveBeanClass(mbd, beanName);</span><br><span class="line">        <span class="keyword">if</span> (resolvedClass != <span class="literal">null</span> &amp;&amp; !mbd.hasBeanClass() &amp;&amp; mbd.getBeanClassName() != <span class="literal">null</span>) &#123;</span><br><span class="line">            mbdToUse = <span class="keyword">new</span> <span class="title class_">RootBeanDefinition</span>(mbd);</span><br><span class="line">            mbdToUse.setBeanClass(resolvedClass);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 校验重载函数</span></span><br><span class="line">        <span class="comment">// Prepare method overrides.</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            mbdToUse.prepareMethodOverrides();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">catch</span> (BeanDefinitionValidationException ex) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanDefinitionStoreException</span>(mbdToUse.getResourceDescription(),</span><br><span class="line">                    beanName, <span class="string">&quot;Validation of method overrides failed&quot;</span>, ex);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// Spring 提供的，由 BeanPostProcessor 进行处理接入点。</span></span><br><span class="line">            <span class="comment">// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.</span></span><br><span class="line">            <span class="type">Object</span> <span class="variable">bean</span> <span class="operator">=</span> resolveBeforeInstantiation(beanName, mbdToUse);</span><br><span class="line">            <span class="keyword">if</span> (bean != <span class="literal">null</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> bean;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">catch</span> (Throwable ex) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanCreationException</span>(mbdToUse.getResourceDescription(), beanName,</span><br><span class="line">                    <span class="string">&quot;BeanPostProcessor before instantiation of bean failed&quot;</span>, ex);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 默认的创建 Bean 方式</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">beanInstance</span> <span class="operator">=</span> doCreateBean(beanName, mbdToUse, args);</span><br><span class="line">        <span class="keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">            logger.debug(<span class="string">&quot;Finished creating instance of bean &#x27;&quot;</span> + beanName + <span class="string">&quot;&#x27;&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> beanInstance;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// AbstractAutowireCapableBeanFactory.class</span></span><br><span class="line">    <span class="keyword">protected</span> Object <span class="title function_">doCreateBean</span><span class="params">(<span class="keyword">final</span> String beanName, <span class="keyword">final</span> RootBeanDefinition mbd, <span class="keyword">final</span> Object[] args)</span></span><br><span class="line">            <span class="keyword">throws</span> BeanCreationException &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 根据 Bean 信息实例化 Bean</span></span><br><span class="line">        <span class="comment">// Instantiate the bean.</span></span><br><span class="line">        <span class="type">BeanWrapper</span> <span class="variable">instanceWrapper</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (mbd.isSingleton()) &#123;</span><br><span class="line">            instanceWrapper = <span class="built_in">this</span>.factoryBeanInstanceCache.remove(beanName);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (instanceWrapper == <span class="literal">null</span>) &#123;</span><br><span class="line">            instanceWrapper = createBeanInstance(beanName, mbd, args);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">final</span> <span class="type">Object</span> <span class="variable">bean</span> <span class="operator">=</span> (instanceWrapper != <span class="literal">null</span> ? instanceWrapper.getWrappedInstance() : <span class="literal">null</span>);</span><br><span class="line">        Class&lt;?&gt; beanType = (instanceWrapper != <span class="literal">null</span> ? instanceWrapper.getWrappedClass() : <span class="literal">null</span>);</span><br><span class="line">        mbd.resolvedTargetType = beanType;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 使用 MergedBeanDefinitionPostProcessor 进行处理</span></span><br><span class="line">        <span class="comment">// Allow post-processors to modify the merged bean definition.</span></span><br><span class="line">        <span class="keyword">synchronized</span> (mbd.postProcessingLock) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!mbd.postProcessed) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">catch</span> (Throwable ex) &#123;</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanCreationException</span>(mbd.getResourceDescription(), beanName,</span><br><span class="line">                            <span class="string">&quot;Post-processing of merged bean definition failed&quot;</span>, ex);</span><br><span class="line">                &#125;</span><br><span class="line">                mbd.postProcessed = <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// Eagerly cache singletons to be able to resolve circular references</span></span><br><span class="line">        <span class="comment">// even when triggered by lifecycle interfaces like BeanFactoryAware.</span></span><br><span class="line">        <span class="type">boolean</span> <span class="variable">earlySingletonExposure</span> <span class="operator">=</span> (mbd.isSingleton() &amp;&amp; <span class="built_in">this</span>.allowCircularReferences &amp;&amp;</span><br><span class="line">                isSingletonCurrentlyInCreation(beanName));</span><br><span class="line">        <span class="comment">// 单例 &amp; 允许循环引用 &amp; 正在创建</span></span><br><span class="line">        <span class="keyword">if</span> (earlySingletonExposure) &#123;</span><br><span class="line">            <span class="keyword">if</span> (logger.isDebugEnabled()) &#123;</span><br><span class="line">                logger.debug(<span class="string">&quot;Eagerly caching bean &#x27;&quot;</span> + beanName +</span><br><span class="line">                        <span class="string">&quot;&#x27; to allow for resolving potential circular references&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 使用 ObjectFactory 来管理 Bean 防止循环依赖。</span></span><br><span class="line">            addSingletonFactory(beanName, <span class="keyword">new</span> <span class="title class_">ObjectFactory</span>&lt;Object&gt;() &#123;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="keyword">public</span> Object <span class="title function_">getObject</span><span class="params">()</span> <span class="keyword">throws</span> BeansException &#123;</span><br><span class="line">                    <span class="keyword">return</span> getEarlyBeanReference(beanName, mbd, bean);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// Initialize the bean instance.</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">exposedObject</span> <span class="operator">=</span> bean;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//  对 Bean 的属性进行填充</span></span><br><span class="line">            populateBean(beanName, mbd, instanceWrapper);</span><br><span class="line">            <span class="keyword">if</span> (exposedObject != <span class="literal">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 初始化 Bean 实例</span></span><br><span class="line">                exposedObject = initializeBean(beanName, exposedObject, mbd);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">catch</span> (Throwable ex) &#123;</span><br><span class="line">            <span class="keyword">if</span> (ex <span class="keyword">instanceof</span> BeanCreationException &amp;&amp; beanName.equals(((BeanCreationException) ex).getBeanName())) &#123;</span><br><span class="line">                <span class="keyword">throw</span> (BeanCreationException) ex;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanCreationException</span>(</span><br><span class="line">                        mbd.getResourceDescription(), beanName, <span class="string">&quot;Initialization of bean failed&quot;</span>, ex);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (earlySingletonExposure) &#123;</span><br><span class="line">            <span class="type">Object</span> <span class="variable">earlySingletonReference</span> <span class="operator">=</span> getSingleton(beanName, <span class="literal">false</span>);</span><br><span class="line">            <span class="comment">// 存在已创建的单例, 一般情况为解决依赖的时候。</span></span><br><span class="line">            <span class="keyword">if</span> (earlySingletonReference != <span class="literal">null</span>) &#123;</span><br><span class="line">                <span class="keyword">if</span> (exposedObject == bean) &#123;</span><br><span class="line">                    exposedObject = earlySingletonReference;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">// 允许循环依赖不一致 &amp; Bean 含有依赖。</span></span><br><span class="line">                <span class="comment">// 此时如果存在依赖，将会发生异常。</span></span><br><span class="line">                <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">this</span>.allowRawInjectionDespiteWrapping &amp;&amp; hasDependentBean(beanName)) &#123;</span><br><span class="line">                    String[] dependentBeans = getDependentBeans(beanName);</span><br><span class="line">                    Set&lt;String&gt; actualDependentBeans = <span class="keyword">new</span> <span class="title class_">LinkedHashSet</span>&lt;String&gt;(dependentBeans.length);</span><br><span class="line">                    <span class="keyword">for</span> (String dependentBean : dependentBeans) &#123;</span><br><span class="line">                        <span class="keyword">if</span> (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) &#123;</span><br><span class="line">                            actualDependentBeans.add(dependentBean);</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">if</span> (!actualDependentBeans.isEmpty()) &#123;</span><br><span class="line">                        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanCurrentlyInCreationException</span>(beanName,</span><br><span class="line">                                <span class="string">&quot;Bean with name &#x27;&quot;</span> + beanName + <span class="string">&quot;&#x27; has been injected into other beans [&quot;</span> +</span><br><span class="line">                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +</span><br><span class="line">                                <span class="string">&quot;] in its raw version as part of a circular reference, but has eventually been &quot;</span> +</span><br><span class="line">                                <span class="string">&quot;wrapped. This means that said other beans do not use the final version of the &quot;</span> +</span><br><span class="line">                                <span class="string">&quot;bean. This is often the result of over-eager type matching - consider using &quot;</span> +</span><br><span class="line">                                <span class="string">&quot;&#x27;getBeanNamesOfType&#x27; with the &#x27;allowEagerInit&#x27; flag turned off, for example.&quot;</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 注册一次性 Bean</span></span><br><span class="line">        <span class="comment">// Register bean as disposable.</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            registerDisposableBeanIfNecessary(beanName, bean, mbd);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">catch</span> (BeanDefinitionValidationException ex) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">BeanCreationException</span>(</span><br><span class="line">                    mbd.getResourceDescription(), beanName, <span class="string">&quot;Invalid destruction signature&quot;</span>, ex);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> exposedObject;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;这几天分析了一下 Spring Boot 启动过程和 Bean 的创建过程，在此记录下来。&lt;br&gt;如果有什么不对的地方，欢迎提出🙏。&lt;/p&gt;</summary>
    
    
    
    <category term="Web" scheme="https://hocg.in/categories/Web/"/>
    
    
    <category term="Spring Boot" scheme="https://hocg.in/tags/Spring-Boot/"/>
    
    <category term="Web" scheme="https://hocg.in/tags/Web/"/>
    
  </entry>
  
  <entry>
    <title>使用 Docker 交叉编译 OpenWrt 上运行的 Golang 程序</title>
    <link href="https://hocg.in/2017/11/23/%E4%BD%BF%E7%94%A8%20Docker%20%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%20OpenWrt%20%E4%B8%8A%E8%BF%90%E8%A1%8C%E7%9A%84%20Golang%20%E7%A8%8B%E5%BA%8F/"/>
    <id>https://hocg.in/2017/11/23/%E4%BD%BF%E7%94%A8%20Docker%20%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%20OpenWrt%20%E4%B8%8A%E8%BF%90%E8%A1%8C%E7%9A%84%20Golang%20%E7%A8%8B%E5%BA%8F/</id>
    <published>2017-11-23T10:17:02.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>&gt;.&lt;</p><span id="more"></span><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><ul><li>使用 <code>https://github.com/gomini/go-mips32</code> 对 Go 程序进行交叉编译.</li></ul><h2 id="使用-Docker-交叉编译-Go-程序"><a href="#使用-Docker-交叉编译-Go-程序" class="headerlink" title="使用 Docker 交叉编译 Go 程序"></a>使用 Docker 交叉编译 Go 程序</h2><ol><li><p>拉取镜像</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull conoro/go-mips32:v1</span><br></pre></td></tr></table></figure></li><li><p>启动镜像并挂载本地目录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">docker run -it -v 程序目录:/go/src conoro/go-mips32:v1 /bin/sh</span><br><span class="line"><span class="built_in">cd</span> src</span><br><span class="line"><span class="comment"># 编译</span></span><br><span class="line"><span class="comment"># export GOOS=linux</span></span><br><span class="line"><span class="comment"># export GOARCH=mips32le</span></span><br><span class="line">go build main.go</span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;&amp;gt;.&amp;lt;&lt;/p&gt;</summary>
    
    
    
    <category term="Docker" scheme="https://hocg.in/categories/Docker/"/>
    
    
    <category term="OpenWrt" scheme="https://hocg.in/tags/OpenWrt/"/>
    
    <category term="Docker" scheme="https://hocg.in/tags/Docker/"/>
    
    <category term="Go" scheme="https://hocg.in/tags/Go/"/>
    
  </entry>
  
  <entry>
    <title>自编译 OpenWrt 系统</title>
    <link href="https://hocg.in/2017/11/22/%E8%87%AA%E7%BC%96%E8%AF%91%20OpenWrt%20%E7%B3%BB%E7%BB%9F/"/>
    <id>https://hocg.in/2017/11/22/%E8%87%AA%E7%BC%96%E8%AF%91%20OpenWrt%20%E7%B3%BB%E7%BB%9F/</id>
    <published>2017-11-22T10:18:02.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>😌 整理、记录一下步骤..</p><span id="more"></span><h1 id="前置"><a href="#前置" class="headerlink" title="前置"></a>前置</h1><h2 id="更改源"><a href="#更改源" class="headerlink" title="更改源"></a>更改源</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sed -i.bak &#x27;s/\/us.archive.ubuntu.com\//\/cn.archive.ubuntu.com\//g&#x27; /etc/apt/sources.list</span><br><span class="line"></span><br><span class="line">sudo apt update</span><br></pre></td></tr></table></figure><h2 id="关闭IPv6"><a href="#关闭IPv6" class="headerlink" title="关闭IPv6"></a>关闭IPv6</h2><p>echo 1 &gt; &#x2F;proc&#x2F;sys&#x2F;net&#x2F;ipv6&#x2F;conf&#x2F;<eth1>&#x2F;disable_ipv6</p><h2 id="前置安装"><a href="#前置安装" class="headerlink" title="前置安装"></a>前置安装</h2><ul><li>git subversion make automake autoconf gcc g++ binutils</li></ul><h2 id="make-缺省安装"><a href="#make-缺省安装" class="headerlink" title="make, 缺省安装"></a>make, 缺省安装</h2><ul><li>libncurses5-dev</li><li>libssl-dev</li><li>gawk</li></ul><h2 id="前置-1"><a href="#前置-1" class="headerlink" title="前置"></a>前置</h2><ul><li>GitHub(git clone <a href="https://github.com/openwrt/openwrt">https://github.com/openwrt/openwrt</a>) 获取 OpenWrt, 更改 openWrt 目录为当前用户所有权<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">例如:</span></span><br><span class="line">chown -R hocgin:hocgin openwrt</span><br></pre></td></tr></table></figure></li></ul><hr><h1 id="编译-openwrt-x2F"><a href="#编译-openwrt-x2F" class="headerlink" title="编译(openwrt&#x2F;)"></a>编译(openwrt&#x2F;)</h1><h2 id="编译过程"><a href="#编译过程" class="headerlink" title="编译过程"></a>编译过程</h2><ol><li><p>make</p></li><li><p>.&#x2F;script&#x2F;feeds update -a</p></li><li><p>.&#x2F;script&#x2F;feeds install -a</p></li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">4. make deconfig <span class="comment"># 使用默认的配置</span></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">5. make menuconfig <span class="comment"># 基于终端的一种配置方式，提供了文本模式的图形用户界面，用户可以通过光标移动来浏览所支持的各种特性。</span></span><br></pre></td></tr></table></figure><blockquote><p>固件配置, 可以选择编译的软件包</p></blockquote><pre><code>## 部分选项- 架构(AR7xxx) - FLASH(Generic)- 路由器型号(WNDR3800) - 文件系统(squashfs)- 通用设置    - [-] Crytographically signed package lists    - [-] Compile with support for patented functionallty    - [-] Enable shadow password support    - [-] Crash logging    - [-] Compile the kernel with debug information    - [-] Compile the kernel SysRq support    - [-] Enable process core dump support    - [-] Enable printk timestamps    - [-] Enable Ipv6 support in packages    - [-] Compile certain packages parallelized    - [-] Enable gcc format-security- [-] Build the OpenWrt Image Builder    - [-] In- [-] Build the OpenWrt SDK- [-] Package the OpenWrt-based Toolchain</code></pre><p>其余默认。</p><ol start="6"><li><p>make kernel_config</p><blockquote><p>内核配置[开启浮点数模拟(FPU)]</p></blockquote></li><li><p>make V&#x3D;s -j&lt;处理器数量&gt;</p></li><li><p>编译完成后，移出<code>bin/ar71xx/OpenWrt-ImageBuilder-ar71xx-generic.Linux-x86_64.tar.bz2</code> 文件, 并解压(tar xvf).</p></li><li><p>进入(<code>OpenWrt-ImageBuilder-ar71xx-generic.Linux-x86_64/</code>)</p></li><li><p>编译成镜像</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查基础镜像</span></span><br><span class="line">parallels@ubuntu:~/OpenWrt/OpenWrt-ImageBuilder-ar71xx-generic.Linux-x86_64$ make image PROFILE=WNDR3700</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">包含必备包`预装软件`的镜像</span></span><br><span class="line">parallels@ubuntu:~/OpenWrt/OpenWrt-ImageBuilder-ar71xx-generic.Linux-x86_64$ make image PROFILE=WNDR3700 PACKAGES=&quot;-dnsmasq dnsmasq-full ipset openssh-keygen openssh-server openssh-sftp-server kmod-fs-ext4 kmod-fs-ntfs kmod-fs-vfat kmod-usb2 kmod-usb-core kmod-usb-storage kmod-usb-storage-extras luci-app-firewall luci-app-samba luci-app-upnp luci luci-theme-material curl kmod-ipt-nat-extra libpcre&quot;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p>生成镜像(<code>~/OpenWrt/OpenWrt-ImageBuilder-ar71xx-generic.Linux-x86_64/bin/</code>)</p></li></ol><ul><li>openwrt-ar71xx-generic-wndr3800-squashfs-sysupgrade.bin</li><li>openwrt-ar71xx-generic-wndr3800-squashfs-factory.img</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;😌 整理、记录一下步骤..&lt;/p&gt;</summary>
    
    
    
    <category term="OpenWrt" scheme="https://hocg.in/categories/OpenWrt/"/>
    
    
    <category term="OpenWrt" scheme="https://hocg.in/tags/OpenWrt/"/>
    
  </entry>
  
  <entry>
    <title>制作.ipk安装文件</title>
    <link href="https://hocg.in/2017/11/19/%E5%88%B6%E4%BD%9C.ipk/"/>
    <id>https://hocg.in/2017/11/19/%E5%88%B6%E4%BD%9C.ipk/</id>
    <published>2017-11-19T12:30:21.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p><code>.ipk</code> 本质是<code>tar.gz</code>格式的压缩包, 按照某种规范格式(<code>类似.deb包</code>)进行 …</p><span id="more"></span><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><ol><li><code>.ipk</code> 本质是<code>tar.gz</code>格式的压缩包, 按照某种规范格式(<code>类似.deb包</code>)进行压缩而成的。</li><li>当我们对它的内容进行操作时候所使用的用户即是它安装后所拥有的用户和权限(<code>sudo chown root:root -R .</code>)。</li><li>已经存在的文件并不能进行替换, 切记。</li></ol><h2 id="文件介绍"><a href="#文件介绍" class="headerlink" title="文件介绍"></a>文件介绍</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── control.tar.gz <span class="comment"># 安装/卸载 脚本</span></span><br><span class="line">├── data.tar.gz <span class="comment"># 二进制/配置文件..</span></span><br><span class="line">└── debian-binary <span class="comment"># 固有文件</span></span><br></pre></td></tr></table></figure><h2 id="control-tar-gz-内容"><a href="#control-tar-gz-内容" class="headerlink" title="control.tar.gz 内容"></a>control.tar.gz 内容</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── control <span class="comment"># 文件介绍[包括: 依赖/版本/架构/作者..]</span></span><br><span class="line">├── postinst <span class="comment"># 安装脚本</span></span><br><span class="line">└── postrm <span class="comment"># 卸载脚本</span></span><br></pre></td></tr></table></figure><h3 id="control-此处举个栗子"><a href="#control-此处举个栗子" class="headerlink" title="control 此处举个栗子"></a><code>control</code> 此处举个栗子</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Package: IPKName <span class="comment"># .ipk NAME</span></span><br><span class="line">Version: 1</span><br><span class="line">Section: net</span><br><span class="line">Priority: optional</span><br><span class="line">Architecture: ar71xx <span class="comment"># 系统架构</span></span><br><span class="line">Maintainer: hocgin &lt;hocgin@gmail.com&gt;</span><br><span class="line">Description: my first ipk</span><br></pre></td></tr></table></figure><h3 id="postinst-安装脚本"><a href="#postinst-安装脚本" class="headerlink" title="postinst 安装脚本"></a>postinst 安装脚本</h3><blockquote><p>因为前言的<code>3</code>原因, 当我们需要对已存在文件进行修改时, 只能使用写入的方式进行修改。</p></blockquote><p>例如:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/sh</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;installed done&quot;</span> &gt; /tmp/ipk.log</span><br></pre></td></tr></table></figure><h3 id="postinst-卸载脚本"><a href="#postinst-卸载脚本" class="headerlink" title="postinst 卸载脚本"></a>postinst 卸载脚本</h3><blockquote><p>自己约的X🤣。。</p></blockquote><p>例如:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/sh</span></span><br><span class="line"><span class="built_in">rm</span> -rf /tmp/ipk.log</span><br></pre></td></tr></table></figure><h3 id="打包"><a href="#打包" class="headerlink" title="打包~"></a>打包~</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo tar -czf control.tar.gz *</span><br></pre></td></tr></table></figure><h2 id="data-tar-gz"><a href="#data-tar-gz" class="headerlink" title="data.tar.gz"></a>data.tar.gz</h2><blockquote><p>此处完全是根据你要增加的脚本按根目录进行存放的。</p></blockquote><p>例如:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── bin</span><br><span class="line">│   ├── ss-redir</span><br><span class="line">│   └── ss-tunnel</span><br><span class="line">├── data.tar.gz</span><br><span class="line">├── etc</span><br><span class="line">│   ├── dnsmasq.d</span><br><span class="line">│   │   ├── address.conf</span><br><span class="line">│   │   ├── dns.conf</span><br><span class="line">│   │   ├── ipset.conf</span><br><span class="line">│   │   ├── option.conf</span><br><span class="line">│   │   └── server.conf</span><br><span class="line">│   ├── pdnsd.conf</span><br><span class="line">│   └── shadowsock.json</span><br><span class="line">├── root</span><br><span class="line">│   ├── addDnsmasq.sh</span><br><span class="line">│   └── changeService.sh</span><br><span class="line">└── usr</span><br><span class="line">    └── sbin</span><br><span class="line">        └── pdnsd</span><br></pre></td></tr></table></figure><h3 id="打包-1"><a href="#打包-1" class="headerlink" title="打包~"></a>打包~</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo tar -czf data.tar.gz *</span><br></pre></td></tr></table></figure><h2 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h2><blockquote><p>将三个文件放在一起进行打包</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo tar -czf mIPK.ipk *</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;code&gt;.ipk&lt;/code&gt; 本质是&lt;code&gt;tar.gz&lt;/code&gt;格式的压缩包, 按照某种规范格式(&lt;code&gt;类似.deb包&lt;/code&gt;)进行 …&lt;/p&gt;</summary>
    
    
    
    <category term="OpenWrt" scheme="https://hocg.in/categories/OpenWrt/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="OpenWrt" scheme="https://hocg.in/tags/OpenWrt/"/>
    
    <category term="Shell" scheme="https://hocg.in/tags/Shell/"/>
    
  </entry>
  
  <entry>
    <title>IDEA 中的 Spring Boot 开发模式</title>
    <link href="https://hocg.in/2017/10/20/IDEA-%E4%B8%AD%E7%9A%84-Spring-Boot-%E5%BC%80%E5%8F%91%E6%A8%A1%E5%BC%8F/"/>
    <id>https://hocg.in/2017/10/20/IDEA-%E4%B8%AD%E7%9A%84-Spring-Boot-%E5%BC%80%E5%8F%91%E6%A8%A1%E5%BC%8F/</id>
    <published>2017-10-20T23:28:09.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>🤑 完全热部署, 配置完成瞬间舒爽无比。</p><span id="more"></span><h2 id="java-文件和配置文件更改后进行自动重启"><a href="#java-文件和配置文件更改后进行自动重启" class="headerlink" title=".java 文件和配置文件更改后进行自动重启"></a><code>.java</code> 文件和配置文件更改后进行自动重启</h2><ol><li>更改<code>IDEA</code>中的如下设置<code>Build project automatically</code>。</li></ol><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-10-19%2022.30.09.png" alt="屏幕快照 2017-10-19 22.30.09.png"></p><ol start="2"><li>打开<code>IDEA</code>的<code>Action window</code>, 快捷键如下:</li></ol><ul><li>Linux : <code>CTRL+SHIFT+A</code></li><li>Mac OSX : <code>SHIFT+COMMAND+A</code></li><li>Windows : <code>CTRL+ALT+SHIFT+/</code><br>输入(选择) <code>Registry...</code>, 选择如下:</li></ul><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-10-19%2022.36.39.png" alt="屏幕快照 2017-10-19 22.36.39.png"></p><p>此时进行<code>.java</code> 文件和配置文件修改时, 会进行 Spring Boot 重启。</p><h2 id="当更改静态HTML进行实时刷新"><a href="#当更改静态HTML进行实时刷新" class="headerlink" title="当更改静态HTML进行实时刷新"></a>当更改静态<code>HTML</code>进行实时刷新</h2><ol><li>加入依赖</li></ol><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-devtools<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><ol start="2"><li>安装浏览器插件</li></ol><ul><li><p><a href="https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei">Chrome 插件</a></p></li><li><p><a href="https://addons.mozilla.org/en-US/firefox/addon/livereload/">Firefox 插件</a></p></li><li><p><a href="http://download.livereload.com/2.1.0/LiveReload-2.1.0.safariextz">Safari 插件</a></p></li></ul><ol start="3"><li>更改文件和静态页面(HTML)都可以进行热部署类。</li></ol><h2 id="实时刷新thymeleaf模版文件"><a href="#实时刷新thymeleaf模版文件" class="headerlink" title="实时刷新thymeleaf模版文件"></a>实时刷新<code>thymeleaf</code>模版文件</h2><p>配置文件设置取消缓存:</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">    <span class="attr">thymeleaf:</span></span><br><span class="line">        <span class="attr">cache:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure><p>Chrome 设置取消缓存:</p><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-10-19%2022.46.23.png" alt="屏幕快照 2017-10-19 22.46.23.png"></p><p>此时几乎所有的东西(<code>.java</code>&#x2F;&#96;&#96;&#x2F;<code>SpringBoot 配置文件</code>)都可以进行热部署了。<br>包括:</p><ul><li>修改 <code>.java</code> 文件。</li><li>修改页面(<code>thymeleaf</code> <code>html</code> <code>..</code>) 文件。</li><li>修改 <code>SpringBoot 配置文件</code>。</li><li>增删静态文件(<code>css</code> <code>js</code> <code>图片</code>)。</li></ul><h2 id="关于定制化热部署"><a href="#关于定制化热部署" class="headerlink" title="关于定制化热部署"></a>关于定制化热部署</h2><p> 可查询<code>spring-boot-devtools</code>的使用, 使用以下子项进行配置。<br> <figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">   <span class="attr">devtools:</span></span><br></pre></td></tr></table></figure></p><h2 id="IDEA-扩展"><a href="#IDEA-扩展" class="headerlink" title="IDEA 扩展"></a>IDEA 扩展</h2><blockquote><p>pom.xml 添加以下依赖可查看更多的信息。<br>该依赖是可查看监控信息的, 更多使用移步 Google.com。</p></blockquote> <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-actuator<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>IDEA 显示如下:</p><p> <img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-10-29%2014.18.38.png" alt="屏幕快照 2017-10-29 14.18.38.png"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;🤑 完全热部署, 配置完成瞬间舒爽无比。&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="Ubuntu" scheme="https://hocg.in/tags/Ubuntu/"/>
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="SpringBoot" scheme="https://hocg.in/tags/SpringBoot/"/>
    
  </entry>
  
  <entry>
    <title>JQuery.pjax 无法再次初始化当前页面的JS</title>
    <link href="https://hocg.in/2017/10/19/JQuery.pjax%E6%97%A0%E6%B3%95%E5%86%8D%E6%AC%A1%E5%88%9D%E5%A7%8B%E5%8C%96%E5%BD%93%E5%89%8D%E9%A1%B5%E9%9D%A2%E7%9A%84JS/"/>
    <id>https://hocg.in/2017/10/19/JQuery.pjax%E6%97%A0%E6%B3%95%E5%86%8D%E6%AC%A1%E5%88%9D%E5%A7%8B%E5%8C%96%E5%BD%93%E5%89%8D%E9%A1%B5%E9%9D%A2%E7%9A%84JS/</id>
    <published>2017-10-19T22:07:20.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>Pjax 很久之前用过一次, 这一次在整合后台模版，发现网上对这个坑竟然是改源码…在这详细记录一下。</p><span id="more"></span><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>当 <code>JQuery.pjax</code> 加载页面后, 再次加载该页面时，其内部的初始化 <code>JS</code> 或 <code>script inline</code> 并不能被再次执行。例如:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;pjax-container&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- .. --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- jQuery 3 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">th:src</span>=<span class="string">&quot;jquery.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- jQuery Pjax --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">th:src</span>=<span class="string">&quot;jquery.pjax.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        $(<span class="variable language_">document</span>).<span class="title function_">ready</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">if</span> ($.support.<span class="property">pjax</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                $(<span class="variable language_">document</span>).<span class="title function_">pjax</span>(<span class="string">&#x27;a[data-pjax]&#x27;</span>, <span class="string">&#x27;#pjax-container&#x27;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">maxCacheLength</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">push</span>: <span class="literal">false</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">replace</span>: <span class="literal">true</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">fragment</span>: <span class="string">&#x27;#pjax-container&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">timeout</span>: <span class="number">8000</span></span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    $(<span class="keyword">function</span>(<span class="params"></span>)&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;不能被再次执行&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">    &#125;);</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 不能被再次执行 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>  <span class="attr">src</span>=<span class="string">&quot;init.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h2><ol><li>其原因是<code>JQuery.pjax</code>对<code>js</code>进行了缓存, 可以使用<code>JQuery</code>进行加载, 当然其代价是牺牲了这部分都缓存, 不过因为是特定页面的脚本, 牺牲的缓存几乎可以忽略。例子如下:<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;pjax-container&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- .. --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 能被再次执行 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">th:inline</span>=<span class="string">&quot;javascript&quot;</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">            $.<span class="title function_">getScript</span>(<span class="string">&#x27;/admin-lte/dist/js/pages/dashboard2.js&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>  <span class="attr">src</span>=<span class="string">&quot;init.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        $(<span class="keyword">function</span>(<span class="params"></span>)&#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;能被再次执行&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- jQuery 3 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">th:src</span>=<span class="string">&quot;jquery.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- jQuery Pjax --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">th:src</span>=<span class="string">&quot;jquery.pjax.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        $(<span class="variable language_">document</span>).<span class="title function_">ready</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">if</span> ($.support.<span class="property">pjax</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                $(<span class="variable language_">document</span>).<span class="title function_">pjax</span>(<span class="string">&#x27;a[data-pjax]&#x27;</span>, <span class="string">&#x27;#pjax-container&#x27;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">maxCacheLength</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">push</span>: <span class="literal">false</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">replace</span>: <span class="literal">true</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">fragment</span>: <span class="string">&#x27;#pjax-container&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">timeout</span>: <span class="number">8000</span></span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;Pjax 很久之前用过一次, 这一次在整合后台模版，发现网上对这个坑竟然是改源码…在这详细记录一下。&lt;/p&gt;</summary>
    
    
    
    <category term="Web" scheme="https://hocg.in/categories/Web/"/>
    
    
    <category term="JavaScript" scheme="https://hocg.in/tags/JavaScript/"/>
    
    <category term="Pjax" scheme="https://hocg.in/tags/Pjax/"/>
    
  </entry>
  
  <entry>
    <title>Thymeleaf 3.0 手册</title>
    <link href="https://hocg.in/2017/10/18/Thymeleaf-3.0-%E6%89%8B%E5%86%8C/"/>
    <id>https://hocg.in/2017/10/18/Thymeleaf-3.0-%E6%89%8B%E5%86%8C/</id>
    <published>2017-10-18T16:40:51.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>Spring 官方推崇的模版引擎，遵循 HTML5规范。</p><span id="more"></span><h2 id="HTML5"><a href="#HTML5" class="headerlink" title="HTML5"></a>HTML5</h2><p>若要完全遵循HTML5规范，可使用 <code>data-th-*</code> 代替 <code>th:*</code>。</p><h2 id="标签"><a href="#标签" class="headerlink" title="标签"></a>标签</h2><h3 id="th-each"><a href="#th-each" class="headerlink" title="th:each"></a>th:each</h3><blockquote><p>foreach 循环<br>语法: th:each&#x3D;”obj, index:list”</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">th:block</span> <span class="attr">th:each</span>=<span class="string">&quot;permission, i:$&#123;role.permissions&#125;&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tr</span> <span class="attr">th:attr</span>=<span class="string">&quot;data-tt-id=$&#123;permission.id&#125;, data-tt-parent-id=$&#123;permission.parent&#125;, data-tt-branch=$&#123;permission.hasChildren&#125;&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;permission.name&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;permission.url&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;permission.type&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;permission.permission&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">th:block</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="th-inline"><a href="#th-inline" class="headerlink" title="th:inline"></a>th:inline</h3><blockquote><p>解析内嵌语法, 一般是混合javascript<br>语法: th:inline&#x3D;”javascript|text|none”</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">th:inline</span>=<span class="string">&quot;javascript&quot;</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">/*&lt;![CDATA[*/</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">var welcome = [[$&#123;welcome&#125;]] &#x27;这是一个 Thymeleaf 变量&#x27;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">var default_value = [[$&#123;maxCount?:0&#125;]]</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">/*]]&gt;*/</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="th-fragment"><a href="#th-fragment" class="headerlink" title="th:fragment"></a>th:fragment</h3><blockquote><p>定义模版，语法: th:fragment&#x3D;”模块名(变量)”<br>变量部分为可选, 配合 th:with 使用。</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 不保留本身的标签, 保留 th:fragment 的标签 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:replace</span>=<span class="string">&quot;/admin/fragments/header::header&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 保留本身的标签, 保留 th:fragment 的标签 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:insert</span>=<span class="string">&quot;/admin/fragments/header::header&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- @过期, 保留本身的标签, 不保留 th:fragment 的标签 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:include</span>=<span class="string">&quot;/admin/fragments/header::header&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="th-with"><a href="#th-with" class="headerlink" title="th:with"></a>th:with</h3><blockquote><p>定义变量。语法: th:with&#x3D;”字段1&#x3D;值, 字段2&#x3D;值2”</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:with</span>=<span class="string">&quot;id=&#x27;UploadImage&#x27;,var=&#x27;image&#x27;,height=1,maxCount=1&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="th-if"><a href="#th-if" class="headerlink" title="th:if"></a>th:if</h3><blockquote><p>就是 if ..</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:if</span>=<span class="string">&quot;$&#123;true&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- </span></span><br><span class="line"><span class="comment">    布尔值.</span></span><br><span class="line"><span class="comment">    0 = false</span></span><br><span class="line"><span class="comment">    &quot;false&quot;/&quot;off&quot;/&quot;no&quot; = false</span></span><br><span class="line"><span class="comment">    null = false</span></span><br><span class="line"><span class="comment"> --&gt;</span></span><br></pre></td></tr></table></figure><h3 id="th-switch-x2F-th-case"><a href="#th-switch-x2F-th-case" class="headerlink" title="th:switch&#x2F;th:case"></a>th:switch&#x2F;th:case</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span> <span class="attr">th:switch</span>=<span class="string">&quot;$&#123;val&#125;&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">th:case</span>=<span class="string">&quot;1&quot;</span>&gt;</span>1<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">th:case</span>=<span class="string">&quot;2&quot;</span>&gt;</span>2<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="th-selected"><a href="#th-selected" class="headerlink" title="th:selected"></a>th:selected</h3><blockquote><p>可用于 <option/> 标签</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">class</span>=<span class="string">&quot;form-control&quot;</span> <span class="attr">id</span>=<span class="string">&quot;type&quot;</span> <span class="attr">name</span>=<span class="string">&quot;type&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">option</span> <span class="attr">value</span>=<span class="string">&quot;0&quot;</span> <span class="attr">th:selected</span>=<span class="string">&quot;$&#123;permission?.type==0&#125;&quot;</span>&gt;</span>菜单<span class="tag">&lt;/<span class="name">option</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">option</span> <span class="attr">value</span>=<span class="string">&quot;1&quot;</span> <span class="attr">th:selected</span>=<span class="string">&quot;$&#123;permission?.type==1&#125;&quot;</span>&gt;</span>数据<span class="tag">&lt;/<span class="name">option</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="注释语法"><a href="#注释语法" class="headerlink" title="注释语法"></a>注释语法</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--/* 这里是 编译器显示为注释, 浏览器不可见 */--&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--/*--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span>这里是 编译器显示不注释，浏览器不可见 <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--*/--&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--/*/</span></span><br><span class="line"><span class="comment">&lt;div th:text=&quot;$&#123;&#x27;这里是 编辑器显示为注释, 浏览器可见&#x27;&#125;&quot;&gt;...&lt;/div&gt;</span></span><br><span class="line"><span class="comment">/*/--&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="表达式"><a href="#表达式" class="headerlink" title="表达式"></a>表达式</h2><h3 id="URL-表达式"><a href="#URL-表达式" class="headerlink" title="URL 表达式"></a>URL 表达式</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">th:src</span>=<span class="string">&quot;@&#123;/img/tup.png&#125;&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;绝对路径&quot;</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;img alt=&quot;绝对路径&quot; src=&quot;/img/tup.png&quot;&gt; --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">th:src</span>=<span class="string">&quot;@&#123;../img/tup.png&#125;&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;相对路径&quot;</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;img alt=&quot;相对路径&quot; src=&quot;../img/tup.png&quot;&gt; --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">th:src</span>=<span class="string">&quot;@&#123;../img/tup.png(size=$&#123;100&#125;)&#125;&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;带参数的路径&quot;</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;img alt=&quot;带参数的路径&quot; src=&quot;../img/tup.png?size=100&quot;&gt; --&gt;</span></span><br></pre></td></tr></table></figure><h3 id="国际化表达式"><a href="#国际化表达式" class="headerlink" title="国际化表达式"></a>国际化表达式</h3><ol><li>创建 <code>resources/messages_zh_CN.properties</code>, 其内容:</li></ol><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">message.error=错误</span><br></pre></td></tr></table></figure><ol start="2"><li>配置 <code>application.yml</code> (使用 xml 的执行转换)</li></ol><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">messages:</span></span><br><span class="line">    <span class="attr">basename:</span> <span class="string">messages_zh_CN</span></span><br></pre></td></tr></table></figure><ol start="3"><li>使用</li></ol><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:text</span>=<span class="string">&quot;#&#123;message.error&#125;&quot;</span>&gt;</span>Error<span class="tag">&lt;/<span class="name">div</span>&gt;</span> </span><br></pre></td></tr></table></figure><h3 id="变量表达式"><a href="#变量表达式" class="headerlink" title="变量表达式"></a>变量表达式</h3><blockquote><p>最基本的表达式, 类似于 EL 表达式。</p><ul><li>合 <code>org.springframework.ui.Model</code> 使用。</li><li>可以使用众多内置对象。</li><li>@访问 Spring 容器内对象</li></ul></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;author.name&#125;&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="变量表达式-扩展-1"><a href="#变量表达式-扩展-1" class="headerlink" title="变量表达式 - 扩展 1"></a>变量表达式 - 扩展 1</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span> <span class="attr">th:object</span>=<span class="string">&quot;$&#123;author&#125;&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">th:text</span>=<span class="string">&quot;*&#123;name&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">th:text</span>=<span class="string">&quot;*&#123;mail&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">th:text</span>=<span class="string">&quot;*&#123;address&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment">    等价于</span></span><br><span class="line"><span class="comment">    &lt;ul&gt;</span></span><br><span class="line"><span class="comment">        &lt;li th:text=&quot;$&#123;author.name&#125;&quot;&gt;&lt;/li&gt;</span></span><br><span class="line"><span class="comment">        &lt;li th:text=&quot;$&#123;author.mail&#125;&quot;&gt;&lt;/li&gt;</span></span><br><span class="line"><span class="comment">        &lt;li th:text=&quot;$&#123;author.address&#125;&quot;&gt;&lt;/li&gt;</span></span><br><span class="line"><span class="comment">    &lt;/ul&gt;</span></span><br><span class="line"><span class="comment">--&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="变量表达式-扩展-2"><a href="#变量表达式-扩展-2" class="headerlink" title="变量表达式 - 扩展 2"></a>变量表达式 - 扩展 2</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;@demoService.getStr(&#x27;hocgin&#x27;)&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="预处理表达式"><a href="#预处理表达式" class="headerlink" title="预处理表达式"></a>预处理表达式</h3><ol><li>前置设置, Controller</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping(&#123;&quot;/test.html&quot;&#125;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">index</span><span class="params">(Model model, <span class="meta">@PathVariable</span> String page)</span> &#123;</span><br><span class="line">    model.addAttribute(<span class="string">&quot;key&quot;</span>, <span class="string">&quot;error&quot;</span>);</span><br><span class="line">    HashMap&lt;String, String&gt; vm = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line">    vm.put(<span class="string">&quot;error&quot;</span>, <span class="string">&quot;来自 $&#123;&#125; 表达式&quot;</span>);</span><br><span class="line">    model.addAttribute(<span class="string">&quot;obj&quot;</span>, vm);</span><br><span class="line">    <span class="keyword">return</span> String.format(<span class="string">&quot;test.html&quot;</span>, page);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>前置设置, <code>messages_zh_CN.properties</code> 参考<strong>国际化表达式</strong></li></ol><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">message.error</span>=<span class="string">错误</span></span><br></pre></td></tr></table></figure><ol start="3"><li>test.html 编写</li></ol><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/img/__$&#123;1+1&#125;__&#125;&quot;</span>&gt;</span>连接<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;a href=&quot;/img/2&quot;&gt;连接&lt;/a&gt; --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:text</span>=<span class="string">&quot;#&#123;message.__$&#123;key&#125;__&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;div&gt;错误&lt;/div&gt; --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;obj.__$&#123;key&#125;__&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;div&gt;来自 $&#123;&#125; 表达式&lt;/div&gt; --&gt;</span></span><br></pre></td></tr></table></figure><h3 id="Fragment-表达式"><a href="#Fragment-表达式" class="headerlink" title="Fragment 表达式"></a>Fragment 表达式</h3><blockquote><p>~{…}</p></blockquote><h2 id="表达式语法"><a href="#表达式语法" class="headerlink" title="表达式语法"></a>表达式语法</h2><h3 id="字符串拼接"><a href="#字符串拼接" class="headerlink" title="字符串拼接"></a>字符串拼接</h3><p>使用 <code>+</code> 或者 <code>|..|</code></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;&#x27;1+1=&#x27; + $&#123;1+1&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 1+1=2 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;|1+1=$&#123;1+1&#125;|&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 1+1=2 --&gt;</span></span><br></pre></td></tr></table></figure><h3 id="运算符号"><a href="#运算符号" class="headerlink" title="运算符号"></a>运算符号</h3><p>使用 <code>+, -, *, /, %</code>。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;-((1+1-1)*2/2)%9&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- -1 --&gt;</span></span><br></pre></td></tr></table></figure><h3 id="与-或-非"><a href="#与-或-非" class="headerlink" title="与 或 非"></a>与 或 非</h3><p>使用 <code>and , or</code> 和 <code>! , not</code>。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;1==1 and true&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- true --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;true and false&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- false --&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;true or false&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- true --&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;not true&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- false --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;! false&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- true --&gt;</span></span><br></pre></td></tr></table></figure><h3 id="关系表达式"><a href="#关系表达式" class="headerlink" title="关系表达式"></a>关系表达式</h3><p>使用 <code>&gt;, &lt;, &gt;=, &lt;=, ==, !=</code>。<br>或者 <code>gt, lt, ge, le, eq, ne</code>。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;((1 &gt; 2 and 2 &lt; 3) or (2 &gt;= 2 and 2 &lt;= 5)) and (1 == 1 and 1 != 2)&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- true --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;((1 gt 2 and 2 lt 3) or (2 ge 2 and 2 le 5)) and (1 eq 1 and 1 ne 2)&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- true --&gt;</span></span><br></pre></td></tr></table></figure><h3 id="简单条件表达式"><a href="#简单条件表达式" class="headerlink" title="简单条件表达式"></a>简单条件表达式</h3><p>使用:<br>if-then <code>(if) ? (then)</code><br>if-then-else <code>(if) ? (then) : (else)</code><br>default <code>(value) ?: (defaultValue)</code>  </p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;true ? &#x27;hocgin&#x27;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- hocgin --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;false ? &#x27;hocgin&#x27; : &#x27;hocg.in&#x27;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- hocg.in --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;iname&#125; ?: &#x27;hocgin&#x27;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- hocgin --&gt;</span></span><br></pre></td></tr></table></figure><h2 id="解析优先级"><a href="#解析优先级" class="headerlink" title="解析优先级"></a>解析优先级</h2><table><thead><tr><th>级别</th><th>描述</th><th>th属性</th></tr></thead><tbody><tr><td>1</td><td>(Fragment inclusion)代码片段导入</td><td><code>th:insert</code>,<code>th:replace</code></td></tr><tr><td>2</td><td>(Fragment iteration)迭代</td><td><code>th:each</code></td></tr><tr><td>3</td><td>(Conditional evaluation)条件</td><td><code>th:if</code>,<code>th:unless</code>,<code>th:switch</code>,<code>th:case</code></td></tr><tr><td>4</td><td>(Local variable definition)局部变量</td><td><code>th:object</code>,<code>th:with</code></td></tr><tr><td>5</td><td>(General attribute modification)通用属性修改</td><td><code>th:attr</code>,<code>th:attrprepend</code>,<code>th:attrappend</code></td></tr><tr><td>6</td><td>(Specific attribute modification)具体属性修改</td><td><code>th:value</code>,<code>th:href</code>,<code>th:src</code> …</td></tr><tr><td>7</td><td>(Text tag body modification) 文本节点修改</td><td><code>th:text</code>,<code>th:utext</code></td></tr><tr><td>8</td><td>(Fragment specification) 代码段定义</td><td><code>th:fragment</code></td></tr><tr><td>9</td><td>(Fragment removal) 代码段删除</td><td><code>th:remove</code></td></tr></tbody></table><h2 id="基础对象"><a href="#基础对象" class="headerlink" title="基础对象"></a>基础对象</h2><h3 id="ctx-org-thymeleaf-spring4-context-SpringWebContext"><a href="#ctx-org-thymeleaf-spring4-context-SpringWebContext" class="headerlink" title="#ctx (org.thymeleaf.spring4.context.SpringWebContext)"></a><code>#ctx</code> (org.thymeleaf.spring4.context.SpringWebContext)</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * org.thymeleaf.context.IContext</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="comment">// 当前语言环境(eg. en_US)。 等价于 &#123;#locale&#125;</span></span><br><span class="line">$&#123;#ctx.locale&#125;</span><br><span class="line"><span class="comment">// org.thymeleaf.context.VariablesMap 对象, 内部存储的是可用于当前上下文(Context)的对象。等价于 &#123;#vars&#125;</span></span><br><span class="line">$&#123;#ctx.variables&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * org.thymeleaf.context.IWebContext</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line">$&#123;#ctx.applicationAttributes&#125;</span><br><span class="line"><span class="comment">// 等价于 &#123;#httpServletRequest&#125;</span></span><br><span class="line">$&#123;#ctx.httpServletRequest&#125;</span><br><span class="line">$&#123;#ctx.httpServletResponse&#125;</span><br><span class="line"><span class="comment">// 等价于 &#123;#httpSession&#125;</span></span><br><span class="line">$&#123;#ctx.httpSession&#125;</span><br><span class="line">$&#123;#ctx.requestAttributes&#125;</span><br><span class="line">$&#123;#ctx.requestParameters&#125;</span><br><span class="line">$&#123;#ctx.servletContext&#125;</span><br><span class="line">$&#123;#ctx.sessionAttributes&#125;</span><br></pre></td></tr></table></figure><h3 id="param-org-apache-catalina-util-ParameterMap"><a href="#param-org-apache-catalina-util-ParameterMap" class="headerlink" title="param (org.apache.catalina.util.ParameterMap)"></a><code>param</code> (org.apache.catalina.util.ParameterMap)</h3><p>包含当前页面的请求的参数(eg. <code>http://localhost:8080/admin/test.html?name=hocgin</code>)。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 返回对象</span></span><br><span class="line">$&#123;param.name&#125; </span><br><span class="line"><span class="comment">// 获得值: hocgin</span></span><br><span class="line">$&#123;param.name[<span class="number">0</span>]&#125; </span><br><span class="line">$&#123;param.size()&#125;</span><br><span class="line">$&#123;param.isEmpty()&#125;</span><br><span class="line">$&#123;param.containsKey(<span class="string">&#x27;name&#x27;</span>)&#125;</span><br></pre></td></tr></table></figure><h3 id="session-org-thymeleaf-context-WebSessionVariablesMap"><a href="#session-org-thymeleaf-context-WebSessionVariablesMap" class="headerlink" title="session (org.thymeleaf.context.WebSessionVariablesMap)"></a><code>session</code> (org.thymeleaf.context.WebSessionVariablesMap)</h3><p>从 Session 获取内容。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获得值: hocgin</span></span><br><span class="line">$&#123;session.name&#125;</span><br><span class="line">$&#123;session.size()&#125;</span><br><span class="line">$&#123;session.isEmpty()&#125;</span><br><span class="line">$&#123;session.containsKey(<span class="string">&#x27;name&#x27;</span>)&#125;</span><br></pre></td></tr></table></figure><h3 id="httpServletRequest-org-apache-catalina-connector-RequestFacade"><a href="#httpServletRequest-org-apache-catalina-connector-RequestFacade" class="headerlink" title="#httpServletRequest (org.apache.catalina.connector.RequestFacade)"></a><code>#httpServletRequest</code> (org.apache.catalina.connector.RequestFacade)</h3><h3 id="themes-org-thymeleaf-spring4-expression-Themes"><a href="#themes-org-thymeleaf-spring4-expression-Themes" class="headerlink" title="#themes (org.thymeleaf.spring4.expression.Themes)"></a><code>#themes</code> (org.thymeleaf.spring4.expression.Themes)</h3><h3 id="application"><a href="#application" class="headerlink" title="application"></a><code>application</code></h3><h3 id="dates-org-thymeleaf-expression-Dates"><a href="#dates-org-thymeleaf-expression-Dates" class="headerlink" title="#dates (org.thymeleaf.expression.Dates)"></a><code>#dates</code> (org.thymeleaf.expression.Dates)</h3><h3 id="calendars-org-thymeleaf-expression-Calendars"><a href="#calendars-org-thymeleaf-expression-Calendars" class="headerlink" title="#calendars (org.thymeleaf.expression.Calendars)"></a><code>#calendars</code> (org.thymeleaf.expression.Calendars)</h3><h3 id="numbers-org-thymeleaf-expression-Numbers"><a href="#numbers-org-thymeleaf-expression-Numbers" class="headerlink" title="#numbers (org.thymeleaf.expression.Numbers)"></a><code>#numbers</code> (org.thymeleaf.expression.Numbers)</h3><h3 id="strings-org-thymeleaf-expression-Strings"><a href="#strings-org-thymeleaf-expression-Strings" class="headerlink" title="#strings (org.thymeleaf.expression.Strings)"></a><code>#strings</code> (org.thymeleaf.expression.Strings)</h3><h3 id="objects-org-thymeleaf-expression-Objects"><a href="#objects-org-thymeleaf-expression-Objects" class="headerlink" title="#objects (org.thymeleaf.expression.Objects)"></a><code>#objects</code> (org.thymeleaf.expression.Objects)</h3><h3 id="bools-org-thymeleaf-expression-Bools"><a href="#bools-org-thymeleaf-expression-Bools" class="headerlink" title="#bools (org.thymeleaf.expression.Bools)"></a><code>#bools</code> (org.thymeleaf.expression.Bools)</h3><h3 id="arrays-org-thymeleaf-expression-Arrays"><a href="#arrays-org-thymeleaf-expression-Arrays" class="headerlink" title="#arrays (org.thymeleaf.expression.Arrays)"></a><code>#arrays</code> (org.thymeleaf.expression.Arrays)</h3><h3 id="lists-org-thymeleaf-expression-Lists"><a href="#lists-org-thymeleaf-expression-Lists" class="headerlink" title="#lists (org.thymeleaf.expression.Lists)"></a><code>#lists</code> (org.thymeleaf.expression.Lists)</h3><h3 id="sets-org-thymeleaf-expression-Sets"><a href="#sets-org-thymeleaf-expression-Sets" class="headerlink" title="#sets (org.thymeleaf.expression.Sets)"></a><code>#sets</code> (org.thymeleaf.expression.Sets)</h3><h3 id="maps-org-thymeleaf-expression-Maps"><a href="#maps-org-thymeleaf-expression-Maps" class="headerlink" title="#maps (org.thymeleaf.expression.Maps)"></a><code>#maps</code> (org.thymeleaf.expression.Maps)</h3><h3 id="aggregates-org-thymeleaf-expression-Aggregates"><a href="#aggregates-org-thymeleaf-expression-Aggregates" class="headerlink" title="#aggregates (org.thymeleaf.expression.Aggregates)"></a><code>#aggregates</code> (org.thymeleaf.expression.Aggregates)</h3><h3 id="messages-org-thymeleaf-expression-Messages"><a href="#messages-org-thymeleaf-expression-Messages" class="headerlink" title="#messages (org.thymeleaf.expression.Messages)"></a><code>#messages</code> (org.thymeleaf.expression.Messages)</h3><h3 id="ids-org-thymeleaf-expression-Ids"><a href="#ids-org-thymeleaf-expression-Ids" class="headerlink" title="#ids (org.thymeleaf.expression.Ids)"></a><code>#ids</code> (org.thymeleaf.expression.Ids)</h3><p><strong>代码示例</strong></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><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">### `#locale` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#locale&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#ctx` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#ctx&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#vars` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#vars&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line"></span><br><span class="line">### `param` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;param&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `application` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;application&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `session` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;session&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#httpSession` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#httpSession&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#httpServletRequest` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#httpServletRequest&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line"></span><br><span class="line">### `#themes` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#themes&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#dates` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#dates&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#calendars` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#calendars&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#numbers` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#numbers&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#strings` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#strings&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#objects` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#objects&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#bools` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#bools&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#arrays` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#arrays&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#lists` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#lists&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#sets` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#sets&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#maps` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#maps&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#aggregates` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#aggregates&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#messages` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#messages&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">### `#ids` (<span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;#ids&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span>)<span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="重点"><a href="#重点" class="headerlink" title="重点"></a>重点</h2><ul><li>在 <code>thymeleaf</code> 中使用 Spring 容器内的单例.</li></ul><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;@demoService.getStr(&#x27;hocgin&#x27;)&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>引入模版片段</li></ul><ol><li><p>XPath 表达式</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:include</span>=<span class="string">&quot;mytemplate :: [//div[@class=&#x27;content&#x27;]]&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>CSS 表达式</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:include</span>=<span class="string">&quot;mytemplate :: [div.content]&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><ul><li>引入公有片段(JS 或 CSS)</li></ul><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">css</span> <span class="attr">th:replace</span>=<span class="string">&quot;mytemplate :: common-css&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">css</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">js</span> <span class="attr">th:replace</span>=<span class="string">&quot;@&#123;mytemplate&#125; :: common-css&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">js</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 可结合 路径表达式 --&gt;</span></span><br></pre></td></tr></table></figure><h2 id="扩展"><a href="#扩展" class="headerlink" title="扩展"></a>扩展</h2><h3 id="thymeleaf-layout-dialect"><a href="#thymeleaf-layout-dialect" class="headerlink" title="thymeleaf-layout-dialect"></a>thymeleaf-layout-dialect</h3><blockquote><p>一般情况网站都有一个外部框架, 如 header 或者 footer, 这个扩展便是用于抽离那些重复的部分的。</p></blockquote><h4 id="layout-decorator"><a href="#layout-decorator" class="headerlink" title="layout:decorator"></a>layout:decorator</h4><blockquote><p>指定需使用的父级模版</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">xmlns:th</span>=<span class="string">&quot;http://www.thymeleaf.org&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">xmlns:layout</span>=<span class="string">&quot;http://www.ultraq.net.nz/thymeleaf/layout&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">layout:decorator</span>=<span class="string">&quot;/admin/_layouts/default&quot;</span>&gt;</span></span><br><span class="line">      ...</span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h4 id="layout-fragment"><a href="#layout-fragment" class="headerlink" title="layout:fragment"></a>layout:fragment</h4><blockquote><p>在父模版中使用定义一个标记，<br>在子模版中使用覆盖到父模版位置。</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 父 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">layout:fragment</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>父模版内容<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 子 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">layout:fragment</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>子模版内容<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 生成 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>子模版内容<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><h4 id="layout-title-pattern"><a href="#layout-title-pattern" class="headerlink" title="layout:title-pattern"></a>layout:title-pattern</h4><blockquote><p>用与 <title/> 标签, 指定 title 的值。</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 后台 - 子标题 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">title</span> <span class="attr">layout:title-pattern</span>=<span class="string">&quot;$DECORATOR_TITLE - $CONTENT_TITLE&quot;</span>&gt;</span>后台<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="黑科技"><a href="#黑科技" class="headerlink" title="黑科技"></a>黑科技</h2><ol><li>当我们想取一个对象里面的一个属性, 但这个对象可能为空时(😋)。<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;user?.address?.city&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;Spring 官方推崇的模版引擎，遵循 HTML5规范。&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="HTML5" scheme="https://hocg.in/tags/HTML5/"/>
    
    <category term="Thymeleaf" scheme="https://hocg.in/tags/Thymeleaf/"/>
    
  </entry>
  
  <entry>
    <title>JDK8 新特性的使用</title>
    <link href="https://hocg.in/2017/10/10/JDK8%20%E6%96%B0%E7%89%B9%E6%80%A7%E7%9A%84%E4%BD%BF%E7%94%A8/"/>
    <id>https://hocg.in/2017/10/10/JDK8%20%E6%96%B0%E7%89%B9%E6%80%A7%E7%9A%84%E4%BD%BF%E7%94%A8/</id>
    <published>2017-10-10T10:02:00.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>JDK8 新特性的使用</p><span id="more"></span><h2 id="JDK8-新特性"><a href="#JDK8-新特性" class="headerlink" title="JDK8 新特性"></a>JDK8 新特性</h2><h3 id="Lambda-表达式-amp-amp-FunctionalInterface"><a href="#Lambda-表达式-amp-amp-FunctionalInterface" class="headerlink" title="Lambda 表达式 &amp;&amp; @FunctionalInterface"></a>Lambda 表达式 &amp;&amp; @FunctionalInterface</h3><p>Java8 支持了 Lambda 表达式，语法如下:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 标准式</span></span><br><span class="line">(形参) -&gt; &#123;</span><br><span class="line">..代码</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 简化式</span></span><br><span class="line">() -&gt; System.out.print(<span class="string">&quot;简化式&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 案例：</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; System.out.print(<span class="string">&quot;run&quot;</span>)).run();</span><br></pre></td></tr></table></figure><p>由于 Lambda 表达式是对<code>单个函数的接口(interface)</code>进行简化处理，即要保证接口不能存在后续新增函数声明，这时就需要引入 @FunctionalInterface 进行注解。<br>以下是 Java8 下 Runable 接口的声明：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@FunctionalInterface</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * When an object implementing interface &lt;code&gt;Runnable&lt;/code&gt; is used</span></span><br><span class="line"><span class="comment">     * to create a thread, starting the thread causes the object&#x27;s</span></span><br><span class="line"><span class="comment">     * &lt;code&gt;run&lt;/code&gt; method to be called in that separately executing</span></span><br><span class="line"><span class="comment">     * thread.</span></span><br><span class="line"><span class="comment">     * &lt;p&gt;</span></span><br><span class="line"><span class="comment">     * The general contract of the method &lt;code&gt;run&lt;/code&gt; is that it may</span></span><br><span class="line"><span class="comment">     * take any action whatsoever.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span>     java.lang.Thread#run()</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注: @FunctionalInterface 接口内允许有<strong>静态函数实现</strong>和<strong>默认函数实现</strong>。</p></blockquote><h2 id="即如下这也是-Java8-interface-中的新特性。"><a href="#即如下这也是-Java8-interface-中的新特性。" class="headerlink" title="即如下这也是 Java8 interface 中的新特性。"></a>即如下<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> <span class="title class_">R2</span> <span class="keyword">extends</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 默认函数实现</span></span><br><span class="line"><span class="keyword">default</span> String <span class="title function_">to</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">return</span> getClass().toString();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 静态函数实现</span></span><br><span class="line"><span class="keyword">static</span> String <span class="title function_">in</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="string">&quot;in()&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>这也是 Java8 interface 中的新特性。</h2><h3 id="关于"><a href="#关于" class="headerlink" title="关于 ::"></a>关于 ::</h3><blockquote><p>函数的引用 (<strong>静态函数引用</strong>、<strong>构造函数引用</strong>、<strong>特定对象函数引用</strong>)</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Main</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="comment">// 对构造函数进行引用，简单工厂实现</span></span><br><span class="line">Supplier&lt;Car&gt; aNew = Car::<span class="keyword">new</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">3</span>; i++) &#123;</span><br><span class="line">System.out.println(aNew.get());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 静态函数引用</span></span><br><span class="line">Function&lt;Supplier&lt;Car&gt;, Car&gt; create = Car::create;</span><br><span class="line"><span class="type">Car</span> <span class="variable">car</span> <span class="operator">=</span> create.apply(Car::<span class="keyword">new</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 特定对象的函数引用    </span></span><br><span class="line">        <span class="comment">// 补充:在 Car 函数中使用 this::to 也是一种</span></span><br><span class="line">Function&lt;String, String&gt; to = car::to;</span><br><span class="line">System.out.println(to.apply(<span class="string">&quot;Shanghai&quot;</span>));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Car</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Car <span class="title function_">create</span><span class="params">(Supplier&lt;Car&gt; carSupplier)</span> &#123;</span><br><span class="line"><span class="keyword">return</span> carSupplier.get();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">to</span><span class="params">(String address)</span> &#123;</span><br><span class="line"><span class="keyword">return</span> String.format(<span class="string">&quot;to %s &quot;</span>, address);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注: Function&lt;参数, 返回值&gt; create &#x3D; Car::create;<br>测试后发现只支持<strong>最多2个参数</strong>的函数对应 Function, BiFunction。</p></blockquote><h2 id="即-是对函数进行引用。"><a href="#即-是对函数进行引用。" class="headerlink" title="即, :: 是对函数进行引用。"></a>即, <code>::</code> 是对函数进行引用。</h2><h3 id="使用-Repeatable-支持重复注解"><a href="#使用-Repeatable-支持重复注解" class="headerlink" title="使用 @Repeatable 支持重复注解"></a>使用 @Repeatable 支持重复注解</h3><h2 id="在-Java8-中-不再限制相同的注解在同一位置只能声明一次。简单示例"><a href="#在-Java8-中-不再限制相同的注解在同一位置只能声明一次。简单示例" class="headerlink" title="在 Java8 中, 不再限制相同的注解在同一位置只能声明一次。简单示例:"></a>在 Java8 中, 不再限制<code>相同的注解在同一位置只能声明一次</code>。<br>简单示例:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RepeatableMain</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Filter(&quot;filter-1&quot;)</span></span><br><span class="line"><span class="meta">@Filter(&quot;filter-2&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="keyword">for</span> (Method method : RepeatableMain.class.getDeclaredMethods()) &#123;</span><br><span class="line">System.out.println(Arrays.asList(method.getAnnotations()).toString());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@Target(ElementType.METHOD)</span></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="meta">@interface</span> Filters &#123;</span><br><span class="line">Filter[] value();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Target(ElementType.METHOD)</span></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="meta">@Repeatable(Filters.class)</span> <span class="comment">// 指定多注解的注解类</span></span><br><span class="line"><span class="meta">@interface</span> Filter &#123;</span><br><span class="line">String <span class="title function_">value</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></h2><h3 id="新增注解支持类型"><a href="#新增注解支持类型" class="headerlink" title="新增注解支持类型"></a>新增注解支持类型</h3><blockquote><p>ElementType.TYPE_PARAMETER<br>ElementType.TYPE_USE</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Annotations</span> &#123;</span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="meta">@Target(&#123;ElementType.TYPE_USE, ElementType.TYPE_PARAMETER&#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> Both &#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="meta">@Target(&#123;ElementType.TYPE_PARAMETER&#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> Parameter &#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="meta">@Target(&#123;ElementType.TYPE_USE&#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> Use &#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">Holder</span>&lt;<span class="meta">@Both</span> <span class="meta">@Use</span> <span class="meta">@Parameter</span> T&gt; extends <span class="meta">@Both</span> <span class="meta">@Use</span> Object &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">method</span><span class="params">()</span> <span class="keyword">throws</span> <span class="meta">@Both</span> <span class="meta">@Use</span> Exception &#123;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SuppressWarnings(&quot;unused&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="keyword">final</span> Holder&lt;String&gt; holder = <span class="keyword">new</span> <span class="meta">@Both</span> <span class="meta">@Use</span> Holder&lt;&gt;();</span><br><span class="line"><span class="meta">@Both</span> <span class="meta">@Use</span> Collection&lt;<span class="meta">@Both</span> <span class="meta">@Use</span> String&gt; strings = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li>ElementType.TYPE_PARAMETER 表示注解可以在泛型声明前使用。</li><li>ElementType.TYPE_USE 表示注解可以在全部类型位置使用。</li></ol><hr><h3 id="Java-编译器新特性"><a href="#Java-编译器新特性" class="headerlink" title="Java 编译器新特性"></a>Java 编译器新特性</h3><h2 id="在-java8-中-可以在编译时使用–parameters参数保存函数形参的原变量命名，然后在代码中可通过反射获得函数的变量命名。示例如下"><a href="#在-java8-中-可以在编译时使用–parameters参数保存函数形参的原变量命名，然后在代码中可通过反射获得函数的变量命名。示例如下" class="headerlink" title="在 java8 中, 可以在编译时使用–parameters参数保存函数形参的原变量命名，然后在代码中可通过反射获得函数的变量命名。示例如下:"></a>在 java8 中, 可以在编译时使用<code>–parameters</code>参数保存函数形参的原变量命名，然后在代码中可通过反射获得函数的变量命名。<br>示例如下:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JVMs</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> NoSuchMethodException &#123;</span><br><span class="line"><span class="type">Method</span> <span class="variable">method</span> <span class="operator">=</span> JVMs.class.getMethod(<span class="string">&quot;main&quot;</span>, String[].class);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">final</span> Parameter parameter : method.getParameters()) &#123;</span><br><span class="line">System.out.println(String.format(<span class="string">&quot;%s 检测到原变量名&quot;</span>, parameter.isNamePresent() ? <span class="string">&quot;可以&quot;</span>: <span class="string">&quot;不可以&quot;</span>));</span><br><span class="line">System.out.println(String.format(<span class="string">&quot;参数: %s&quot;</span>, parameter.getName()));</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></h2><h3 id="Java-新增类库"><a href="#Java-新增类库" class="headerlink" title="Java 新增类库"></a>Java 新增类库</h3><h4 id="Optional"><a href="#Optional" class="headerlink" title="Optional"></a>Optional</h4><blockquote><p>用于解决 NullPointerException </p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OptionalMain</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// Null 值</span></span><br><span class="line">Optional&lt;String&gt; optional = Optional.empty();</span><br><span class="line">System.out.println(String.format(<span class="string">&quot;是否为null: %s&quot;</span>, !optional.isPresent() ? <span class="string">&quot;是&quot;</span> : <span class="string">&quot;否&quot;</span>));</span><br><span class="line">System.out.println(optional.orElseGet(() -&gt; <span class="string">&quot;无值回调该函数()&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 非 Null 值</span></span><br><span class="line">optional = Optional.of(<span class="string">&quot;hocgin&quot;</span>);</span><br><span class="line">System.out.println(optional.map(s -&gt; String.format(<span class="string">&quot;值: %s&quot;</span>, s)).orElse(<span class="string">&quot;默认值: 10086&quot;</span>));</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="Stream-API"><a href="#Stream-API" class="headerlink" title="Stream API"></a>Stream API</h4><blockquote><p>函数式编程，简化了之前繁琐的代码编写方式。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SteamMain</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="comment">// 集合中使用 Stream API</span></span><br><span class="line">Collection&lt;String&gt; collections = Arrays.asList(</span><br><span class="line"><span class="string">&quot;1&quot;</span>,</span><br><span class="line"><span class="string">&quot;2&quot;</span>,</span><br><span class="line"><span class="string">&quot;3&quot;</span>,</span><br><span class="line"><span class="string">&quot;4&quot;</span>,</span><br><span class="line"><span class="string">&quot;5&quot;</span>,</span><br><span class="line"><span class="string">&quot;6&quot;</span>,</span><br><span class="line"><span class="string">&quot;7&quot;</span></span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">collections.stream()</span><br><span class="line">.filter(i -&gt; Integer.valueOf(i) &gt; <span class="number">3</span>)</span><br><span class="line">.limit(<span class="number">3</span>)</span><br><span class="line">.forEach(System.out::println);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 文件流中使用 Stream API</span></span><br><span class="line"><span class="keyword">final</span> <span class="type">Path</span> <span class="variable">path</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">File</span>(<span class="string">&quot;filePath&quot;</span>).toPath();</span><br><span class="line"><span class="keyword">try</span> (Stream&lt;String&gt; lines = Files.lines(path, StandardCharsets.UTF_8)) &#123;</span><br><span class="line">lines.onClose(() -&gt; System.out.println(<span class="string">&quot;读取完成&quot;</span>)).forEach(System.out::println);</span><br><span class="line">&#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">e.printStackTrace();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>注: 此处 try 中可在文件流读取完进行自动关闭流的处理。</p></blockquote><h3 id="Date-x2F-Time-API"><a href="#Date-x2F-Time-API" class="headerlink" title="Date&#x2F;Time API"></a>Date&#x2F;Time API</h3><blockquote><p>加强了对时间与日期的处理。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DateAndTimeMain</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="comment">// 日期相关</span></span><br><span class="line"><span class="type">LocalDate</span> <span class="variable">nowDate</span> <span class="operator">=</span> LocalDate.now();</span><br><span class="line"><span class="comment">// 时间相关</span></span><br><span class="line"><span class="type">LocalTime</span> <span class="variable">nowTime</span> <span class="operator">=</span> LocalTime.now();</span><br><span class="line"><span class="comment">// 日期&amp;时间相关</span></span><br><span class="line"><span class="type">LocalDateTime</span> <span class="variable">now</span> <span class="operator">=</span> LocalDateTime.now();</span><br><span class="line"><span class="comment">// 获取指定时区的当前时刻</span></span><br><span class="line"><span class="type">Clock</span> <span class="variable">clock</span> <span class="operator">=</span> Clock.systemUTC();</span><br><span class="line"><span class="comment">// 获取某时区的当前时间</span></span><br><span class="line"><span class="type">ZonedDateTime</span> <span class="variable">zonedDateTime</span> <span class="operator">=</span> ZonedDateTime.now(ZoneId.of(<span class="string">&quot;Asia/Shanghai&quot;</span>));</span><br><span class="line"></span><br><span class="line">System.out.println(String.format(<span class="string">&quot;当前日期: %s&quot;</span>, nowDate));</span><br><span class="line">System.out.println(String.format(<span class="string">&quot;当前时间: %s&quot;</span>, nowTime));</span><br><span class="line">System.out.println(String.format(<span class="string">&quot;当前日期&amp;时间: %s&quot;</span>, now));</span><br><span class="line">System.out.println(String.format(<span class="string">&quot;当前时间戳: %s&quot;</span>, clock.millis())); <span class="comment">// === System.currentTimeMillis()</span></span><br><span class="line">System.out.println(String.format(<span class="string">&quot;上海时间: %s&quot;</span>, zonedDateTime));</span><br><span class="line"></span><br><span class="line"><span class="comment">// 用于计算两个日期间的间隔</span></span><br><span class="line"><span class="type">ZonedDateTime</span> <span class="variable">zonedDateTime2</span> <span class="operator">=</span> ZonedDateTime.now(ZoneId.of(<span class="string">&quot;Asia/Shanghai&quot;</span>));</span><br><span class="line"><span class="type">Duration</span> <span class="variable">duration</span> <span class="operator">=</span> Duration.between(zonedDateTime, zonedDateTime2);</span><br><span class="line">System.out.println(duration.abs().getNano());</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="JavaScript引擎-Nashorn"><a href="#JavaScript引擎-Nashorn" class="headerlink" title="JavaScript引擎(Nashorn)"></a>JavaScript引擎(Nashorn)</h3><blockquote><p>允许 Java 与 JavaScript 相互调用。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NashornMain</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ScriptException &#123;</span><br><span class="line"><span class="type">ScriptEngineManager</span> <span class="variable">manager</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ScriptEngineManager</span>();</span><br><span class="line"><span class="type">ScriptEngine</span> <span class="variable">engine</span> <span class="operator">=</span> manager.getEngineByName(<span class="string">&quot;JavaScript&quot;</span>);</span><br><span class="line">System.out.println(engine.getClass().getName());</span><br><span class="line">System.out.println(<span class="string">&quot;Result:&quot;</span> + engine.eval(<span class="string">&quot;function f() &#123; return 1; &#125;; f() + 1;&quot;</span>));</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Base64"><a href="#Base64" class="headerlink" title="Base64"></a>Base64</h3><p>在 java8 中, 加入了，Base64编码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Base64Main</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="keyword">final</span> <span class="type">String</span> <span class="variable">text</span> <span class="operator">=</span> <span class="string">&quot;Base64 finally in Java 8!&quot;</span>;</span><br><span class="line"><span class="keyword">final</span> <span class="type">String</span> <span class="variable">encoded</span> <span class="operator">=</span> Base64</span><br><span class="line">.getEncoder()</span><br><span class="line">.encodeToString(text.getBytes(StandardCharsets.UTF_8));</span><br><span class="line">System.out.println(encoded);</span><br><span class="line"></span><br><span class="line"><span class="keyword">final</span> <span class="type">String</span> <span class="variable">decoded</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(</span><br><span class="line">Base64.getDecoder().decode(encoded),</span><br><span class="line">StandardCharsets.UTF_8);</span><br><span class="line">System.out.println(decoded);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="并行数组"><a href="#并行数组" class="headerlink" title="并行数组"></a>并行数组</h3><p>在 java8 中, 对数组进行并行处理, 极大提高在多核机子上的处理速度。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ParallelMain</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="type">long</span>[] arrayOfLong = <span class="keyword">new</span> <span class="title class_">long</span>[<span class="number">20000</span>];</span><br><span class="line"></span><br><span class="line"><span class="comment">// 进行赋值操作</span></span><br><span class="line">Arrays.parallelSetAll(arrayOfLong,</span><br><span class="line">index -&gt; ThreadLocalRandom.current().nextInt(<span class="number">1000000</span>));</span><br><span class="line">Arrays.stream(arrayOfLong).limit(<span class="number">10</span>).forEach(</span><br><span class="line">i -&gt; System.out.print(i + <span class="string">&quot; &quot;</span>));</span><br><span class="line">System.out.println();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 进行数组排序</span></span><br><span class="line">Arrays.parallelSort(arrayOfLong);</span><br><span class="line">Arrays.stream(arrayOfLong).limit(<span class="number">10</span>).forEach(</span><br><span class="line">i -&gt; System.out.print(i + <span class="string">&quot; &quot;</span>));</span><br><span class="line">System.out.println();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 进行数组操作, 结果: [a1, a1+a2, a1+a2+a3,..]</span></span><br><span class="line">Arrays.parallelPrefix(arrayOfLong, (x, y) -&gt; x + y);</span><br><span class="line">Arrays.stream(arrayOfLong).limit(<span class="number">10</span>).forEach(</span><br><span class="line">i -&gt; System.out.print(i + <span class="string">&quot; &quot;</span>));</span><br><span class="line">System.out.println();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="并发"><a href="#并发" class="headerlink" title="并发"></a>并发</h3><ul><li>线程池<code>ExecutorService/ScheduledExecutorService</code>支持使用<code>Stream API</code>.</li><li>新增 StampedLock 用于替代 ReadWriteLock<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">StampedLock</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StampedLock</span>();</span><br><span class="line">lock.writeLock();</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="comment">// 代码..</span></span><br><span class="line">&#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">    lock.unlockWrite(stamp);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>原子操作(java.concurrent.atomic)</li><li>ConcurrentMap 继承自Map接口</li><li>ForkJoinPool 预置并行机制</li></ul><h3 id="新增的-Java-工具"><a href="#新增的-Java-工具" class="headerlink" title="新增的 Java 工具"></a>新增的 Java 工具</h3><ul><li>Nashorn引擎命令行工具 <strong>jjs</strong><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">jjs # 回车</span><br><span class="line">(function()&#123;return 1+1&#125;)()</span><br></pre></td></tr></table></figure></li><li>类依赖分析器命令行工具 <strong>jdeps</strong><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">.class 文件</span></span><br><span class="line">jdeps Base64Main.class</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">.jar 文件</span></span><br><span class="line">jdeps demo.jar</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">文件夹</span></span><br><span class="line">jdeps jdk8 </span><br></pre></td></tr></table></figure></li></ul><h3 id="JVM-新特性"><a href="#JVM-新特性" class="headerlink" title="JVM 新特性"></a>JVM 新特性</h3><ul><li>PermGen 被移除</li><li>JVM选项<code>-XX:PermSize</code>与<code>-XX:MaxPermSize</code>分别被<code>-XX:MetaSpaceSize</code>与<code>-XX:MaxMetaspaceSize</code>所代替</li></ul><h3 id="相关"><a href="#相关" class="headerlink" title="相关"></a>相关</h3><p><a href="https://www.gitbook.com/book/wizardforcel/modern-java/details">Java 8</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;JDK8 新特性的使用&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="语法" scheme="https://hocg.in/tags/%E8%AF%AD%E6%B3%95/"/>
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>Java线程池和锁-小记</title>
    <link href="https://hocg.in/2017/10/07/Java%20%E7%BA%BF%E7%A8%8B%E6%B1%A0%20%E5%92%8C%20%E9%94%81%20%E5%B0%8F%E8%AE%B0/"/>
    <id>https://hocg.in/2017/10/07/Java%20%E7%BA%BF%E7%A8%8B%E6%B1%A0%20%E5%92%8C%20%E9%94%81%20%E5%B0%8F%E8%AE%B0/</id>
    <published>2017-10-07T01:03:29.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>提取想要的apk， 例如CM ROM包中的含天气的时钟不错！</p><span id="more"></span><h2 id="并发"><a href="#并发" class="headerlink" title="并发"></a>并发</h2><h3 id="线程池"><a href="#线程池" class="headerlink" title="线程池"></a>线程池</h3><ul><li>ExecutorService<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConcurrencyMain</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line"><span class="type">ExecutorService</span> <span class="variable">executor</span> <span class="operator">=</span> Executors.newWorkStealingPool();</span><br><span class="line"></span><br><span class="line">List&lt;Callable&lt;String&gt;&gt; callables = Arrays.asList(</span><br><span class="line">() -&gt; <span class="string">&quot;task1&quot;</span>,</span><br><span class="line">() -&gt; <span class="string">&quot;task2&quot;</span>,</span><br><span class="line">() -&gt; <span class="string">&quot;task3&quot;</span>);</span><br><span class="line"></span><br><span class="line">executor.invokeAll(callables)</span><br><span class="line">.stream()</span><br><span class="line">.map(future -&gt; &#123;</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line"><span class="keyword">return</span> future.get();</span><br><span class="line">&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"><span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalStateException</span>(e);</span><br><span class="line">&#125;</span><br><span class="line">&#125;)</span><br><span class="line">.forEach(System.out::println);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>ScheduledExecutorService<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConcurrencyMain</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line"><span class="type">ScheduledExecutorService</span> <span class="variable">executor</span> <span class="operator">=</span> Executors.newScheduledThreadPool(<span class="number">3</span>);</span><br><span class="line"></span><br><span class="line">ScheduledFuture&lt;?&gt; future = executor.schedule(() -&gt; System.out.println(<span class="string">&quot;执行延迟任务&quot;</span>), <span class="number">2</span>, TimeUnit.SECONDS);</span><br><span class="line"></span><br><span class="line">TimeUnit.MILLISECONDS.sleep(<span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line"><span class="type">long</span> <span class="variable">remainingDelay</span> <span class="operator">=</span> future.getDelay(TimeUnit.MILLISECONDS);</span><br><span class="line">System.out.println(String.format(<span class="string">&quot;剩余延迟时间: %sms&quot;</span>, remainingDelay));</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><strong>区别</strong> 两者的区别是<code>ScheduledExecutorService</code>是可延迟执行。</li></ul><h3 id="同步-Synchronized"><a href="#同步-Synchronized" class="headerlink" title="同步(Synchronized)"></a>同步(Synchronized)</h3><ol><li><p>对象锁<br><strong>语法:</strong> </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SynchronizedMain</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ==[测试一:同一对象]==</span></span><br><span class="line"><span class="comment">// 结果: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9</span></span><br><span class="line"><span class="type">Test</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Test</span>();</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec());</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec());</span><br><span class="line">runnable1.start();</span><br><span class="line">runnable2.start();</span><br><span class="line"></span><br><span class="line"><span class="comment">// ==[测试二:不同一对象]==</span></span><br><span class="line"><span class="comment">// 结果: 0 0 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 9 8 9</span></span><br><span class="line"><span class="type">Test</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Test</span>();</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec());</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t2.exec());</span><br><span class="line">runnable3.start();</span><br><span class="line">runnable4.start();</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 以下两种方式等价，仅作用范围不一样。</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">exec</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">System.out.printf(i + <span class="string">&quot; &quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">exec</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">synchronized</span> (<span class="built_in">this</span>) &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">System.out.printf(i + <span class="string">&quot; &quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>结论:</strong> 同一对象调用该方法是锁定的，不同对象不会进行锁定。  </p></li><li><p>类锁</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SynchronizedMain</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="comment">// ==[测试一:同一对象]==</span></span><br><span class="line"><span class="comment">// 结果: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9</span></span><br><span class="line"><span class="type">Test</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Test</span>();</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec());</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec());</span><br><span class="line">runnable1.start();</span><br><span class="line">runnable2.start();</span><br><span class="line"></span><br><span class="line"><span class="comment">// ==[测试二:不同一对象]==</span></span><br><span class="line"><span class="comment">// 结果: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9</span></span><br><span class="line"><span class="type">Test</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Test</span>();</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec());</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t2.exec());</span><br><span class="line">runnable3.start();</span><br><span class="line">runnable4.start();</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 以下两种方式等价</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="type">Object</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line"><span class="keyword">public</span>  <span class="keyword">void</span> <span class="title function_">exec</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">synchronized</span> (lock) &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">System.out.printf(i + <span class="string">&quot; &quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">exec</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">synchronized</span> (Test.class) &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">System.out.printf(i + <span class="string">&quot; &quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>结论:</strong> 该方式锁的作用范围是整个类。</p></li><li><p>指定锁<br><strong>语法:</strong> </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SynchronizedMain</span> &#123;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="type">Object</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ==[测试一:同一对象]==</span></span><br><span class="line"><span class="comment">// 结果: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9</span></span><br><span class="line"><span class="type">Test</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Test</span>();</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec(lock));</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec(lock));</span><br><span class="line">runnable1.start();</span><br><span class="line">runnable2.start();</span><br><span class="line"></span><br><span class="line"><span class="comment">// ==[测试二:不同一对象]==</span></span><br><span class="line"><span class="comment">// 结果: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9</span></span><br><span class="line"><span class="type">Test</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Test</span>();</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t1.exec(lock));</span><br><span class="line"><span class="type">Thread</span> <span class="variable">runnable4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; t2.exec(lock));</span><br><span class="line">runnable3.start();</span><br><span class="line">runnable4.start();</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">exec</span><span class="params">(Object lock)</span> &#123;</span><br><span class="line"><span class="keyword">synchronized</span> (lock) &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">System.out.printf(i + <span class="string">&quot; &quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>结论:</strong> 该方式取决于传入的锁。<strong>当对象属性发生改变时，锁就失去了作用。</strong></p></li></ol><p>对于 Java8 中，<code>ReentrantLock</code> 可实现锁的作用。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;提取想要的apk， 例如CM ROM包中的含天气的时钟不错！&lt;/p&gt;</summary>
    
    
    
    <category term="Java" scheme="https://hocg.in/categories/Java/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>解决 WebView 点击时网页不断闪耀</title>
    <link href="https://hocg.in/2017/09/28/TextView%20%E6%BB%9A%E5%8A%A8%E9%97%AE%E9%A2%98/"/>
    <id>https://hocg.in/2017/09/28/TextView%20%E6%BB%9A%E5%8A%A8%E9%97%AE%E9%A2%98/</id>
    <published>2017-09-28T21:47:21.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>解决高版本 WebView 点击时网页不断闪耀的问题 🤗</p><span id="more"></span><h2 id="设置-TextView-自动水平滚动"><a href="#设置-TextView-自动水平滚动" class="headerlink" title="设置 TextView 自动水平滚动"></a>设置 TextView 自动水平滚动</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">TextView</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">&quot;@+id/tx&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;40dp&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:background</span>=<span class="string">&quot;#fdf&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:text</span>=<span class="string">&quot;1234567890123456789012345678901234567890&quot;</span></span></span><br><span class="line"><span class="tag"></span></span><br><span class="line"><span class="tag">    <span class="attr">android:focusable</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:focusableInTouchMode</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:singleLine</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:scrollHorizontally</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:ellipsize</span>=<span class="string">&quot;marquee&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:marqueeRepeatLimit</span> =<span class="string">&quot;marquee_forever&quot;</span></span></span><br><span class="line"><span class="tag">    /&gt;</span></span><br></pre></td></tr></table></figure><p>高版本测试中<code>android:singleLine=&quot;true&quot;</code>虽然过期了，但仍不能使用<code>android:maxLines=&quot;1&quot;</code>进行替换，如果实在强迫症患者可以使用<code>tx.setSingleLine(true);</code>替换。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;解决高版本 WebView 点击时网页不断闪耀的问题 🤗&lt;/p&gt;</summary>
    
    
    
    <category term="Android" scheme="https://hocg.in/categories/Android/"/>
    
    
    <category term="Android" scheme="https://hocg.in/tags/Android/"/>
    
    <category term="问题" scheme="https://hocg.in/tags/%E9%97%AE%E9%A2%98/"/>
    
  </entry>
  
  <entry>
    <title>解决 WebView 点击时网页不断闪耀</title>
    <link href="https://hocg.in/2017/09/28/%E8%A7%A3%E5%86%B3WebView%E7%82%B9%E5%87%BB%E6%97%B6%E7%BD%91%E9%A1%B5%E4%B8%8D%E6%96%AD%E9%97%AA%E8%80%80/"/>
    <id>https://hocg.in/2017/09/28/%E8%A7%A3%E5%86%B3WebView%E7%82%B9%E5%87%BB%E6%97%B6%E7%BD%91%E9%A1%B5%E4%B8%8D%E6%96%AD%E9%97%AA%E8%80%80/</id>
    <published>2017-09-28T21:47:21.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>解决高版本 WebView 点击时网页不断闪耀的问题 🤗</p><span id="more"></span><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>网页渲染开启了硬件加速，如果你也出现了该问题，可以尝试关闭硬件加速。  </p><h2 id="方案"><a href="#方案" class="headerlink" title="方案"></a>方案</h2><p>方案一: 在xml中使用<code>android:layerType=&quot;software&quot;</code>进行关闭。<strong>推荐</strong><br>方案二: 通过 java 代码<code>webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);</code>进行关闭。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://github.com/hocgin/BroswerKit/blob/master/app/src/main/res/layout/activity_browser.xml#L40-L53">BroswerKit</a>进行标记的这段代码解决了我的闪耀问题</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;解决高版本 WebView 点击时网页不断闪耀的问题 🤗&lt;/p&gt;</summary>
    
    
    
    <category term="Android" scheme="https://hocg.in/categories/Android/"/>
    
    
    <category term="Android" scheme="https://hocg.in/tags/Android/"/>
    
    <category term="问题" scheme="https://hocg.in/tags/%E9%97%AE%E9%A2%98/"/>
    
  </entry>
  
  <entry>
    <title>解决 ProgressBar 上下出现空白现象</title>
    <link href="https://hocg.in/2017/09/27/%E8%A7%A3%E5%86%B3ProgressBar%E9%A1%B6%E9%83%A8%E5%87%BA%E7%8E%B0%E7%A9%BA%E7%99%BD%E7%8E%B0%E8%B1%A1/"/>
    <id>https://hocg.in/2017/09/27/%E8%A7%A3%E5%86%B3ProgressBar%E9%A1%B6%E9%83%A8%E5%87%BA%E7%8E%B0%E7%A9%BA%E7%99%BD%E7%8E%B0%E8%B1%A1/</id>
    <published>2017-09-27T10:27:22.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>解决 ProgressBar 上下出现空白现象 🤠</p><span id="more"></span><h2 id="出现问题"><a href="#出现问题" class="headerlink" title="出现问题"></a>出现问题</h2><p>一般情况我们使用如下代码来创建<code>ProgressBar</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ProgressBar</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/progressBar&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">style</span>=<span class="string">&quot;?android:attr/progressBarStyleHorizontal&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:background</span>=<span class="string">&quot;#fff&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:max</span>=<span class="string">&quot;100&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:indeterminate</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure><p>那么将会出现如下情况:<br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-28%2021.58.00.png" alt="出现空白间隔问题"></p><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><p>通过变更<code>android:layout_marginBottom</code>和<code>android:layout_marginTop</code>在结合<code>android:background</code>设置为透明来处理这个问题:</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ProgressBar</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">&quot;@+id/progressBar&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">style</span>=<span class="string">&quot;?android:attr/progressBarStyleHorizontal&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_marginBottom</span>=<span class="string">&quot;-7dp&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_marginTop</span>=<span class="string">&quot;-7dp&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:background</span>=<span class="string">&quot;#00ffffff&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:max</span>=<span class="string">&quot;100&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:indeterminate</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure><p>以下是处理后的结果<br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-28%2022.03.46.png" alt="解决问题后"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;解决 ProgressBar 上下出现空白现象 🤠&lt;/p&gt;</summary>
    
    
    
    <category term="Android" scheme="https://hocg.in/categories/Android/"/>
    
    
    <category term="Android" scheme="https://hocg.in/tags/Android/"/>
    
    <category term="问题" scheme="https://hocg.in/tags/%E9%97%AE%E9%A2%98/"/>
    
  </entry>
  
  <entry>
    <title>在 OpenWrt 部署 Shadowsocks</title>
    <link href="https://hocg.in/2017/09/18/OpenWrt-Shadowsocks/"/>
    <id>https://hocg.in/2017/09/18/OpenWrt-Shadowsocks/</id>
    <published>2017-09-18T14:32:26.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>关于 OpenWrt 请看 <a href="http://hocg.in/2017/09/18/OpenWrt-%E5%85%A5%E9%97%A8%E7%AF%87/#more">OpenWrt 入门篇</a><br>关于 Shadowsocks 请看 <a href="https://www.wikiwand.com/zh/Shadowsocks">什么是 Shadowsocks</a><br>已有 Shadowsocks 账号, 后续可能会记录。<br><strong>重要:</strong> 本文前提为读者已观看过以上2篇文章，如阅读引起任何不适请立即停止。</p><h2 id="关于-Shadowsocks-libev-模块"><a href="#关于-Shadowsocks-libev-模块" class="headerlink" title="关于 Shadowsocks-libev 模块"></a>关于 Shadowsocks-libev 模块</h2><blockquote><p><a href="https://github.com/shadowsocks/shadowsocks-libev">Shadowsocks-libev 官网</a><br><a href="https://sourceforge.net/projects/openwrt-dist/files/shadowsocks-libev">Shadowsocks-libev 下载地址 (推荐下载非spec版本)</a></p></blockquote><p>ss-server：服务器端，部署于服务器，提供 shadowsocks 服务。<br>ss-local：客户端，提供 SOCKS 代理<br>ss-redir：客户端，提供透明代理, 从 v2.2.0 开始支持 UDP<br>ss-tunnel: 客户端，提供端口转发, 可用于 DNS 查询</p><p><strong>Note:</strong> 下载的时候请根据 CPU 类型, 查看方式请<a href="">参照</a></p><h2 id="安装-Shadowsocks-libev"><a href="#安装-Shadowsocks-libev" class="headerlink" title="安装 Shadowsocks-libev"></a>安装 Shadowsocks-libev</h2><ol><li>将下载的<code>Shadowsocks-libev</code>移至路由器<code>/tmp</code>目录<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">scp shadowsocks-libev-polarssl_2.4.8-2_ar71xx.ipk root@192.168.1.1:/tmp</span><br></pre></td></tr></table></figure></li><li>安装依赖<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">opkg update</span><br><span class="line">opkg install iptables-mod-nat-extra ipset libopenssl</span><br></pre></td></tr></table></figure></li><li>安装<code>Shadowsocks-libev</code><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">opkg install /tmp/shadowsocks-libev-polarssl_2.4.8-2_ar71xx.ipk</span><br></pre></td></tr></table></figure></li></ol><h2 id="配置-shadowsocks"><a href="#配置-shadowsocks" class="headerlink" title="配置 shadowsocks"></a>配置 shadowsocks</h2><ol><li>修改<code>/etc/shadowsocks.json</code>为实际参数。格式如下 <figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;server&quot;</span><span class="punctuation">:</span> <span class="string">&quot;127.0.0.1&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;server_port&quot;</span><span class="punctuation">:</span> <span class="number">443</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;local_port&quot;</span><span class="punctuation">:</span> <span class="number">7654</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;password&quot;</span><span class="punctuation">:</span> <span class="string">&quot;password&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;timeout&quot;</span><span class="punctuation">:</span> <span class="number">60</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;method&quot;</span><span class="punctuation">:</span> <span class="string">&quot;rc4-md5&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure> 此处, <strong>“local_port”: 7654</strong> 为重点。不理解的, 请不要进行修改此项，后续会解释。<br> <strong>注:</strong> <code>/etc/shadowsocks.json</code> 为配置文件, 存储 shadowsocks 的账号、 密码及设置。</li><li>查看<code>/etc/init.d/shadowsocks</code>。内容如下 <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/sh /etc/rc.common</span></span><br><span class="line"></span><br><span class="line">START=95</span><br><span class="line"></span><br><span class="line">SERVICE_USE_PID=1</span><br><span class="line">SERVICE_WRITE_PID=1</span><br><span class="line">SERVICE_DAEMONIZE=1</span><br><span class="line"></span><br><span class="line">CONFIG=/etc/shadowsocks.json</span><br><span class="line"></span><br><span class="line">start() &#123;</span><br><span class="line">  service_start /usr/bin/ss-local -c $CONFIG -b 0.0.0.0</span><br><span class="line"><span class="meta prompt_">  #</span><span class="language-bash">service_start /usr/bin/ss-redir -c <span class="variable">$CONFIG</span> -b 0.0.0.0</span></span><br><span class="line"><span class="meta prompt_">  #</span><span class="language-bash">service_start /usr/bin/ss-tunnel -c <span class="variable">$CONFIG</span> -b 0.0.0.0 -l 5353 -L 8.8.8.8:53 -u</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">stop() &#123;</span><br><span class="line">  service_stop /usr/bin/ss-local</span><br><span class="line"><span class="meta prompt_">  #</span><span class="language-bash">service_stop /usr/bin/ss-redir</span></span><br><span class="line"><span class="meta prompt_">  #</span><span class="language-bash">service_stop /usr/bin/ss-tunnel</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure> <strong>注:</strong> <code>/etc/init.d/shadowsocks</code> 为运行文件, shadowsocks 的启动、停止、重启。</li><li>运行检查配置是否正确 <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/etc/init.d/shadowsocks restart</span><br></pre></td></tr></table></figure></li><li>使用代理进行检查, Chrome 浏览器下载 <a href="https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif">ExtensionProxy SwitchyOmega</a>，墙内地址后续补上..。对插件进行如下配置:<br><img src="http://7xs6lq.com1.z0.glb.clouddn.com/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2015.43.33.png" alt="image"></li><li>在 Chrome 浏览器使用 ExtensionProxy SwitchyOmega 切换到该协议并访问 <a href="https://www.youtube.com/">YouTuBe</a>，验证其配置的正确性。</li><li>关闭 shadowsocks <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/etc/init.d/shadowsocks stop</span><br></pre></td></tr></table></figure></li></ol><h2 id="自动化"><a href="#自动化" class="headerlink" title="自动化"></a>自动化</h2><h3 id="安装-dnsmasq-amp-ipset"><a href="#安装-dnsmasq-amp-ipset" class="headerlink" title="安装 dnsmasq &amp; ipset"></a>安装 dnsmasq &amp; ipset</h3><ol><li>查看是否支持 ipset <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">opkg update</span><br><span class="line">opkg list-installed    </span><br><span class="line">dnsmasq -v</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果不支持，卸载掉安装full版</span></span><br><span class="line">opkg remove dnsmasq</span><br><span class="line">opkg install dnsmasq-full</span><br><span class="line">opkg install ipset iptables-mod-nat-extra</span><br><span class="line">opkg install /tmp/pdnsd_1.2.9a-par-a8e46ccba7b0fa2230d6c42ab6dcd92926f6c21d_ar71xx.ipk</span><br></pre></td></tr></table></figure> 附件:<ul><li><a href="%E9%A2%84%E7%95%99">pdnsd_1.2.9a-par-a8e46ccba7b0fa2230d6c42ab6dcd92926f6c21d_ar71xx.ipk 下载</a></li></ul></li><li>配置 dnsmasq 和 ipset <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/dnsmasq.conf</span><br><span class="line">mkdir /etc/dnsmasq.d</span><br></pre></td></tr></table></figure> 在末尾加入 <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">conf-dir=/etc/dnsmasq.d</span><br><span class="line">cache-size=1500      #修改dnsmasq缓存大小，默认为150。</span><br><span class="line">min-cache-ttl=720    #修改DNS缓存最小有效期（秒）。仅适用于aa65535的dnsmasq-full版本。</span><br></pre></td></tr></table></figure></li><li>下载国内重要网站名单，用国内域名服务器查询iP地址 <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cd /etc/dnsmasq.d</span><br><span class="line">opkg install wget</span><br><span class="line">wget -4 --no-check-certificate -O /etc/dnsmasq.d/accelerated-domains.china.conf https://github.com/felixonmars/dnsmasq-china-list/raw/master/accelerated-domains.china.conf</span><br><span class="line">wget -4 --no-check-certificate -O /etc/dnsmasq.d/bogus-nxdomain.china.conf https://github.com/felixonmars/dnsmasq-china-list/raw/master/bogus-nxdomain.china.conf</span><br><span class="line">echo &quot;server=/#/127.0.0.1#3210&quot; &gt; gfwlist.conf</span><br></pre></td></tr></table></figure></li><li>修改<code>/etc/init.d/shadowsocks</code>启动文件, 内容如下 <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/sh /etc/rc.common</span></span><br><span class="line"></span><br><span class="line">START=95</span><br><span class="line"></span><br><span class="line">SERVICE_USE_PID=1</span><br><span class="line">SERVICE_WRITE_PID=1</span><br><span class="line">SERVICE_DAEMONIZE=1</span><br><span class="line"></span><br><span class="line">CONFIG=/etc/shadowsocks.json</span><br><span class="line"></span><br><span class="line">start() &#123;</span><br><span class="line">    sed -i &#x27;s/114.114.114.114/127.0.0.1#3210/&#x27; /etc/dnsmasq.d/gfwlist.conf</span><br><span class="line">    /etc/init.d/dnsmasq restart</span><br><span class="line"></span><br><span class="line">    service_start /usr/bin/ss-redir -b 0.0.0.0 -c $CONFIG -f /var/run/shadowsocks.pid -u</span><br><span class="line">    service_start /usr/bin/ss-tunnel -b 0.0.0.0 -c $CONFIG -l 3210 -L 8.8.8.8:53 -u</span><br><span class="line">    /usr/bin/shadowsocks-firewall</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">stop() &#123;</span><br><span class="line">    sed -i &#x27;s/127.0.0.1#3210/114.114.114.114/&#x27; /etc/dnsmasq.d/gfwlist.conf</span><br><span class="line">    /etc/init.d/dnsmasq restart</span><br><span class="line"></span><br><span class="line">    service_stop /usr/bin/ss-redir</span><br><span class="line">    service_stop /usr/bin/ss-tunnel</span><br><span class="line">    killall ss-redir</span><br><span class="line">    killall ss-tunnel</span><br><span class="line">    /etc/init.d/firewall restart</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>配置 iptables 防火墙转发IP和端口<br><strong>创建执行文件 &#x2F;usr&#x2F;bin&#x2F;shadowsocks-firewall</strong> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">touch /usr/bin/shadowsocks-firewall</span><br><span class="line">chmod +x /usr/bin/shadowsocks-firewall</span><br></pre></td></tr></table></figure> <strong>&#x2F;usr&#x2F;bin&#x2F;shadowsocks-firewall 其内容如下</strong> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/sh</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">create a new chain named SHADOWSOCKS</span></span><br><span class="line">iptables -t nat -N SHADOWSOCKS</span><br><span class="line">iptables -t nat -N SHADOWSOCKS_WHITELIST</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Ignore your shadowsocks server<span class="string">&#x27;s addresses</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">It&#x27;</span>s very IMPORTANT, just be careful.</span></span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 此处为服务器IP -j RETURN</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Ignore LANs IP address</span></span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Check whitelist</span></span><br><span class="line">iptables -t nat -A SHADOWSOCKS -j SHADOWSOCKS_WHITELIST</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -m mark --mark 1 -j RETURN</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="keyword">for</span> hulu.com</span></span><br><span class="line">iptables -t nat -A SHADOWSOCKS -p tcp --dport 1935 -j REDIRECT --to-ports 7654</span><br><span class="line">iptables -t nat -A SHADOWSOCKS -p udp --dport 1935 -j REDIRECT --to-ports 7654</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="keyword">for</span> Chrome browser and youtube.com</span></span><br><span class="line">iptables -t nat -A SHADOWSOCKS -p udp --dport 443 -j REDIRECT --to-ports 7654</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Anything <span class="keyword">else</span> should be redirected to shadowsocks<span class="string">&#x27;s local port</span></span></span><br><span class="line">iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 7654</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">Apply the rules</span></span></span><br><span class="line">iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">Ignore China IP address</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">for white_ip in `cat /etc/chinadns_chnroute.txt`;</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">do</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">  iptables -t nat -A SHADOWSOCKS_WHITELIST -d &quot;$&#123;white_ip&#125;&quot; -j MARK --set-mark 1</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">done</span></span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">Ignore Asia IP address</span></span></span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 1.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 14.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 27.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 36.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 39.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 42.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 49.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 58.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 59.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 60.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 61.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 101.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 103.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 106.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 110.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 111.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 112.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 113.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 114.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 115.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 116.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 117.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 118.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 119.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 120.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 121.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 122.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 123.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 124.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 125.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 126.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 169.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 175.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 180.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 182.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 183.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 202.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 203.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 210.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 211.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 218.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 219.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 220.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 221.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 222.0.0.0/8 -j MARK --set-mark 1</span><br><span class="line">iptables -t nat -A SHADOWSOCKS_WHITELIST -d 223.0.0.0/8 -j MARK --set-mark 1</span><br></pre></td></tr></table></figure> <strong>重要:</strong><ol><li><code>此处为服务器IP</code>更换为实际IP。</li><li><code>Ignore Asia IP address</code>为亚洲IP地址段。如果路由器内存够大的话，可开启<code>Ignore China IP address</code>。<a href="https://github.com/softwaredownload/openwrt-fanqiang/blob/master/openwrt/default/etc/chinadns_chnroute.txt">chinadns_chnroute.txt 文件下载</a></li><li><code>--to-ports 7654</code>即<code>/etc/shadowsocks.json</code>中的 <strong>“local_port”: 7654</strong></li></ol></li></ol><h3 id="shadowsocks-控制"><a href="#shadowsocks-控制" class="headerlink" title="shadowsocks 控制"></a>shadowsocks 控制</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/etc/init.d/shadowsocks stop</span><br><span class="line">/etc/init.d/shadowsocks start</span><br><span class="line">/etc/init.d/shadowsocks enable</span><br><span class="line">/etc/init.d/shadowsocks disable</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h2&gt;&lt;p&gt;关于 OpenWrt 请看 &lt;a href=&quot;http://hocg.in/2017/09/18/OpenWrt-%E5%85%A5%E9</summary>
      
    
    
    
    <category term="OpenWrt" scheme="https://hocg.in/categories/OpenWrt/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="OpenWrt" scheme="https://hocg.in/tags/OpenWrt/"/>
    
  </entry>
  
  <entry>
    <title>OpenWrt 入门篇</title>
    <link href="https://hocg.in/2017/09/18/OpenWrt-%E5%85%A5%E9%97%A8%E7%AF%87/"/>
    <id>https://hocg.in/2017/09/18/OpenWrt-%E5%85%A5%E9%97%A8%E7%AF%87/</id>
    <published>2017-09-18T14:32:26.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>今天刚好重刷 OpenWrt 固件，整理整理</p><span id="more"></span><h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p><a href="https://www.wikiwand.com/zh/OpenWrt">什么是 OpenWrt?</a></p><h2 id="关于支持-OpenWrt-的路由器"><a href="#关于支持-OpenWrt-的路由器" class="headerlink" title="关于支持 OpenWrt 的路由器"></a>关于支持 OpenWrt 的路由器</h2><p>可以去 <a href="https://wiki.openwrt.org/toh/start">支持 OpenWrt 的路由器列表</a> 查看支持的路由器, 了解其 <strong>CPU型号(既芯片型号)</strong> <strong>RAM容量</strong> <strong>Flash容量</strong></p><h2 id="关于-OpenWrt-固件的下载"><a href="#关于-OpenWrt-固件的下载" class="headerlink" title="关于 OpenWrt 固件的下载"></a>关于 OpenWrt 固件的下载</h2><p><a href="https://downloads.openwrt.org/">OpenWrt 官方下载固件地址</a><br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2012.12.12.png" alt="image"><br><strong>关于下载地址格式:</strong></p><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2012.26.38.png" alt="image"></p><p><strong>关于固件类型</strong></p><ul><li>后缀为<code>factory</code>是用于从原厂固件刷为 OpenWrt。</li><li>后缀为<code>sysupgrade</code>是用于从 OpenWrt 更新 OpenWrt。</li></ul><h2 id="原厂刷-OpenWrt-固件"><a href="#原厂刷-OpenWrt-固件" class="headerlink" title="原厂刷 OpenWrt 固件"></a>原厂刷 OpenWrt 固件</h2><blockquote><p>待补充</p></blockquote><h2 id="网页界面-OpenWrt-备份-amp-升级固件"><a href="#网页界面-OpenWrt-备份-amp-升级固件" class="headerlink" title="网页界面 OpenWrt 备份 &amp; 升级固件"></a>网页界面 OpenWrt 备份 &amp; 升级固件</h2><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2012.50.34.png" alt="image"><br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2012.57.13.png" alt="image"></p><h2 id="OpenWrt-安全模式"><a href="#OpenWrt-安全模式" class="headerlink" title="OpenWrt 安全模式"></a>OpenWrt 安全模式</h2><blockquote><p>当我们无法进入网页界面，可以使用<strong>安全模式</strong>管理恢复固件<br><strong>必须使用有线电缆进行连接。</strong><br>环境: Linux or macOS</p></blockquote><p>进入OpenWrt安全模式的方法：</p><ol><li>使用网线连接电脑和路由器</li><li>设置电脑网卡<br>  IP 地址:<code>192.168.1.x</code>(x为2至255)<br>  子网掩码:<code>255.255.255.0</code></li><li>打开终端运行命令<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">注, 此处 eth0 为网卡. 可使用 ifconfig 进行查看</span></span><br><span class="line">sudo tcpdump -Ani eth0 port 4919 and udp</span><br></pre></td></tr></table></figure></li><li>断电重启</li><li>打开终端运行命令<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">telnet 192.168.1.1</span><br></pre></td></tr></table></figure></li><li>执行指令, 例如<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重置系统</span></span><br><span class="line">firstboot</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重置密码</span></span><br><span class="line">passwd</span><br></pre></td></tr></table></figure></li><li>重启路由器</li></ol><h2 id="不死-U-Boot"><a href="#不死-U-Boot" class="headerlink" title="不死 U-Boot"></a>不死 U-Boot</h2><blockquote><p>待补充</p></blockquote><h2 id="网页界面-OpenWrt-宽带拨号设置"><a href="#网页界面-OpenWrt-宽带拨号设置" class="headerlink" title="网页界面 OpenWrt 宽带拨号设置"></a>网页界面 OpenWrt 宽带拨号设置</h2><ol><li><p>进入接口设置界面</p></li><li><p>进行 WAN 口编辑<br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2013.37.35.png" alt="image"></p></li><li><p>填写宽带账号 &amp; 密码<br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2013.45.42.png" alt="image"></p></li><li><p>此时电脑连接 LAN 口的话，即可进行上网。</p></li></ol><h2 id="WiFi-设置"><a href="#WiFi-设置" class="headerlink" title="WiFi 设置"></a>WiFi 设置</h2><ol><li>进入 WiFi 设置界面，此处为双网卡<br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2013.53.43.png" alt="image"></li><li>开启WiFi<br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2014.00.00.png" alt="image"></li><li>设置WiFi<br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-18%2014.26.04.png" alt="image"></li></ol><hr><h2 id="基础知识"><a href="#基础知识" class="headerlink" title="基础知识"></a>基础知识</h2><h3 id="什么是WAN口？什么是LAN口？"><a href="#什么是WAN口？什么是LAN口？" class="headerlink" title="什么是WAN口？什么是LAN口？"></a>什么是WAN口？什么是LAN口？</h3><blockquote><p>路由器通常有多个LAN口，一个WAN口</p></blockquote><ul><li>WAN<blockquote><p>广域网（WAN、公网、外网）</p></blockquote></li></ul><p>设置拨号上网连接互联网</p><ul><li>LAN<blockquote><p>局域网（LAN、私网、内网)</p></blockquote></li></ul><p>连接本地计算机</p><h3 id="PPPoE"><a href="#PPPoE" class="headerlink" title="PPPoE"></a>PPPoE</h3><blockquote><p>以太网上的点对点协议中的一种, 宽带接入方式ADSL 就使用了PPPoE协议</p></blockquote><h3 id="关于-WiFi-2-4G-和-5G"><a href="#关于-WiFi-2-4G-和-5G" class="headerlink" title="关于 WiFi 2.4G 和 5G"></a>关于 WiFi 2.4G 和 5G</h3><p><code>802.11n/b/g</code> 主要工作频段为2.4GHz<br><code>802.11a/ac</code> 主要工作频段为5GHz</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;今天刚好重刷 OpenWrt 固件，整理整理&lt;/p&gt;</summary>
    
    
    
    <category term="OpenWrt" scheme="https://hocg.in/categories/OpenWrt/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="OpenWrt" scheme="https://hocg.in/tags/OpenWrt/"/>
    
  </entry>
  
  <entry>
    <title>关于 Android Studio 启动 Android 模拟器失败问题</title>
    <link href="https://hocg.in/2017/07/02/%E5%85%B3%E4%BA%8EAndroid%20Studio%20%E5%90%AF%E5%8A%A8Android%E6%A8%A1%E6%8B%9F%E5%99%A8%E5%A4%B1%E8%B4%A5%E9%97%AE%E9%A2%98/"/>
    <id>https://hocg.in/2017/07/02/%E5%85%B3%E4%BA%8EAndroid%20Studio%20%E5%90%AF%E5%8A%A8Android%E6%A8%A1%E6%8B%9F%E5%99%A8%E5%A4%B1%E8%B4%A5%E9%97%AE%E9%A2%98/</id>
    <published>2017-07-02T21:07:00.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><p>Android Studio 启动虚拟机一直闪退，不显示任何报错信息</p><span id="more"></span><h2 id="排查问题"><a href="#排查问题" class="headerlink" title="排查问题"></a>排查问题</h2><ol><li>尝试用命令启动模拟器, 方便查看其错误日志<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看你创建的设备</span></span><br><span class="line">emulator -list-avds</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动命令</span></span><br><span class="line">emulator -netdelay none -netspeed full -avd New_Device_API_2</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">以下为报错日志</span></span><br><span class="line">Hax is enabled</span><br><span class="line">Hax ram_size 0x60000000</span><br><span class="line">HAX is working and emulator runs in fast virt mode.</span><br><span class="line">Failed to sync vcpu reg</span><br><span class="line">Failed to sync vcpu reg</span><br><span class="line">Failed to sync vcpu reg</span><br><span class="line">Failed to sync vcpu reg</span><br><span class="line">Failed to sync vcpu reg</span><br><span class="line">Failed to sync HAX vcpu contextInternal error: Initial hax sync failed</span><br></pre></td></tr></table></figure>vcpu无法进行同步?? What??<br>尝试进行了 Google，<a href="https://stackoverflow.com/questions/17024538/how-do-i-fix-failed-to-sync-vcpu-reg-error/17024645">How do I fix “Failed to sync vcpu reg” error?</a><br>好吧, docker 之类的虚拟机引起了冲突</li></ol><h2 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h2><p>关掉用不着的虚拟机如 docker ..</p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;起因&quot;&gt;&lt;a href=&quot;#起因&quot; class=&quot;headerlink&quot; title=&quot;起因&quot;&gt;&lt;/a&gt;起因&lt;/h2&gt;&lt;p&gt;Android Studio 启动虚拟机一直闪退，不显示任何报错信息&lt;/p&gt;</summary>
    
    
    
    <category term="Android" scheme="https://hocg.in/categories/Android/"/>
    
    
    <category term="Android" scheme="https://hocg.in/tags/Android/"/>
    
    <category term="Mac" scheme="https://hocg.in/tags/Mac/"/>
    
  </entry>
  
  <entry>
    <title>Google 使用技巧</title>
    <link href="https://hocg.in/2017/06/18/Google-%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/"/>
    <id>https://hocg.in/2017/06/18/Google-%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/</id>
    <published>2017-06-18T11:24:06.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>摩擦 Google 利器。</p><span id="more"></span><h2 id="前提"><a href="#前提" class="headerlink" title="前提"></a>前提</h2><p>使用 <a href="https://www.google.com/ncr">https://www.google.com/ncr</a> 模式并且是<code>英文版</code>。</p><h2 id="技巧"><a href="#技巧" class="headerlink" title="技巧"></a>技巧</h2><h3 id="双引号"><a href="#双引号" class="headerlink" title="双引号"></a>双引号</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2011.44.17.png" alt="image"></p><blockquote><p><strong>完全匹配搜索</strong></p></blockquote><h3 id="减号"><a href="#减号" class="headerlink" title="减号"></a>减号</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2011.46.03.png" alt="image"></p><blockquote><p>使用这个指令时减号前面必须是空格，减号后面没有空格，紧跟着需要<strong>排除特定的词</strong>。</p></blockquote><h3 id="星号"><a href="#星号" class="headerlink" title="星号"></a>星号</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2011.52.27.png" alt="image"></p><blockquote><p><em>号代表任何文字，即*<em>模糊搜索</em></em></p></blockquote><h3 id="～"><a href="#～" class="headerlink" title="～"></a>～</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.40.20.png" alt="image"></p><blockquote><p>匹配 <strong>该关键词 或 该关键词的同义词</strong></p></blockquote><h3 id="OR"><a href="#OR" class="headerlink" title="OR"></a>OR</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.35.15.png" alt="image"></p><blockquote><p>匹配关键词<code>hocgin</code>或者<code>hocg.in</code></p></blockquote><h3 id=""><a href="#" class="headerlink" title="+"></a>+</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.37.40.png" alt="image"></p><blockquote><p>匹配关键词<code>hocgin</code>与<code>hocg.in</code>同时存在</p></blockquote><h3 id="inurl"><a href="#inurl" class="headerlink" title="inurl"></a>inurl</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2011.58.08.png" alt="image"></p><blockquote><p>匹配<strong>url连接中包含该词汇</strong>，例如上方匹配 <a href="https://hocg.in/hocgin">https://hocg.in/hocgin</a></p></blockquote><h3 id="allinurl"><a href="#allinurl" class="headerlink" title="allinurl"></a>allinurl</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.21.25.png" alt="image"></p><blockquote><p>等价于: <code>inurl: hocgin inurl: hocg.in</code><br>匹配<strong>url连接中既包含<code>hocgin</code>也包含<code>hocg.in</code></strong>, 例如: <a href="https://hocg.in/hocgin">https://hocg.in/hocgin</a></p></blockquote><h3 id="inanchor"><a href="#inanchor" class="headerlink" title="inanchor"></a>inanchor</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.10.13.png" alt="image"></p><blockquote><p>匹配<strong>a标签中的文字</strong>, 例如上方匹配 &lt;a href&#x3D;”<a href="https://hocg.in">hocgin\">https://hocg.in&quot;&gt;hocgin\</a></a></p></blockquote><h3 id="intitle"><a href="#intitle" class="headerlink" title="intitle"></a>intitle</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.12.39.png" alt="image"></p><blockquote><p>匹配<strong>title标签中的文字</strong>, &lt;title&gt;hocgin&lt;&#x2F;title&gt;</p></blockquote><h3 id="allintitle"><a href="#allintitle" class="headerlink" title="allintitle"></a>allintitle</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.17.18.png" alt="image"></p><blockquote><p>等价于: <code>intitle: hocgin intitle: hocg.in</code><br>匹配<strong>标题中既包含<code>hocgin</code>也包含<code>hocg.in</code></strong>,例如: &lt;title&gt;hocgin 的博客地址 hocg.in&lt;&#x2F;title&gt;</p></blockquote><h3 id="filetype"><a href="#filetype" class="headerlink" title="filetype"></a>filetype</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.24.45.png" alt="image"></p><blockquote><p>匹配<strong>包含关键词<code>hocgin</code>的所有pdf文件</strong></p></blockquote><h3 id="site"><a href="#site" class="headerlink" title="site"></a>site</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.26.38.png" alt="image"></p><blockquote><p><strong>某个域名的搜索</strong></p></blockquote><h3 id="ralated"><a href="#ralated" class="headerlink" title="ralated"></a>ralated</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.36.45.png" alt="image"></p><blockquote><p>返回 Google 人为相关的页面</p></blockquote><p><strong>混合使用示例</strong><br><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.43.18.png" alt="image"><br><a href="">图片来源</a></p><h2 id="工具"><a href="#工具" class="headerlink" title="工具"></a>工具</h2><h3 id="查询字词的释义"><a href="#查询字词的释义" class="headerlink" title="查询字词的释义"></a>查询字词的释义</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.50.27.png" alt="image"></p><h3 id="数学运算"><a href="#数学运算" class="headerlink" title="数学运算"></a>数学运算</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.51.30.png" alt="image"></p><h3 id="天气查询"><a href="#天气查询" class="headerlink" title="天气查询"></a>天气查询</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.52.39.png" alt="image"></p><h3 id="当前时间"><a href="#当前时间" class="headerlink" title="当前时间"></a>当前时间</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.57.12.png" alt="image"></p><h3 id="日出"><a href="#日出" class="headerlink" title="日出"></a>日出</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.58.31.png" alt="image"></p><h3 id="日落"><a href="#日落" class="headerlink" title="日落"></a>日落</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2012.59.30.png" alt="image"></p><h3 id="音乐人搜索"><a href="#音乐人搜索" class="headerlink" title="音乐人搜索"></a>音乐人搜索</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.02.27.png" alt="image"></p><h3 id="省会"><a href="#省会" class="headerlink" title="省会"></a>省会</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.04.05.png" alt="image"></p><h3 id="汇率"><a href="#汇率" class="headerlink" title="汇率"></a>汇率</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.08.03.png" alt="image"></p><blockquote><p>200美元换多少人民币，可以进行数学运算</p></blockquote><h3 id="设置计时器"><a href="#设置计时器" class="headerlink" title="设置计时器"></a>设置计时器</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.09.39.png" alt="image"></p><blockquote><p>Set timer XX seconds&#x2F;minutes&#x2F;hours，XX表示具体的数字。</p></blockquote><h3 id="两地点距离计算"><a href="#两地点距离计算" class="headerlink" title="两地点距离计算"></a>两地点距离计算</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.11.53.png" alt="image"></p><h3 id="当前位置"><a href="#当前位置" class="headerlink" title="当前位置"></a>当前位置</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.14.44.png" alt="image"></p><h3 id="显示当前电脑IP"><a href="#显示当前电脑IP" class="headerlink" title="显示当前电脑IP"></a>显示当前电脑IP</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.23.04.png" alt="image"></p><h3 id="显示国家-GDP"><a href="#显示国家-GDP" class="headerlink" title="显示国家 GDP"></a>显示国家 GDP</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.25.31.png" alt="image"></p><h3 id="绘制多元方程以及复杂的方程式"><a href="#绘制多元方程以及复杂的方程式" class="headerlink" title="绘制多元方程以及复杂的方程式"></a>绘制多元方程以及复杂的方程式</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.27.12.png" alt="image"></p><blockquote><p>graph + 方程式</p></blockquote><h3 id="搜索某个单词的由来"><a href="#搜索某个单词的由来" class="headerlink" title="搜索某个单词的由来"></a>搜索某个单词的由来</h3><p><img src="http://cdn.hocgin.top/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202017-09-19%2013.31.02.png" alt="image"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;摩擦 Google 利器。&lt;/p&gt;</summary>
    
    
    
    <category term="Other" scheme="https://hocg.in/categories/Other/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Google" scheme="https://hocg.in/tags/Google/"/>
    
  </entry>
  
  <entry>
    <title>OpenWrt 入门篇</title>
    <link href="https://hocg.in/2017/05/31/OpenWrt-%E8%BF%9B%E9%98%B6%E7%AF%87/"/>
    <id>https://hocg.in/2017/05/31/OpenWrt-%E8%BF%9B%E9%98%B6%E7%AF%87/</id>
    <published>2017-05-31T14:52:26.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Tips"><a href="#Tips" class="headerlink" title="Tips"></a>Tips</h2><h3 id="查看路由器支持架构"><a href="#查看路由器支持架构" class="headerlink" title="查看路由器支持架构"></a>查看路由器支持架构</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">opkg print-architecture | awk &#x27;&#123;print $2&#125;&#x27;</span><br></pre></td></tr></table></figure><h3 id="如何更改时区"><a href="#如何更改时区" class="headerlink" title="如何更改时区?"></a>如何更改时区?</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看当前的时区</span></span><br><span class="line">date -R</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Wed, 31 May 2017 07:07:28 +0000</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改时区</span></span><br><span class="line">vi /etc/config/system</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">进行修改</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">config system</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">       option hostname <span class="string">&#x27;Openwrt&#x27;</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">       option timezone <span class="string">&#x27;CST-8&#x27;</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">       option zonename <span class="string">&#x27;Asia/Shanghai&#x27;</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重启</span></span><br><span class="line">reboot</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看是否成功</span></span><br><span class="line">date -R</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Wed, 31 May 2017 15:08:01 +0800</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">同步系统时间</span></span><br><span class="line">ntpd -n -q -p 0.asia.pool.ntp.org</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="如何在-OpenWrt-上搭建-PHP-环境"><a href="#如何在-OpenWrt-上搭建-PHP-环境" class="headerlink" title="如何在 OpenWrt 上搭建 PHP 环境?"></a>如何在 OpenWrt 上搭建 PHP 环境?</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">更新索引</span></span><br><span class="line">opkg update</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装必须的环境</span></span><br><span class="line">opkg install php5 php5-mod-gd php5-mod-curl php5-mod-session php5-mod-pdo php5-mod-mcrypt php5-mod-mbstring php5-fastcgi php5-cgi php5-mod-ctype php5-mod-exif php5-mod-iconv php5-mod-json php5-mod-sockets php5-mod-sqlite3 php5-mod-tokenizer php5-mod-zip</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置文件目录</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">/etc/httpd.conf</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重启http服务</span></span><br><span class="line">/etc/init.d/uhttpd restart</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Tips&quot;&gt;&lt;a href=&quot;#Tips&quot; class=&quot;headerlink&quot; title=&quot;Tips&quot;&gt;&lt;/a&gt;Tips&lt;/h2&gt;&lt;h3 id=&quot;查看路由器支持架构&quot;&gt;&lt;a href=&quot;#查看路由器支持架构&quot; class=&quot;headerlink&quot; title=</summary>
      
    
    
    
    <category term="OpenWrt" scheme="https://hocg.in/categories/OpenWrt/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="OpenWrt" scheme="https://hocg.in/tags/OpenWrt/"/>
    
  </entry>
  
  <entry>
    <title>字符串编码篇</title>
    <link href="https://hocg.in/2017/05/12/%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%BC%96%E7%A0%81%E7%AF%87/"/>
    <id>https://hocg.in/2017/05/12/%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%BC%96%E7%A0%81%E7%AF%87/</id>
    <published>2017-05-12T21:09:03.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p> 字符编码的来历..</p><span id="more"></span><h2 id="ASCII"><a href="#ASCII" class="headerlink" title="ASCII"></a>ASCII</h2><blockquote><p>最早只有127个字符被编码到计算机里，也就是大小写英文字母、数字和一些符号</p></blockquote><ul><li>占位: 1个字节</li></ul><h2 id="GB2312"><a href="#GB2312" class="headerlink" title="GB2312"></a>GB2312</h2><blockquote><p>中文显然一个字节是不够的，至少需要两个字节，而且还不能和ASCII编码冲突</p></blockquote><h2 id="Unicode-u-16进制"><a href="#Unicode-u-16进制" class="headerlink" title="Unicode \u[16进制]"></a>Unicode <code>\u[16进制]</code></h2><blockquote><p>Unicode把所有语言都统一到一套编码里，这样就不会再有乱码问题了。</p></blockquote><ul><li>占位: 通常是2个字节</li></ul><h2 id="UTF-8"><a href="#UTF-8" class="headerlink" title="UTF-8"></a>UTF-8</h2><blockquote><p>本着节约的精神，又出现了把Unicode编码转化为“可变长编码”<br><strong>Note:</strong> UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节，常用的英文字母被编码成1个字节，汉字通常是3个字节，只有很生僻的字符才会被编码成4-6个字节</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt; 字符编码的来历..&lt;/p&gt;</summary>
    
    
    
    <category term="Other" scheme="https://hocg.in/categories/Other/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
  </entry>
  
  <entry>
    <title>Wireshark 的使用</title>
    <link href="https://hocg.in/2017/04/20/Wireshark%E7%9A%84%E4%BD%BF%E7%94%A8/"/>
    <id>https://hocg.in/2017/04/20/Wireshark%E7%9A%84%E4%BD%BF%E7%94%A8/</id>
    <published>2017-04-20T19:34:05.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p> 抽空整理一下, 虽然<code>Charles</code>很好用, 但是某些情况下该软件也是不可替代的.</p><span id="more"></span><!-- ## 参考[WireShark](http://www.cnblogs.com/TankXiao/archive/2012/10/10/2711777.html) --><h3 id="关于Wireshark"><a href="#关于Wireshark" class="headerlink" title="关于Wireshark"></a>关于Wireshark</h3><p>适合研究 TCP,UDP 等协议. <strong>因为限制并不能改包或模拟发包，只能分析协议</strong><br>若, 研究HTTP,HTTPS推荐使用<code>Charles</code> or <code>Fiddler</code></p><h3 id="关于抓包五颜六色的意义"><a href="#关于抓包五颜六色的意义" class="headerlink" title="关于抓包五颜六色的意义"></a>关于抓包五颜六色的意义</h3><blockquote><p>更多详情查看 View - Coloring Rules</p></blockquote><ul><li>绿色背景（黑字）<code>HTTP包</code></li><li>灰色背景（黑字）<code>TCP包</code></li><li>蓝色背景 (黑字)  <code>DNS包</code></li><li>黑色背景 (红字)  <code>TCP错误包或者校验错误包</code></li></ul><h3 id="Wireshark主窗口"><a href="#Wireshark主窗口" class="headerlink" title="Wireshark主窗口"></a>Wireshark主窗口</h3><blockquote><p>从上至下</p></blockquote><p><img src="https://cloud.githubusercontent.com/assets/16535610/21889866/01695500-d906-11e6-8ddb-c82c20967ae0.png" alt="img"></p><ul><li>菜单栏: 用于开始操作。</li><li>主工具栏: 提供快速访问菜单中经常用到的项目的功能。</li><li>过滤工具栏: 提供处理当前显示过滤得方法。</li><li>拦截的数据包列表(Packet list): 显示打开文件的每个包的摘要。点击面板中的单独条目，包的其他情况将会显示在另外两个面板中。</li><li>选中的数据包信息(Packet details): 显示您在Packet list面板中选择的包的更多详情。</li><li>选中的数据包字节码: 显示您在Packet list面板选择的包的数据，以及在Packet details面板高亮显示的字段。</li><li>状态栏: 显示当前程序状态以及捕捉数据的更多详情。</li></ul><p><strong>选中的数据包信息</strong></p><ul><li>Frame: 物理层的数据帧概况</li><li>Ethernet II: 数据链路层以太网帧头部信息</li><li>Internet Protocol Version 4: 互联网层IP包头部信息</li><li>Transmission Control Protocol:  传输层T的数据段头部信息，此处是TCP</li><li>Hypertext Transfer Protocol:  应用层的信息，此处是HTTP协议</li></ul><h3 id="过滤表达式"><a href="#过滤表达式" class="headerlink" title="过滤表达式"></a>过滤表达式</h3><ul><li><p>协议过滤</p><blockquote><p>tcp upd ..</p></blockquote></li><li><p>ip 过滤</p><blockquote><p><code>来源</code> ip.src &#x3D;&#x3D; 192.168.1.1<br><code>目的地</code> ip.dst &#x3D;&#x3D; 192.168.1.1</p></blockquote></li><li><p>端口</p><blockquote><p>tcp.port &#x3D;&#x3D; 8080<br><code>仅显示来源为8080的</code> tcp.srcport &#x3D;&#x3D; 8080</p></blockquote></li><li><p>Http模式</p><blockquote><p>http.request.method&#x3D;&#x3D;”GET”</p></blockquote></li><li><p>逻辑运算符为 <code>and</code> <code>or</code></p></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt; 抽空整理一下, 虽然&lt;code&gt;Charles&lt;/code&gt;很好用, 但是某些情况下该软件也是不可替代的.&lt;/p&gt;</summary>
    
    
    
    <category term="IDE" scheme="https://hocg.in/categories/IDE/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Wireshark" scheme="https://hocg.in/tags/Wireshark/"/>
    
  </entry>
  
  <entry>
    <title>SQL的重新梳理</title>
    <link href="https://hocg.in/2017/04/07/SQL%E9%87%8D%E6%96%B0%E6%A2%B3%E7%90%86/"/>
    <id>https://hocg.in/2017/04/07/SQL%E9%87%8D%E6%96%B0%E6%A2%B3%E7%90%86/</id>
    <published>2017-04-07T09:19:09.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>持续积累..</p><span id="more"></span><h2 id="关于-SQL-执行顺序"><a href="#关于-SQL-执行顺序" class="headerlink" title="关于 SQL 执行顺序"></a>关于 SQL 执行顺序</h2><h3 id="资料"><a href="#资料" class="headerlink" title="资料"></a>资料</h3><p><a href="http://www.uol123.com/2013/01/26/sql%E8%AF%AD%E5%8F%A5%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86.html">参考</a></p><h3 id="例句"><a href="#例句" class="headerlink" title="例句"></a>例句</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> t_1 <span class="keyword">join</span> t_2</span><br><span class="line"><span class="keyword">on</span> t_1.id <span class="operator">=</span> t_2.fid</span><br><span class="line"><span class="keyword">where</span> <span class="number">1</span><span class="operator">=</span><span class="number">1</span></span><br><span class="line"><span class="keyword">group</span> <span class="keyword">by</span> t_1.className</span><br><span class="line"><span class="keyword">having</span> t_1.className <span class="operator">=</span> <span class="string">&#x27;1班&#x27;</span></span><br><span class="line"><span class="keyword">order</span> <span class="keyword">by</span> id <span class="keyword">desc</span>;</span><br></pre></td></tr></table></figure><blockquote><p>这是一条简单&#x2F;规范的基本SQL。</p></blockquote><h3 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h3><ol><li><p>SQL三个很重要的位置<strong>on&#x2F;where&#x2F;having</strong><br>它们分别对应着 <strong>join&#x2F;from&#x2F;group</strong> 形成后的虚表进行筛选。</p></li><li><p><strong>select</strong>部分并不是一开始就执行的，而是表数据确认完毕，只差排序的时候执行的。<br>并且select中的<strong>函数&#x2F;DISTINCT&#x2F;TOP</strong>也是在<strong>select</strong>执行阶段执行的</p></li><li><p><strong>聚合函数</strong>需Group后才可执行, <strong>普通函数</strong>随执行步骤执行(正常执行)</p></li></ol><h3 id="具体顺序"><a href="#具体顺序" class="headerlink" title="具体顺序"></a>具体顺序</h3><ol><li>FROM FROM后面的表标识了这条语句要查询的数据源。和一些子句如，（1-J1）笛卡尔积，（1-J2）ON过滤，（1-J3）添加外部列，所要应用的对象。FROM过程之后会生成一个虚拟表VT1。<br>(1-J1)笛卡尔积 这个步骤会计算两个相关联表的笛卡尔积(CROSS JOIN) ，生成虚拟表VT1-J1。<br>(1-J2)ON过滤 这个步骤基于虚拟表VT1-J1这一个虚拟表进行过滤，过滤出所有满足ON 谓词条件的列，生成虚拟表VT1-J2。<br>(1-J3)添加外部行  如果使用了<code>外连接(外连接才会加入字段/数据)</code>，保留表中的不符合ON条件的列也会被加入到VT1-J2中，作为外部行，生成虚拟表VT1-J3。<code>此时 不符合ON的会被加入回来</code></li><li>WHERE 对VT1过程中生成的临时表进行过滤，满足where子句的列被插入到VT2表中。 <code>数据现在还没有被分组，因此现在你不能使用聚合运算-</code></li><li>GROUP BY 这个子句会把VT2中生成的表按照GROUP BY中的列进行分组。生成VT3表。<code>每一个分组必须只能返回一行(除非被过滤掉)，即每一行整体都无重复，对于没有出现GROUP BY后面的列必须使用聚合函数(如 MAX ,MIN,COUNT,AVG等)，保证每一个GROUP只返回一行</code></li><li>HAVING 这个子句对VT3表中的不同的组进行过滤，满足HAVING条件的子句被加入到VT4表中。</li><li>SELECT 这个子句对SELECT子句中的元素进行处理，生成VT5表。<br>(5-1)计算表达式 计算SELECT 子句中的表达式，生成VT5-1 <code>如果这个sql语句是一个聚合查询，在GROUP BY之后，你只能使用GROUP BY中的列，对不属于GROUP集合中的列必须使用聚合运算</code><br>(5-2)DISTINCT 寻找VT5-1中的重复列，并删掉，生成VT5-2<br>(5-3)TOP 从ORDER BY子句定义的结果中，筛选出符合条件的列。生成VT5-3表</li><li>ORDER BY 从VT5-3中的表中，根据ORDER BY 子句的条件对结果进行排序，生成VC6表。<code>唯一一个可以使用SELECT子句创建的别名的地方</code></li></ol><blockquote><p><strong>聚合函数</strong>是对一组值执行计算并返回单一的值的函数</p></blockquote><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> C.customerid, <span class="built_in">COUNT</span>(O.orderid) <span class="keyword">AS</span> numorders</span><br><span class="line"><span class="keyword">FROM</span> dbo.Customers <span class="keyword">AS</span> C</span><br><span class="line">  <span class="keyword">LEFT</span> <span class="keyword">OUTER</span> <span class="keyword">JOIN</span> dbo.Orders <span class="keyword">AS</span> O</span><br><span class="line">    <span class="keyword">ON</span> C.customerid <span class="operator">=</span> O.customerid</span><br><span class="line"><span class="keyword">WHERE</span> C.city <span class="operator">=</span> <span class="string">&#x27;Madrid&#x27;</span></span><br><span class="line"><span class="keyword">GROUP</span> <span class="keyword">BY</span> C.customerid</span><br><span class="line"><span class="keyword">HAVING</span> <span class="built_in">COUNT</span>(O.orderid)</span><br></pre></td></tr></table></figure><h2 id="关于-表-Joins"><a href="#关于-表-Joins" class="headerlink" title="关于 表 Joins"></a>关于 表 Joins</h2><blockquote><p> Joins 子句用于结合两个或多个数据库中表的记录, 也就是说是<strong>通过某种联系建立表之间的关联, 并形成一张新表</strong></p></blockquote><h3 id="SQL-定义了三种主要类型的连接"><a href="#SQL-定义了三种主要类型的连接" class="headerlink" title="SQL 定义了三种主要类型的连接"></a>SQL 定义了三种主要类型的连接</h3><ul><li><p>交叉连接 ( <strong>CROSS JOIN</strong> ), 又称 <strong>笛卡尔积</strong></p><blockquote><p>会形成庞大的表, 因此慎用。<br><strong>假设:</strong> 表t1(5行数据, 3列), 表t2(4行数据, 2列)<br><strong>SQL:</strong> select * from t1 cross join t2<br><strong>结果:</strong> 数据数量为20行数据(5 * 4), 5列</p></blockquote></li><li><p>内连接 ( <strong>INNER JOIN</strong> ), 通常可省略 <code>inner</code></p><blockquote><p>通过 <code>on</code> 或 <code>where</code> 建立表之间的联系或者说<strong>表形成的条件</strong><br><strong>假设:</strong> 表t1(5行数据, 3列), 表t2(4行数据, 2列)<br><strong>SQL:</strong> select * from t1 inner join t2 on t1.sid &#x3D; t2.sid<br><strong>结果:</strong> 查询操作列出与连接条件匹配的数据行, 5列</p></blockquote></li><li><p>外连接 ( <strong>OUTER JOIN</strong> )</p><blockquote><p>外连接为内连接的扩展, 主要区别在于哪边为基准, 使用 <code>on</code> 进行数据关联<br>外连接分为: <code>左外连接</code>、<code>右外连接</code>、<code>全外连接</code><br>部分SQL语言并不包含全部种类, 例如<br>SQLite 之包含 <strong>左外连接</strong></p></blockquote><ul><li><p>左外连接 ( <strong>LEFT JOIN</strong> )</p><blockquote><p><strong>假设:</strong> 表t1(5行数据, 3列), 表t2(4行数据, 2列)<br><strong>SQL:</strong> select * from t1 left join t2 on t1.sid &#x3D; t2.sid<br><strong>结果:</strong> 以左表为基准, 将数据按条件进行连接, 左表行全部显示, 若右表没有满足条件的行则显示为NULL, 5列</p></blockquote></li><li><p>右外连接 ( <strong>RIGHT JOIN</strong> )</p><blockquote><p><strong>假设:</strong> 表t1(5行数据, 3列), 表t2(4行数据, 2列)<br><strong>SQL:</strong> select * from t1 right join t2 on t1.sid &#x3D; t2.sid<br><strong>结果:</strong> 以右表为基准, 将数据按条件进行连接, 右表行全部显示, 若左表没有满足条件的行则显示为NULL, 5列</p></blockquote></li><li><p>全外连接 ( <strong>FULL JOIN</strong> )</p><blockquote><p><strong>假设:</strong> 表t1(5行数据, 3列), 表t2(4行数据, 2列)<br><strong>SQL:</strong> select * from t1 full join t2 on t1.sid &#x3D; t2.sid<br><strong>结果:</strong> 完整的显示两表的数据, 将数据按条件进行连接, 当没有被关联的表中没有存在满足条件的行时, 则显示为NULL, 5列</p></blockquote></li></ul></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;持续积累..&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="SQL" scheme="https://hocg.in/tags/SQL/"/>
    
  </entry>
  
  <entry>
    <title>Vue.js项目 部件简介 (未完待续)</title>
    <link href="https://hocg.in/2017/03/31/Vue.js%E9%A1%B9%E7%9B%AE-%E9%83%A8%E4%BB%B6%E7%AE%80%E4%BB%8B/"/>
    <id>https://hocg.in/2017/03/31/Vue.js%E9%A1%B9%E7%9B%AE-%E9%83%A8%E4%BB%B6%E7%AE%80%E4%BB%8B/</id>
    <published>2017-03-31T15:32:36.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>🦋 目前国内前端MVVM最火的框架.. 前段时间写了一个<a href="https://github.com/hocgin/iPage">About页面</a>, 这几天顺带整理一下知识点.</p><span id="more"></span><h1 id="Vue-js"><a href="#Vue-js" class="headerlink" title="Vue.js"></a>Vue.js</h1><blockquote><p>Vue.js是当下很火的一个JavaScript MVVM库，它是以数据驱动和组件化的思想构建的.<br>类似的有<code>Angular.js</code>.</p></blockquote><ul><li>可以建立DOM和数据之间的绑定</li><li>可以按功能&#x2F;组件抽离HTML代码</li></ul><p><strong>相关</strong><br><a href="http://hocg.in/2017/03/26/Vue.js-%E9%A1%B9%E7%9B%AE%E5%AE%9E%E8%B7%B5">Vue 项目实践 - 持续更新</a></p><h2 id="功能部分"><a href="#功能部分" class="headerlink" title="功能部分"></a>功能部分</h2><h3 id="基础"><a href="#基础" class="headerlink" title="基础"></a>基础</h3><ul><li>数值默认双向绑定</li><li>支持 条件语法特性&#x2F;功能函数&#x2F;生命周期</li><li>动态设定<code>style</code>&#x2F;<code>class</code></li><li>捆绑<code>event</code></li><li>渲染生命周期</li></ul><h3 id="高级"><a href="#高级" class="headerlink" title="高级"></a>高级</h3><ul><li>单页面组件</li><li>自定义指令</li><li>单元测试</li><li>插件</li></ul><h2 id="单文件组件-vue"><a href="#单文件组件-vue" class="headerlink" title="单文件组件.vue"></a>单文件组件<code>.vue</code></h2><p><strong>定义:</strong></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h1</span>&gt;</span>This is title<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="attr">name</span>: <span class="string">&#x27;Title&#x27;</span></span></span><br><span class="line"><span class="language-javascript">  &#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p><strong>使用:</strong></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./assets/logo.png&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">Title</span>&gt;</span><span class="tag">&lt;/<span class="name">Title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">import</span> <span class="title class_">Title</span> <span class="keyword">from</span> <span class="string">&#x27;./components/Title&#x27;</span></span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="attr">name</span>: <span class="string">&#x27;app&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">    <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Title</span></span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h1 id="Vue-Router"><a href="#Vue-Router" class="headerlink" title="Vue Router"></a>Vue Router</h1><blockquote><p>扩展 Vue<br>按字面意思来看为<code>Vue 路由</code><br>其实质也就是用于<strong>单页应用</strong>管理页面跳转, 负责路径解析.</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Router</span> <span class="keyword">from</span> <span class="string">&#x27;vue-router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Hello</span> <span class="keyword">from</span> <span class="string">&#x27;@/components/Hello&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">Router</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">Router</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;/&#x27;</span>,</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;Hello&#x27;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="title class_">Hello</span></span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><h1 id="Vuex"><a href="#Vuex" class="headerlink" title="Vuex"></a>Vuex</h1><blockquote><p>扩展 Vue<br>当开发大型项目时, 为防止 Vue 太过臃肿, 使用 Vuex 管理数据状态.</p></blockquote><h1 id="webpack"><a href="#webpack" class="headerlink" title="webpack"></a>webpack</h1><blockquote><p>一款模块加载器兼打包工具<br>使用模块的理念来处理 JS&#x2F;CSS&#x2F;图片等资源文件</p></blockquote><h2 id="指令"><a href="#指令" class="headerlink" title="指令"></a>指令</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">npm install webpack --save-dev</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">执行</span></span><br><span class="line">webpack</span><br><span class="line">   --display-error-details # 输出详细错误</span><br><span class="line">   --watch # 实时监听并自动打包</span><br><span class="line">   --config &lt;file&gt; # 指定配置文件打包</span><br><span class="line">   -p # 压缩打包</span><br><span class="line">   -d # 生成map映射文件</span><br></pre></td></tr></table></figure><h2 id="配置-webpack-config-js"><a href="#配置-webpack-config-js" class="headerlink" title="配置(webpack.config.js)"></a>配置(webpack.config.js)</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="comment">// 插件</span></span><br><span class="line">  <span class="attr">plugins</span>: [],</span><br><span class="line">  <span class="comment">// 页面入口</span></span><br><span class="line">  <span class="attr">entry</span>: &#123;&#125;,</span><br><span class="line">  <span class="comment">// 入口文件输出位置, 即处理后的文件存放位置</span></span><br><span class="line">  <span class="attr">output</span>: &#123;&#125;,</span><br><span class="line">  <span class="attr">module</span>: &#123;</span><br><span class="line">    <span class="comment">// 文件处理加载器</span></span><br><span class="line">    <span class="attr">rules</span>: []</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 额外处理</span></span><br><span class="line">  <span class="attr">resolve</span>: &#123;</span><br><span class="line">    <span class="comment">// 自动扩展文件后缀, require时可以进行省略</span></span><br><span class="line">    <span class="attr">extensions</span>: [],</span><br><span class="line">    <span class="comment">// 模块定义别名, require时可以进行路径省略, 直接使用别名</span></span><br><span class="line">    <span class="attr">alias</span>: &#123;&#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="入口文件-main-js"><a href="#入口文件-main-js" class="headerlink" title="入口文件(main.js)"></a>入口文件(main.js)</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">App</span> <span class="keyword">from</span> <span class="string">&#x27;./App&#x27;</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;./router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">&#x27;./store/index&#x27;</span></span><br><span class="line"><span class="comment">// 引入js, 加载器会自动进行处理</span></span><br><span class="line"><span class="keyword">import</span> holderjs <span class="keyword">from</span> <span class="string">&#x27;holderjs&#x27;</span></span><br><span class="line"><span class="comment">// 引入 css/scss, 加载器会自动进行处理</span></span><br><span class="line"><span class="keyword">import</span> appScss <span class="keyword">from</span> <span class="string">&#x27;./assets/app.scss&#x27;</span></span><br><span class="line"><span class="keyword">import</span> fontAwesomeCss <span class="keyword">from</span> <span class="string">&#x27;./assets/font-awesome-4.7.0/css/font-awesome.css&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property">config</span>.<span class="property">productionTip</span> = <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* eslint-disable no-new */</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  <span class="attr">el</span>: <span class="string">&#x27;#app&#x27;</span>,</span><br><span class="line">  router,</span><br><span class="line">  store,</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&#x27;&lt;App/&gt;&#x27;</span>,</span><br><span class="line">  <span class="attr">components</span>: &#123; <span class="title class_">App</span> &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><blockquote><p>未完待续ing</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;🦋 目前国内前端MVVM最火的框架.. 前段时间写了一个&lt;a href=&quot;https://github.com/hocgin/iPage&quot;&gt;About页面&lt;/a&gt;, 这几天顺带整理一下知识点.&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="JavaScript" scheme="https://hocg.in/tags/JavaScript/"/>
    
    <category term="HTML5" scheme="https://hocg.in/tags/HTML5/"/>
    
    <category term="前端" scheme="https://hocg.in/tags/%E5%89%8D%E7%AB%AF/"/>
    
  </entry>
  
  <entry>
    <title>Vue 项目实践 - 持续更新</title>
    <link href="https://hocg.in/2017/03/26/Vue.js-%E9%A1%B9%E7%9B%AE%E5%AE%9E%E8%B7%B5/"/>
    <id>https://hocg.in/2017/03/26/Vue.js-%E9%A1%B9%E7%9B%AE%E5%AE%9E%E8%B7%B5/</id>
    <published>2017-03-26T15:40:08.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>🐌 目前国内前端MVVM最火的框架.. 项目实践记录一些流程</p><span id="more"></span><h1 id="相关"><a href="#相关" class="headerlink" title="相关"></a>相关</h1><ul><li>vue<ul><li>vue-router <code>给vue使用的路由</code></li><li>vuex <code>一个专为 Vue.js 应用程序开发的状态管理模式</code></li></ul></li><li>webpack</li></ul><h1 id="快速搭建项目"><a href="#快速搭建项目" class="headerlink" title="快速搭建项目"></a>快速搭建项目</h1><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">构建项目</span></span><br><span class="line">npm install -g vue-cli</span><br><span class="line">vue init webpack &lt;project-name&gt;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">试行</span></span><br><span class="line">cd iPage</span><br><span class="line">npm install</span><br><span class="line">npm run dev</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 vuex</span></span><br><span class="line">npm install vuex -S</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 sass 开发支持</span></span><br><span class="line">npm install --save-dev sass-loader</span><br><span class="line">npm install --save-dev node-sass</span><br><span class="line">npm install --save-dev css-loader</span><br><span class="line">npm install --save-dev style-loader</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">编译生成静态文件</span></span><br><span class="line">npm run build</span><br></pre></td></tr></table></figure><h1 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">.  </span><br><span class="line">├── README.md  </span><br><span class="line">├── build  </span><br><span class="line">├── config   </span><br><span class="line">├── index.html  </span><br><span class="line">├── node_modules  </span><br><span class="line">├── package.json  </span><br><span class="line">├── src // 源码</span><br><span class="line">|    ├── App.vue    // 父组件  </span><br><span class="line">|    ├── assets     // 静态文件  </span><br><span class="line">|    ├── components // 公共组件  </span><br><span class="line">|    ├── main.js    // webpack打包入口文件  </span><br><span class="line">|    └── router  </span><br><span class="line">|          └── index.js // 页面路由  </span><br><span class="line">├── static  </span><br><span class="line">└── test  </span><br></pre></td></tr></table></figure><h1 id="遇到的问题"><a href="#遇到的问题" class="headerlink" title="遇到的问题"></a>遇到的问题</h1>]]></content>
    
    
    <summary type="html">&lt;p&gt;🐌 目前国内前端MVVM最火的框架.. 项目实践记录一些流程&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="JavaScript" scheme="https://hocg.in/tags/JavaScript/"/>
    
    <category term="HTML5" scheme="https://hocg.in/tags/HTML5/"/>
    
    <category term="前端" scheme="https://hocg.in/tags/%E5%89%8D%E7%AB%AF/"/>
    
  </entry>
  
  <entry>
    <title>关于 Objective-C 的小笔记</title>
    <link href="https://hocg.in/2017/03/20/%E5%85%B3%E4%BA%8E%20Objective-C%20%E7%9A%84%E5%B0%8F%E7%AC%94%E8%AE%B0/"/>
    <id>https://hocg.in/2017/03/20/%E5%85%B3%E4%BA%8E%20Objective-C%20%E7%9A%84%E5%B0%8F%E7%AC%94%E8%AE%B0/</id>
    <published>2017-03-20T08:07:00.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>之前学 <code>swift3</code> 顺带整理的小笔记</p><span id="more"></span><h1 id="Objective-C"><a href="#Objective-C" class="headerlink" title="Objective-C"></a>Objective-C</h1><h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><table><thead><tr><th>文件后缀</th><th>文件类型</th></tr></thead><tbody><tr><td><code>*.h</code></td><td><strong>头文件</strong>。头文件包含类，类型，函数和常数的声明。</td></tr><tr><td><code>*.m</code></td><td><strong>源代码文件</strong>。这是典型的源代码文件扩展名，可以包含 Objective-C 和 C 代码</td></tr><tr><td><code>*.mm</code></td><td><strong>源代码文件</strong>。带有这种扩展名的源代码文件，除了可以包含Objective-C和C代码以外还可以包含C++代码。仅在你的Objective-C代码中确实需要使用C++类或者特性的时候才用这种扩展名。</td></tr></tbody></table><h2 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h2><table><thead><tr><th>关键词</th><th>说明</th></tr></thead><tbody><tr><td>#import</td><td>引入文件, 并确保相同的文件只会被包含一次</td></tr><tr><td>NSString* say &#x3D; @”Hello World”</td><td>创建NSString对象</td></tr><tr><td>@interface&#x2F;@implementation</td><td>objective-c 一个类是由:定义和实现来构成的, @interface 用于定义, @implementation用于实现细节.</td></tr><tr><td>@property与@synthesize</td><td>@property用于在@interface声明getter与setter函数, @synthesize用于在@implementation实现getter与setter函数, <br/><strong>二者是搭配口味</strong><br/><strong>高版本(Xcode4.5)可省略@synthesize</strong></td></tr></tbody></table><h2 id="基础框架"><a href="#基础框架" class="headerlink" title="基础框架"></a>基础框架</h2><h3 id="lt-Foundation-x2F-Foundation-h-gt"><a href="#lt-Foundation-x2F-Foundation-h-gt" class="headerlink" title="&lt;Foundation&#x2F;Foundation.h&gt;"></a>&lt;Foundation&#x2F;Foundation.h&gt;</h3><ul><li>它包括 NSArray，NSDictionary中的NSSet等扩展数据类型的列表。</li><li>它由一组丰富的操作文件的函数，字符串，等等。</li><li>URL处理它提供的功能，如日期格式，数据处理，错误处理等实用工具</li></ul><h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><h3 id="语法速读"><a href="#语法速读" class="headerlink" title="语法速读"></a>语法速读</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">/* 预处理(导包) */</span><br><span class="line">#import &lt;Foundation/Foundation.h&gt;</span><br><span class="line"></span><br><span class="line">/* 定义接口(继承:NSObject) */</span><br><span class="line">@interface SampleClass:NSObject</span><br><span class="line">- (void)sampleMethod;</span><br><span class="line">@end</span><br><span class="line"></span><br><span class="line">/* 实现接口(SampleClass) */</span><br><span class="line">@implementation SampleClass</span><br><span class="line"></span><br><span class="line">- (void)sampleMethod&#123;</span><br><span class="line">   NSLog(@&quot;Hello, World!</span><br><span class="line">&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@end</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">/* 主函数 */</span><br><span class="line">int main() &#123;</span><br><span class="line">   /* my first program in Objective-C */</span><br><span class="line">   SampleClass *sampleClass = [[SampleClass alloc]init];</span><br><span class="line"></span><br><span class="line">   /* - 调用函数</span><br><span class="line">   C: sampleClass.sampleMethod(args);</span><br><span class="line">   OC: [对象 函数名: 参数]</span><br><span class="line">    */</span><br><span class="line">   [sampleClass sampleMethod: args];</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">   return 0;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="类的语法"><a href="#类的语法" class="headerlink" title="类的语法"></a>类的语法</h3><blockquote><p>类分为: <strong>类的定义(.h)</strong> 和 <strong>类的实现(.m)</strong><br><img src="http://cdn.hocgin.top/%E7%B1%BB%E7%9A%84%E5%AE%9A%E4%B9%89%E8%AF%AD%E6%B3%95.jpg" alt="image"></p></blockquote><h4 id="定义-h"><a href="#定义-h" class="headerlink" title="定义 ( *.h )"></a>定义 ( *.h )</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">@interface MyObject : NSObject</span><br><span class="line">&#123;</span><br><span class="line">    // 此处变量默认为受保护(protected)</span><br><span class="line">    int memberVar1; // 实体变量</span><br><span class="line">    id  memberVar2;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">+(return_type) class_method; // &quot;+&quot; 表示 类方法</span><br><span class="line"></span><br><span class="line">-(return_type) instance_method1; // &quot;-&quot; 表示 实例方法</span><br><span class="line">-(return_type) instance_method2: (int) p1;</span><br><span class="line">// 这里的调用方式为: [obj instance_method3: 1 andPar: 2];</span><br><span class="line">// andPar 相当于外部的另外一个别名</span><br><span class="line">-(return_type) instance_method3: (int) p1 andPar: (int) p2;</span><br><span class="line">@end</span><br></pre></td></tr></table></figure><h4 id="实现-m"><a href="#实现-m" class="headerlink" title="实现 ( *.m )"></a>实现 ( *.m )</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">@implementation MyObject</span><br><span class="line">&#123;</span><br><span class="line">  // 此处变量为私有(private)</span><br><span class="line">  int memberVar3; //私有实体变量</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">+(return_type) class_method &#123;</span><br><span class="line">    .... //method implementation</span><br><span class="line">&#125;</span><br><span class="line">-(return_type) instance_method1 &#123;</span><br><span class="line">     ....</span><br><span class="line">&#125;</span><br><span class="line">-(return_type) instance_method2: (int) p1 &#123;</span><br><span class="line">    ....</span><br><span class="line">&#125;</span><br><span class="line">-(return_type) instance_method3: (int) p1 andPar: (int) p2 &#123;</span><br><span class="line">    ....</span><br><span class="line">&#125;</span><br><span class="line">@end</span><br></pre></td></tr></table></figure><h4 id="创建对象"><a href="#创建对象" class="headerlink" title="创建对象"></a>创建对象</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// 注: alloc 与 init 都属于 NSObject 里的函数</span><br><span class="line">MyObject * my = [[MyObject alloc] init];</span><br><span class="line">// 无参构建, 也可采用以下方式 (Objective-C 2.0)</span><br><span class="line">MyObject * my = [MyObject new];</span><br></pre></td></tr></table></figure><blockquote><p><strong>Note:</strong> { } 需如文这样标识, 才可表达出准确的语义, 读者自行领悟.</p></blockquote><h3 id="函数语法"><a href="#函数语法" class="headerlink" title="函数语法"></a>函数语法</h3><blockquote><p>函数分为: <strong>类函数</strong> 和 <strong>对象函数</strong><br><img src="http://cdn.hocgin.top/%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9A%E4%B9%89%E8%AF%AD%E6%B3%95.jpg" alt="image"></p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">// 如上</span><br><span class="line">// 定义语法: 范围标识 (返回值)函数名:外部形参别名:(参数类型) 形参名 外部形参别名:(参数类型) 形参名</span><br><span class="line">// 注: 第一个 外部形参别名 可省略</span><br><span class="line">- (void)insertObject:(id)anObject atIndex:(NSUInteger) index</span><br><span class="line">+ (void)insertObject:(id)anObject atIndex:(NSUInteger) index</span><br><span class="line"></span><br><span class="line">// 调用</span><br><span class="line">// 对象调用 [对象 函数名: 参数1 外部形参别名: 参数2]</span><br><span class="line">[obj insertObject: arg1 atIndex: arg2]</span><br><span class="line">// 类调用 [类名 函数名: 参数1 外部形参别名: 参数2]</span><br><span class="line">[Object insertObject: arg1 atIndex: arg2]</span><br><span class="line"></span><br><span class="line">// 注:) 类调用 和 对象调用 的形式是一样的</span><br></pre></td></tr></table></figure><h3 id="属性语法"><a href="#属性语法" class="headerlink" title="属性语法"></a>属性语法</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">@interface Person : NSObject</span><br><span class="line">&#123;</span><br><span class="line">/*</span><br><span class="line">相当于 @public 至 @private 之间的属性被暴露出去</span><br><span class="line">可通过实例直接访问, 例如: obj-&gt;name</span><br><span class="line">*/</span><br><span class="line">@public</span><br><span class="line">  NSString *name;</span><br><span class="line">@private</span><br><span class="line">  int age;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">  参考: http://justcoding.iteye.com/blog/1444548</span><br><span class="line">  使用范围: @interface, @protocol, @category</span><br><span class="line">  可声明特性:</span><br><span class="line">          读写属性：   （readwrite/readonly）</span><br><span class="line">          setter语意：（assign/retain/copy）</span><br><span class="line">          原子性：    （atomicity/nonatomic）</span><br><span class="line">  使用效果(声明一个setter与getter方法):</span><br><span class="line">    - (NSString*)name;  </span><br><span class="line">    - (void)setName: (NSString*)newName;</span><br><span class="line"> */</span><br><span class="line">@property(copy) NSString *name;</span><br><span class="line">@property(readonly) int age;</span><br><span class="line"></span><br><span class="line">-(id)initWithAge:(int)age;</span><br><span class="line"></span><br><span class="line">@end</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">@implementation Person</span><br><span class="line">/*</span><br><span class="line">  使用范围: @implementation</span><br><span class="line">  使用效果(自动实现一个setter与getter方法):</span><br><span class="line">    - (NSString*)name &#123;</span><br><span class="line">      return name;</span><br><span class="line">    &#125;  </span><br><span class="line">    - (void)setName: (NSString*)newName &#123;</span><br><span class="line">      name = newName;</span><br><span class="line">    &#125;</span><br><span class="line"> */</span><br><span class="line">@synthesize name;</span><br><span class="line">/* @dynamic 仅仅是告诉编译器这两个方法在运行期会有的，无需产生警告 */</span><br><span class="line">@dynamic age;</span><br><span class="line"></span><br><span class="line">-(id)initWithAge:(int)initAge</span><br><span class="line">&#123;</span><br><span class="line">    age = initAge; // 注意：直接赋给成员变量，而非属性</span><br><span class="line">    return self;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">-(int)age</span><br><span class="line">&#123;</span><br><span class="line">    return 29; // 注意：并非返回真正的年龄</span><br><span class="line">&#125;</span><br><span class="line">@end</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="类或协议的属性可以被动态的读取"><a href="#类或协议的属性可以被动态的读取" class="headerlink" title="类或协议的属性可以被动态的读取"></a>类或协议的属性可以被动态的读取</h4><blockquote><p>类似反射机制 , 略过..</p></blockquote><h3 id="快速枚举"><a href="#快速枚举" class="headerlink" title="快速枚举"></a>快速枚举</h3><blockquote><p>一种省内存的循环遍历 , 略过..</p></blockquote><h3 id="协议语法"><a href="#协议语法" class="headerlink" title="协议语法"></a>协议语法</h3><blockquote><p>类似 Java 中的接口</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">/*定义协议*/</span><br><span class="line">@protocol Locking</span><br><span class="line">- (void)lock;</span><br><span class="line">- (void)unlock;</span><br><span class="line">@end</span><br><span class="line">/*</span><br><span class="line">类的@interface 宣称使用 协议</span><br><span class="line">*/</span><br><span class="line">@interface SomeClass : SomeSuperClass &lt;Locking&gt;</span><br><span class="line">@end</span><br><span class="line">/*</span><br><span class="line">类的@implementation 实现 协议 细节</span><br><span class="line">*/</span><br><span class="line">@implementation SomeClass</span><br><span class="line">- (void)lock &#123;</span><br><span class="line">  // 实现lock方法...</span><br><span class="line">&#125;</span><br><span class="line">- (void)unlock &#123;</span><br><span class="line">  // 实现unlock方法...</span><br><span class="line">&#125;</span><br><span class="line">@end</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="动态类型"><a href="#动态类型" class="headerlink" title="动态类型"></a>动态类型</h3><blockquote><p>id 相当于 Java 中的 Object, 即 任意对象</p></blockquote><h3 id="类别-Category-语法"><a href="#类别-Category-语法" class="headerlink" title="类别 (Category) 语法"></a>类别 (Category) 语法</h3><blockquote><p>分类不仅可以增加类的方法，也可以代替原有的<strong>函数</strong>, <strong>并不能新增变量</strong><br>动态增加和替换函数, 强得一匹</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">/*</span><br><span class="line">  说明: 定义扩展 Integer类 接口, 新增/覆盖 函数 showstars 与 showint</span><br><span class="line">  语法:</span><br><span class="line">    #import &quot;待扩展类接口文件.h&quot;</span><br><span class="line">    @interface 待扩展类(扩展类)</span><br><span class="line">      // 函数定义</span><br><span class="line">    @end</span><br><span class="line">*/</span><br><span class="line">#import &quot;Integer.h&quot;</span><br><span class="line">@interface Integer(Display)</span><br><span class="line">- (id) showstars;</span><br><span class="line">- (id) showint;</span><br><span class="line">@end</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">  说明: 实现扩展 Integer类 接口, 新增/覆盖 函数 showstars 与 showint</span><br><span class="line">  语法:</span><br><span class="line">    #import &quot;扩展类接口文件.h&quot;</span><br><span class="line">    @implementation 待扩展类(扩展类)</span><br><span class="line">      // 函数实现</span><br><span class="line">    @end</span><br><span class="line">*/</span><br><span class="line">#import &quot;Display.h&quot;</span><br><span class="line">@implementation Integer(Display)</span><br><span class="line">- (id) showstars &#123;</span><br><span class="line">  ..</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">- (id) showint &#123;</span><br><span class="line">    ..</span><br><span class="line">&#125;</span><br><span class="line">@end</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>NOTE:</strong> 使用时需#import 待扩展类与扩展类的接口文件**(.h)**</p><h2 id="划重点"><a href="#划重点" class="headerlink" title="划重点"></a>划重点</h2><ul><li><code>NSString*</code>&#x2F;<code>NSObject*</code>等 表示对象</li><li><code>self</code> 某种程度相当于 <code>this</code></li><li>nil 基本上等同于 NULL</li><li>调用属性 self-&gt;name</li><li>一般(.h 存放**@interface文件**, .m 存放**@implementation文件**). 进行#import时, 只需#import .h文件</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;之前学 &lt;code&gt;swift3&lt;/code&gt; 顺带整理的小笔记&lt;/p&gt;</summary>
    
    
    
    <category term="Mac" scheme="https://hocg.in/categories/Mac/"/>
    
    
    <category term="语法" scheme="https://hocg.in/tags/%E8%AF%AD%E6%B3%95/"/>
    
    <category term="Objective-C" scheme="https://hocg.in/tags/Objective-C/"/>
    
  </entry>
  
  <entry>
    <title>PHP Laravel 快速入门</title>
    <link href="https://hocg.in/2017/03/01/PHP-laravel-%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/"/>
    <id>https://hocg.in/2017/03/01/PHP-laravel-%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/</id>
    <published>2017-03-01T14:59:38.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>PHP 框架 Laravel 搭建开始, 慢慢更新~ 😜😜😜😜</p><span id="more"></span><h1 id="Quit-Start"><a href="#Quit-Start" class="headerlink" title="Quit Start"></a>Quit Start</h1><p>一. 安装<code>composer</code>, 用于管理依赖</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">全局安装 macOS</span></span><br><span class="line">brew update</span><br><span class="line">brew tap josegonzalez/homebrew-php</span><br><span class="line">brew tap homebrew/versions</span><br><span class="line">brew install php55-intl</span><br><span class="line">brew install josegonzalez/php/composer</span><br></pre></td></tr></table></figure><p>二. 下载<code>laravel</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer global require &quot;laravel/installer&quot;</span><br></pre></td></tr></table></figure><p>三. 创建项目</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer create-project laravel/laravel --prefer-dist</span><br></pre></td></tr></table></figure><p>四. 关于如何使用<code>PhpStorm</code>  </p><blockquote><p>默认已经配置好PHP开发环境了!</p></blockquote><p>4.0.1 相关插件</p><ul><li>Laravel Plugin</li><li><strong>[Optional]</strong> PHP Annotations Plugin</li><li><strong>[Optional]</strong> Symfony2 Plugin</li></ul><p>4.1 配置<code>Composer</code></p><ul><li>右键项目根节点 -&gt; Composer -&gt; init composer, 配置<code>PHP解释器</code>和<code>Composer路径</code></li></ul><p><img src="http://cdn.hocgin.top/874D3259-AB37-4EA4-BAAC-CA17674334C8.png" alt="image"></p><ul><li>右键项目根节点 -&gt; Composer -&gt; add dependency, 添加<code>barryvdh/laravel-ide-helper</code></li></ul><p><img src="http://cdn.hocgin.top/2F36AE2A-A1A7-40D0-8668-26EB0038BBCE.png" alt="image"><br>或者</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require barryvdh/laravel-ide-helper</span><br></pre></td></tr></table></figure><p>4.2 编辑<code>config/app.php</code>文件, 在<code>providers</code>节点下面添加<br><img src="http://cdn.hocgin.top/4761A0E6-27E9-4544-B379-DE897A42E24E.png" alt="image"></p><p>4.3 扩展命令工具</p><ul><li>Preferences -&gt; Tools -&gt; Command Line Tool Support</li></ul><p><img src="http://cdn.hocgin.top/A84F6129-8F9E-4BC3-BAAA-D32FEFB7F1D5.png" alt="image"></p><p><img src="http://cdn.hocgin.top/3C942985-0082-4675-BA3F-1FCC3A83CD2B.png" alt="image"></p><p><strong>使用</strong>: Tools -&gt; Run Command(⌘ + ⇧ + X)</p><p><img src="http://cdn.hocgin.top/363F317B-FED9-40AE-A30A-84216A3A2721.png" alt="image"></p><p>4.4 配置 php-xdebug</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查是否安装php-xdebug</span></span><br><span class="line">php -m</span><br></pre></td></tr></table></figure><p>安装后，修改下php.ini把xdebug.so前的注释’;’去掉</p><p><img src="http://cdn.hocgin.top/5157CD6B-FD07-4F82-9DE6-9E8BEA21D504.png" alt="image"></p><p>五. 配置启动<br><img src="http://cdn.hocgin.top/A1D8FA94-D5A1-46A6-AE09-B638BC4C5FCE.png" alt="image"></p><p>六. 配置Debug</p><p><img src="http://cdn.hocgin.top/03337E90-7562-498F-A595-98FEA679EDDE.png" alt="image"><br>并且在根目录加入<code>debug.ini</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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">xdebug.remote_enable = On</span><br><span class="line">xdebug.remote_autostart = On</span><br><span class="line">upload_max_filesize = 1000M</span><br><span class="line">post_max_size = 1005M</span><br><span class="line">max_execution_time = 120</span><br><span class="line"></span><br><span class="line">;xdebug.profiler_enable = On</span><br><span class="line">;xdebug.profiler_enable_trigger = Off</span><br><span class="line">;xdebug.profiler_output_dir = ./xdebug</span><br><span class="line">;xdebug.profiler_aggregate = On</span><br><span class="line">;xdebug.profiler_append = On</span><br><span class="line">;xdebug.profiler_output_name = &quot;cachegrind.out.%R.%u.%p&quot;</span><br></pre></td></tr></table></figure><h1 id="资源"><a href="#资源" class="headerlink" title="资源"></a>资源</h1><p><a href="https://github.com/koomai/phpstorm-laravel-live-templates#requests--input">Laravel Live Templates for PhpStorm</a><br><a href="https://laracasts.com/series/how-to-be-awesome-in-phpstorm/episodes/15">Laravel 插件视频</a></p><h2 id="标签"><a href="#标签" class="headerlink" title="标签"></a>标签</h2><ul><li><p>继承<br><code>@extends</code></p></li><li><p>存在替换<br><code>@yield(&#39;content&#39;)</code><br><code>@section</code><br><code>@endsection</code></p></li><li><p>增加<br><code>@stack(&quot;appendCSS&quot;)</code><br><code>@push(&#39;appendCSS&#39;)</code><br><code>@endpush</code></p></li><li><p>注入<br><code>@inject(&quot;xx&quot;, &quot;xx[Name]&quot;)</code></p></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;PHP 框架 Laravel 搭建开始, 慢慢更新~ 😜😜😜😜&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="Mac" scheme="https://hocg.in/tags/Mac/"/>
    
    <category term="PHP" scheme="https://hocg.in/tags/PHP/"/>
    
  </entry>
  
  <entry>
    <title>Nginx 部署</title>
    <link href="https://hocg.in/2017/02/24/Nginx-%E9%83%A8%E7%BD%B2/"/>
    <id>https://hocg.in/2017/02/24/Nginx-%E9%83%A8%E7%BD%B2/</id>
    <published>2017-02-24T09:12:22.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>🎽  <a href="http://baike.baidu.com/link?url=6LDqhy3I7UWDkwOT6TS_s-d4Jsv9AVcA_yedSmd618s1BjJl-0NQ-roxjDF7jHazXWlTwbIHTv03_gWIWeRPUq">Nginx</a> 是一个很强大的高性能Web和反向代理服务器</p><span id="more"></span><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><h3 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h3><p>OS: Ubuntu-16</p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><h3 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h3><ul><li><a href="http://www.pcre.org/">PCRE</a></li><li><a href="http://zlib.net/">zlib</a></li><li><a href="nginx.org/en/download.html">nginx</a></li></ul><h3 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h3><p>&#x2F;opt<br>|– nginx-1.10.1<br>|– pcre-8.38<br>`– zlib-1.2.8</p><h3 id="shell"><a href="#shell" class="headerlink" title="shell"></a>shell</h3><blockquote><p>以下操作均在<code>/opt</code>目录</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">tar -zxvf nginx-1.10.1.tar.gz</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">cd</span> nginx-1.10.1</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./configure</span></span><br></pre></td></tr></table></figure><p>ERROR:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">checking for OS</span><br><span class="line"> + Linux 2.6.32-042stab113.21 x86_64</span><br><span class="line">checking for C compiler ... not found</span><br><span class="line"></span><br><span class="line">./configure: error: C compiler cc is not found</span><br></pre></td></tr></table></figure><p>缺失编译部件, 解决办法如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">apt-get install build-essential libtool</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./configure</span></span><br></pre></td></tr></table></figure><p>Error:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">./configure: error: the HTTP rewrite module requires the PCRE library.</span><br><span class="line">You can either disable the module by using --without-http_rewrite_module</span><br><span class="line">option, or install the PCRE library into the system, or build the PCRE library</span><br><span class="line">statically from the source with nginx by using --with-pcre=&lt;path&gt; option.</span><br></pre></td></tr></table></figure><p>缺失<code>PCRE</code>, 移步官网下载(<code>顶部有链接</code>), 我是在<code>/opt</code>目录中解压<br><strong>注</strong>: pcre 没有 <code>2</code></p><blockquote><p>以下操作均在<code>/opt</code>目录  </p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">tar -jxvf pcre-8.38.tar.bz2</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">cd</span> pcre-8.38</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./configure &amp;&amp; make &amp;&amp; make install</span></span><br></pre></td></tr></table></figure><p>回到<code>/opt/nginx-1.10.1</code>目录继续进行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./configure --with-pcre=/opt/pcre-8.38</span></span><br></pre></td></tr></table></figure><p>Error:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">./configure: error: the HTTP gzip module requires the zlib library.</span><br><span class="line">You can either disable the module by using --without-http_gzip_module</span><br><span class="line">option, or install the zlib library into the system, or build the zlib library</span><br><span class="line">statically from the source with nginx by using --with-zlib=&lt;path&gt; option.</span><br></pre></td></tr></table></figure><p>原因是缺失<code>zlib</code>,移步官网下载(<code>顶部有链接</code>), 同样是在<code>/opt</code>目录中解压</p><blockquote><p>以下操作均在<code>/opt</code>目录  </p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">tar -zxvf zlib-1.2.8.tar.gz</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">cd</span> zlib-1.2.8</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./configure &amp;&amp; make &amp;&amp; make install</span></span><br></pre></td></tr></table></figure><p>回到<code>/opt/nginx-1.10.1</code>目录继续进行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./configure --with-pcre=/opt/pcre-8.38 --with-zlib=/opt/zlib-1.2.8</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">make</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">make install</span></span><br></pre></td></tr></table></figure><p>至此，安装结束。可查看<code>ls /usr/local/nginx/</code>目录<br>显示如下文件:<br>&#x2F;usr&#x2F;local&#x2F;nginx&#x2F;<br><img src="http://cdn.hocgin.top/E3B25E4D-8D26-4E4D-BBA2-F77F7B089FA5.png" alt="image"></p><h2 id="基础命令"><a href="#基础命令" class="headerlink" title="基础命令"></a>基础命令</h2><blockquote><p>以下命令均在<code>/usr/local/nginx</code>目录下运行  </p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动</span></span><br><span class="line">./sbin/nginx</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">检查配置</span></span><br><span class="line">./sbin/nginx -t</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重新加载配置</span></span><br><span class="line">./sbin/nginx -s reload</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看配置文件</span></span><br><span class="line">cat ./conf/nginx.conf</span><br></pre></td></tr></table></figure><h2 id="扩展"><a href="#扩展" class="headerlink" title="扩展"></a>扩展</h2><h3 id="nginx-conf配置"><a href="#nginx-conf配置" class="headerlink" title="nginx.conf配置"></a><code>nginx.conf</code>配置</h3><p><a href="http://blog.csdn.net/tjcyjd/article/details/50695922">字段详解</a></p><h3 id="模块"><a href="#模块" class="headerlink" title="模块"></a>模块</h3><p><strong>待续ing</strong></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;🎽  &lt;a href=&quot;http://baike.baidu.com/link?url=6LDqhy3I7UWDkwOT6TS_s-d4Jsv9AVcA_yedSmd618s1BjJl-0NQ-roxjDF7jHazXWlTwbIHTv03_gWIWeRPUq&quot;&gt;Nginx&lt;/a&gt; 是一个很强大的高性能Web和反向代理服务器&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="Ubuntu" scheme="https://hocg.in/tags/Ubuntu/"/>
    
  </entry>
  
  <entry>
    <title>关于Chrome 插件开发的一些知识点</title>
    <link href="https://hocg.in/2017/02/04/%E5%85%B3%E4%BA%8EChrome%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E4%BA%9B%E7%9F%A5%E8%AF%86%E7%82%B9/"/>
    <id>https://hocg.in/2017/02/04/%E5%85%B3%E4%BA%8EChrome%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E4%BA%9B%E7%9F%A5%E8%AF%86%E7%82%B9/</id>
    <published>2017-02-04T13:20:51.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>身为Chrome重度患者，生活和工作处处不离，这篇并不是入门教程，而是开发中的一些小Tip的记录.</p><span id="more"></span><h1 id="我开发的Chrome-插件"><a href="#我开发的Chrome-插件" class="headerlink" title="我开发的Chrome 插件"></a>我开发的Chrome 插件</h1><ul><li><a href="https://github.com/hocgin/Weather-For-Chrome-Plugin">天气预报</a></li></ul><h1 id="数据存储"><a href="#数据存储" class="headerlink" title="数据存储"></a>数据存储</h1><ul><li>HTML5 <code>localStorage</code> <strong>存储在解析页面当前范围和网站共享localStorage</strong></li><li>Chrome API <code>chrome.storage</code> <strong>存储在系统磁盘，适合少量数据</strong></li><li>Web SQL Database <strong>存储在系统磁盘，适合大量数据</strong></li></ul><h1 id="脚本运行范围"><a href="#脚本运行范围" class="headerlink" title="脚本运行范围"></a>脚本运行范围</h1><ul><li>background <strong>浏览器打开后运行, 会一直存在于后台, 因此开发时更改后必须<code>⌘+R</code>重新加载</strong></li><li>content_scripts <strong>在网页加载后运行</strong></li><li>html内导入的脚本 <strong>运行于该html页面, 例如: option页面和popup页面</strong></li></ul><p><strong>Note:</strong></p><blockquote><p>popup.js 于background.js 是可以进行共通的.<br>使用<code>var BG = chrome.extension.getBackgroundPage();</code> BG便是<code>background.js</code>的<code>window</code>对象</p></blockquote><h1 id="Action-入口"><a href="#Action-入口" class="headerlink" title="Action 入口"></a>Action 入口</h1><ul><li>地址栏右侧图标外 <code>browser_action</code> <strong>可显示badge</strong></li><li>右键菜单 <code>chrome.contextMenus</code> <strong>可在<code>background</code>中创建</strong></li><li>地址栏右侧图标<del>内</del>外 <code>page_action</code> <strong>新版的已更改显示在外围 <a href="https://developer.chrome.com/extensions/pageAction">PageAction API</a></strong></li><li>多功能框 <code>omnibox</code> <strong>对地址框进行监听</strong></li><li>overrides <strong>如, <code>管理书签</code>&#x2F;<code>历史记录</code>&#x2F;<code>新标签页</code>等 (一个扩展只能替换一个页面)</strong></li><li>桌面提醒 <code>webkitNotifications.createNotification</code></li></ul><h1 id="权限"><a href="#权限" class="headerlink" title="权限"></a>权限</h1><blockquote><p>相当一部分Chrome API 使用需要在<code>Manifest</code>申明权限</p></blockquote><h1 id="页面间通信"><a href="#页面间通信" class="headerlink" title="页面间通信"></a>页面间通信</h1><ul><li>popup 与 background 通信</li></ul><ol><li>使用上面提到的<code>共通</code>的特性。</li><li>使用 <code>chrome.extension.onMessage.addListener</code>进行通信监听 与 使用<code>chrome.extension.sendMessage</code>进行触发</li></ol><ul><li>option 与 (popup 或者 background) 通信</li></ul><ol><li>使用 <code>chrome.extension.onMessage.addListener</code>进行通信监听 与 使用<code>chrome.extension.sendMessage</code>进行触发</li></ol><ul><li>(popup 或者 background) 与 option 通信</li></ul><ol><li>使用 <code>chrome.extension.onMessage.addListener</code>进行通信监听, 触发方式比较麻烦, 查看以下例子:<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">chrome.<span class="property">tabs</span>.<span class="title function_">query</span>(&#123;<span class="attr">active</span>: <span class="literal">true</span>, <span class="attr">currentWindow</span>: <span class="literal">true</span>&#125;, <span class="keyword">function</span> (<span class="params">tabs</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!!tabs</span><br><span class="line">                &amp;&amp; tabs.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                chrome.<span class="property">tabs</span>.<span class="title function_">sendMessage</span>(tabs[<span class="number">0</span>].<span class="property">id</span>, &#123;</span><br><span class="line">                  <span class="comment">//message..</span></span><br><span class="line">                  &#125;, callback);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br></pre></td></tr></table></figure></li></ol><h1 id="i18"><a href="#i18" class="headerlink" title="i18"></a>i18</h1><ul><li><code>CSS</code> __MSG_@@key</li><li><code>JS</code> chrome.i18n.getMessage(‘key’);</li></ul><h1 id="关于打包-amp-发布"><a href="#关于打包-amp-发布" class="headerlink" title="关于打包 &amp; 发布"></a>关于打包 &amp; 发布</h1><ol><li><code>扩展程序</code>中进行打包，生成<code>.crx</code>(扩展程序) &amp; <code>.pem</code>(秘钥<strong>重要</strong>)</li><li>前往<a href="https://chrome.google.com/webstore/developer/dashboard/">Chrome 开发者中心</a> 认证<code>需支付5美元用于认证</code></li><li>把<code>.pem</code>更名为<code>key.pem</code>并放入<code>源码文件夹</code>中，打包为<code>.zip</code>文件</li><li>上传 并编辑 (<strong>必填 (扩展描述、ICON(128x128)、扩展截图(1280x800 or 640x400)、类别、语言)</strong>)</li></ol><hr><blockquote><p>如有遗漏或错误欢迎补充..</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;身为Chrome重度患者，生活和工作处处不离，这篇并不是入门教程，而是开发中的一些小Tip的记录.&lt;/p&gt;</summary>
    
    
    
    <category term="IDE" scheme="https://hocg.in/categories/IDE/"/>
    
    
    <category term="HTML5" scheme="https://hocg.in/tags/HTML5/"/>
    
    <category term="Chrome" scheme="https://hocg.in/tags/Chrome/"/>
    
  </entry>
  
  <entry>
    <title>关于log4j报错</title>
    <link href="https://hocg.in/2017/01/16/%E5%85%B3%E4%BA%8Elog4j%E6%8A%A5%E9%94%99/"/>
    <id>https://hocg.in/2017/01/16/%E5%85%B3%E4%BA%8Elog4j%E6%8A%A5%E9%94%99/</id>
    <published>2017-01-16T08:09:27.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>  Java开发中经常遇到日志<code>冲突</code>或者<code>异常</code>, 彻底的来此追根究底.</p><span id="more"></span><h2 id="日志历史"><a href="#日志历史" class="headerlink" title="日志历史"></a>日志历史</h2><ul><li>log4j</li><li>JCL + log4j</li><li>SLF4J <code>slf4j-XXX-version.jar</code> [XXX指代log4j12, jdk14, jcl, nop 等]</li><li>slf4j-api<blockquote><p>v1 <code>log4j</code> 早期直接实现日志打印<br>v2 <code>JCL + log4j</code> 动态绑定, 面向<code>JCL 接口</code>实现的<code>log4j</code><br>v3 <code>slf4j-api</code> 提供 <code>SLF4J接口</code> <strong>面向对象编程</strong><br><code>slf4j-XXX-version.jar</code> 对接口和指定<code>XXX</code>种类日志的具体实现</p></blockquote></li></ul><h2 id="slf4j-举例jar"><a href="#slf4j-举例jar" class="headerlink" title="slf4j 举例jar"></a>slf4j 举例jar</h2><ul><li>log4j-over-slf4j.jar 把<code>log4j</code>转为<code>slf4j</code></li><li>slf4j-log4j12.jar 以slf4j标准实现的log4j12</li><li><code>XXX-over-slf4j.jar</code> 把日志重定向到<code>slf4j</code> eg.<code>jcl-over-slf4j.jar</code></li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>即.<br>Component<br>   |<br>   | log to Apache Commons Logging<br>   V<br> jcl-over-slf4j.jar — (redirect) —&gt; SLF4j —&gt; slf4j-log4j12-version.jar —&gt; log4j.jar —&gt; 输出日志<br><strong>解释:</strong><br>JCL实现的重定向为SLF4J日志形式, 然后SLF4J转为Log4j12输出!</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;  Java开发中经常遇到日志&lt;code&gt;冲突&lt;/code&gt;或者&lt;code&gt;异常&lt;/code&gt;, 彻底的来此追根究底.&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="JAVA" scheme="https://hocg.in/tags/JAVA/"/>
    
  </entry>
  
  <entry>
    <title>Redis 相关</title>
    <link href="https://hocg.in/2016/10/20/Redis-%E7%9B%B8%E5%85%B3/"/>
    <id>https://hocg.in/2016/10/20/Redis-%E7%9B%B8%E5%85%B3/</id>
    <published>2016-10-20T09:11:48.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>  Redis 的部署和部位设计的实践, 还有常见问题的梳理! 💪</p><span id="more"></span><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p><a href="http://redis.io/download">官网</a></p><h2 id="详情"><a href="#详情" class="headerlink" title="详情"></a>详情</h2><h3 id="默认项"><a href="#默认项" class="headerlink" title="默认项"></a>默认项</h3><ul><li>端口 <code>6379</code></li></ul><h3 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h3><p>redis-3.2.4&#x2F;<br>|– redis.conf <code>redis配置文件</code><br><code>-- src</code>编译后目录<code>    |-- redis-server</code>启动bit文件<code>     </code>– redis-cli <code>终端bit文件</code></p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><blockquote><p>以下操作均在<code>/opt</code></p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载</span></span><br><span class="line">wget http://download.redis.io/releases/redis-3.2.4.tar.gz</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">解压</span></span><br><span class="line">tar -zxvf redis-3.2.4.tar.gz</span><br><span class="line">cd redis-3.2.4</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">编译， 生成`src`目录</span></span><br><span class="line">make</span><br></pre></td></tr></table></figure><h2 id="指令"><a href="#指令" class="headerlink" title="指令"></a>指令</h2><blockquote><p>以下操作均在<code>/opt</code></p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">默认配置运行</span></span><br><span class="line">./redis-3.2.4/src/redis-server</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定配置文件运行</span></span><br><span class="line">./redis-3.2.4/src/redis-server [config file]</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="疑问？"><a href="#疑问？" class="headerlink" title="疑问？"></a>疑问？</h2><ul><li><p>如何使<code>redis</code>后台运行?</p><blockquote><p>更改配置文件, 找到<code>daemonize</code>字段,更改<code>no</code>为<code>yes</code>, 重启<code>redis</code> <strong>切记！要指定配置文件</strong></p></blockquote></li><li><p>如何更改<code>redis</code>默认<code>6379</code>端口?</p><blockquote><p>更改配置文件, 找到<code>port</code>字段,更改为指定端口, 重启<code>redis</code> <strong>切记！要指定配置文件</strong></p></blockquote></li><li><p>如何设置<code>redis</code>的验证密码?</p><blockquote><p>更改配置文件, 找到<code>requirepass</code>字段, 设置相应的验证密码, 重启<code>redis</code> <strong>切记！要指定配置文件</strong><br>由于增加了验证密码，因此客户端连接命令为<code>redis-cli –a [upassword]</code></p></blockquote></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;  Redis 的部署和部位设计的实践, 还有常见问题的梳理! 💪&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Redis" scheme="https://hocg.in/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>Ubuntu 下的 Oh My ZSH!</title>
    <link href="https://hocg.in/2016/09/30/Ubuntu%E4%B8%8B%E7%9A%84OhMyZSH!/"/>
    <id>https://hocg.in/2016/09/30/Ubuntu%E4%B8%8B%E7%9A%84OhMyZSH!/</id>
    <published>2016-09-30T16:18:09.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>号称终极shell :)</p><span id="more"></span><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><h3 id="什么是zsh？"><a href="#什么是zsh？" class="headerlink" title="什么是zsh？"></a>什么是zsh？</h3><p>shell的一种,<code>cat /etc/shells</code>查看当前系统支持的shell</p><h3 id="相关Link"><a href="#相关Link" class="headerlink" title="相关Link"></a>相关Link</h3><p><a href="http://www.zhihu.com/question/21418449">为什么说 zsh 是 shell 中的极品？</a></p><h3 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h3><p>OS: Ubuntu 16.04 x86_64</p><h2 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h2><ul><li><p>~&#x2F;.zshrc <code>文件zsh配置文件</code></p><blockquote><ol><li>可用来更改<code>Theme</code></li><li>加载<code>Plugin</code></li></ol></blockquote></li><li><p>~&#x2F;.oh-my-zsh <code>oh-my-zsh目录</code></p></li></ul><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装zsh</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt-get install zsh</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装oh-my-zsh</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt-get install wget git</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">wget --no-check-certificate https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">替换zsh为系统shell</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">chsh -s /bin/zsh</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">退出&amp;重新登入</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">exit</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看是否成功</span></span><br></pre></td></tr></table></figure><h2 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h2><p><a href="">zsh.config</a></p><p><strong>注意</strong></p><ul><li>需更改<code>.oh-my-zsh</code>的目录</li></ul><h2 id="插件介绍"><a href="#插件介绍" class="headerlink" title="插件介绍"></a>插件介绍</h2><ul><li><code>git</code>;处于git项目下出现提示</li><li><code>autojump</code>; 目录自动提示, 需要[Linux 额外安装](git clone git:&#x2F;&#x2F;github.com&#x2F;joelthelion&#x2F;autojump.git)<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">~/.bashrc 追加</span></span><br><span class="line">[[ -s ~/.autojump/etc/profile.d/autojump.sh ]] &amp;&amp; . ~/.autojump/etc/profile.d/autojump.sh</span><br></pre></td></tr></table></figure></li><li><code>git</code>;处于git项目下出现提示</li><li><code>zsh-syntax-highlighting</code>;高亮可用命令<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git <span class="built_in">clone</span> git://github.com/jimmijj/zsh-syntax-highlighting ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting</span></span><br><span class="line">plugins=(zsh-syntax-highlighting)</span><br></pre></td></tr></table></figure></li><li><code>colored-man-pages</code>; 帮助文档高亮</li><li><code>colorize</code>;更多代码高亮</li><li><code>copydir</code>; 整个目录拷贝</li><li><code>command-not-found</code>;命令行智能提示</li><li><code>history</code>;查看输入历史</li><li><code>z</code>; <code>autojump</code>同类</li></ul><h2 id="主题"><a href="#主题" class="headerlink" title="主题"></a>主题</h2><ul><li>ys</li></ul><h2 id="小技巧"><a href="#小技巧" class="headerlink" title="小技巧"></a>小技巧</h2><ul><li>转换路径时可以省去cd命令，直接输入路径即可</li><li><code>d</code> 可以查看访问过的路径，然后输入数字就可以直接切换</li><li>输入不完整的路径&#x2F;文件&#x2F;命令，按下tab键可以出现提示，再按tab则可以实现路径补全</li><li>普通命令使用两次tab可进入选择模式， ctrl+f&#x2F;b&#x2F;n&#x2F;p 可以向前后左右切换</li><li>kill + tab <code>强强强</code></li><li>alias -s xx&#x3D;’xxx’ 快捷配置</li></ul><h2 id="相关设置"><a href="#相关设置" class="headerlink" title="相关设置"></a>相关设置</h2><blockquote><p>cat 代码高亮</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pip install Pygments</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">增加以下<span class="built_in">alias</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">alias</span> ccat=<span class="string">&#x27;pygmentize -g&#x27;</span></span></span><br></pre></td></tr></table></figure><h2 id="后续"><a href="#后续" class="headerlink" title="后续"></a>后续</h2><p><a href="https://github.com/hocgin/Gather/tree/master/oh-my-zsh">Oh My ZSH!</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;号称终极shell :)&lt;/p&gt;</summary>
    
    
    
    <category term="IDE" scheme="https://hocg.in/categories/IDE/"/>
    
    
    <category term="Ubuntu" scheme="https://hocg.in/tags/Ubuntu/"/>
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Oh My ZSH" scheme="https://hocg.in/tags/Oh-My-ZSH/"/>
    
  </entry>
  
  <entry>
    <title>Glup 自动化构建工具</title>
    <link href="https://hocg.in/2016/09/20/Glup-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/"/>
    <id>https://hocg.in/2016/09/20/Glup-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/</id>
    <published>2016-09-20T08:10:29.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>Gulp.js 是一个自动化构建工具 😜</p><span id="more"></span><h2 id="来源"><a href="#来源" class="headerlink" title="来源"></a>来源</h2><p><a href="https://github.com/hocgin/Gulp-Scaffold">Glup 整合</a></p><h2 id="Glup"><a href="#Glup" class="headerlink" title="Glup"></a>Glup</h2><blockquote><p>Glup用自动化构建工具增强你的工作流程！</p></blockquote><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">npm install gulp -g</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">npm install gulp --save-dev</span></span><br></pre></td></tr></table></figure><h2 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h2><ul><li>编译Sass (gulp-ruby-sass)</li><li>Autoprefixer (gulp-autoprefixer)</li><li>缩小化(minify)CSS (gulp-minify-css)</li><li>JSHint (gulp-jshint)</li><li>拼接 (gulp-concat)</li><li>丑化(Uglify) (gulp-uglify)</li><li>图片压缩 (gulp-imagemin)</li><li>即时重整(LiveReload) (gulp-livereload)</li><li>清理档案 (gulp-clean)</li><li>图片快取，只有更改过得图片会进行压缩 (gulp-cache)</li><li>更动通知 (gulp-notify)<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">npm install gulp-ruby-sass gulp-autoprefixer gulp-minify-css gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-clean gulp-notify gulp-rename gulp-livereload gulp-cache --save-dev</span></span><br></pre></td></tr></table></figure></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;Gulp.js 是一个自动化构建工具 😜&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="NodeJS" scheme="https://hocg.in/tags/NodeJS/"/>
    
    <category term="Ubuntu" scheme="https://hocg.in/tags/Ubuntu/"/>
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
  </entry>
  
  <entry>
    <title>Ngrok使用指南</title>
    <link href="https://hocg.in/2016/08/31/Ngrok%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/"/>
    <id>https://hocg.in/2016/08/31/Ngrok%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/</id>
    <published>2016-08-31T07:15:24.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>Ngrok 是一款内部端口转发，对于微信类似的开发很有用的😆<br>可参照墙内(花生壳 or nat123)</p><span id="more"></span><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p><strong>编译环境:</strong><br><a href="https://storage.googleapis.com/golang/go1.4.1.linux-amd64.tar.gz">Go 1.4.1 强烈建议</a><br>根域名: <code>web.hocg.in</code>,即生成的域名为<code>*.web.hocg.in</code><br>文件结构:<br>ngrok<br>  ├── bin<br>  │   └── ngrok.cfg<br>  ├── client.sh<br>  ├── code.sh<br>  └── server.sh<br><strong>部署环境:</strong><br>服务器OS: Ubuntu-15<br>客户端OS: Ubuntu-16</p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><h3 id="环境依赖及源码下载"><a href="#环境依赖及源码下载" class="headerlink" title="环境依赖及源码下载"></a>环境依赖及源码下载</h3><blockquote><p>以下命令根目录统一在<code>/opt</code></p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">环境依赖</span></span><br><span class="line">sudo apt-get install build-essential golang mercurial git</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">获取 ngrok 源码</span></span><br><span class="line">git clone https://github.com/tutumcloud/ngrok.git ngrok</span><br><span class="line">cd ngrok</span><br></pre></td></tr></table></figure><h3 id="生成证书-amp-amp-编译"><a href="#生成证书-amp-amp-编译" class="headerlink" title="生成证书 &amp;&amp; 编译"></a>生成证书 &amp;&amp; 编译</h3><blockquote><p>以下命令根目录统一在<code>/opt/ngrok</code></p></blockquote><p><code>code.sh</code>文件</p><blockquote><p>生成证书 &amp;&amp; 编译服务端<br><code>DOMAIN</code> 为配置的<code>根域名</code>, 用于签名.</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line">echo &quot;开始清除..&quot;</span><br><span class="line">rm -rf assets/client/tls/ngrokroot.crt</span><br><span class="line">rm -rf assets/server/tls/snakeoil.crt</span><br><span class="line">rm -rf assets/server/tls/snakeoil.key</span><br><span class="line">rm -rf device.*</span><br><span class="line">rm -rf rootCA.*</span><br><span class="line">DOMAIN=web.hocg.in</span><br><span class="line">echo &quot;设置域名为[*.$DOMAIN]&quot;</span><br><span class="line">echo &quot;开始生成秘钥..&quot;</span><br><span class="line">openssl genrsa -out rootCA.key 2048</span><br><span class="line">openssl req -x509 -new -nodes -key rootCA.key -subj &quot;/CN=$DOMAIN&quot; -days 5000 -out rootCA.pem</span><br><span class="line">openssl genrsa -out device.key 2048</span><br><span class="line">openssl req -new -key device.key -subj &quot;/CN=$DOMAIN&quot; -out device.csr</span><br><span class="line">openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000</span><br><span class="line"></span><br><span class="line">echo &quot;开始迁移秘钥..&quot;</span><br><span class="line">cp -rf rootCA.pem assets/client/tls/ngrokroot.crt</span><br><span class="line">cp -rf device.crt assets/server/tls/snakeoil.crt</span><br><span class="line">cp -rf device.key assets/server/tls/snakeoil.key</span><br><span class="line"></span><br><span class="line">echo &quot;开始编译..&quot;</span><br><span class="line">make release-server</span><br></pre></td></tr></table></figure><p><strong>客户端</strong></p><blockquote><p>前置条件: Go需先增加对这些平台交叉编译的支持</p></blockquote><ul><li><p>Windows<br>go的<code>src</code>目录  </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GOOS=windows GOARCH=amd64 ./make.bash</span><br></pre></td></tr></table></figure><p><code>nginx</code>目录,编译</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GOOS=windows GOARCH=amd64 make release-client</span><br></pre></td></tr></table></figure></li><li><p>macOS<br>go的<code>src</code>目录  </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GOOS=darwin GOARCH=amd64 ./make.bash</span><br></pre></td></tr></table></figure><p><code>nginx</code>目录,编译</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GOOS=darwin GOARCH=amd64 make release-client</span><br></pre></td></tr></table></figure></li><li><p>Linux<br><code>nginx</code>目录,编译</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make release-client</span><br></pre></td></tr></table></figure></li></ul><h3 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h3><p><code>ngrok.cfg</code>文件</p><blockquote><p><code>server_addr</code> 为配置的<code>根域名</code>， <code>4443</code>为默认端口</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">server_addr: web.hocg.in:4443</span><br><span class="line">trust_host_root_certs: false</span><br></pre></td></tr></table></figure><h3 id="运行文件"><a href="#运行文件" class="headerlink" title="运行文件"></a>运行文件</h3><p><code>server.sh</code>文件</p><blockquote><p>服务器运行<br><code>DOMAIN</code> 为配置的<code>根域名</code>.<br>注释的那一句用于后台运行</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="variable">$1</span> HTTP</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="variable">$2</span> HTTPS</span></span><br><span class="line">killall ngrokd</span><br><span class="line">DOMAIN=web.hocg.in</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">nohup</span> ./bin/ngrokd -domain=<span class="string">&quot;<span class="variable">$DOMAIN</span>&quot;</span> -httpAddr=<span class="string">&quot;:<span class="variable">$1</span>&quot;</span> -httpsAddr=<span class="string">&quot;:<span class="variable">$2</span>&quot;</span> &gt;/tmp/ngrok.log 2&gt;&amp;1 &amp;</span></span><br><span class="line">./bin/ngrokd -domain=&quot;$DOMAIN&quot; -httpAddr=&quot;:$1&quot; -httpsAddr=&quot;:$2&quot;</span><br></pre></td></tr></table></figure><p><code>client.sh</code>文件</p><blockquote><p>客户端运行, default:linux<br>具体环境修改具体内容</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="variable">$1</span> Port</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="variable">$2</span> domain</span></span><br><span class="line">./bin/ngrok -subdomain $2 -proto=http -config=./bin/ngrok.cfg $1</span><br></pre></td></tr></table></figure><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><blockquote><p>若需变更域名, 需修改<code>code.sh</code>的<code>DOMAIN</code>、<code>server.sh</code>的<code>DOMAIN</code>与<code>./bin/ngrok.cfg</code>的<code>server_addr</code></p></blockquote><h3 id="编译"><a href="#编译" class="headerlink" title="编译"></a>编译</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh code.sh</span><br></pre></td></tr></table></figure><blockquote><p><strong>成功</strong> 检查<code>ngrok/bin</code>文件夹是否存在<code>ngrok</code> and <code>ngrokd</code></p></blockquote><h3 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh server.sh 8888 9999</span><br></pre></td></tr></table></figure><h3 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh client.sh 8080 dm</span><br></pre></td></tr></table></figure><h3 id="检验"><a href="#检验" class="headerlink" title="检验"></a>检验</h3><p>访问:<code>http://dm.web.hocg.in:8888</code><br><img src="https://hocg.in/i/Ngrok%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97.png" alt="image"></p><h2 id="重要"><a href="#重要" class="headerlink" title="重要"></a>重要</h2><h3 id="关于域名解析"><a href="#关于域名解析" class="headerlink" title="关于域名解析"></a>关于域名解析</h3><p>eg. <code>*.web.hocg.in</code><br>路径解析需配置<code>*.web</code> and <code>web</code> 两个A记录</p><h3 id="关于签名"><a href="#关于签名" class="headerlink" title="关于签名"></a>关于签名</h3><p>最好在同一环境进行<code>服务端</code>和<code>客户端</code>的编译</p><h2 id="小技巧"><a href="#小技巧" class="headerlink" title="小技巧"></a>小技巧</h2><ul><li>如何让服务端的<code>ngrok</code>后台运行<blockquote><p>正常的<code>nohup</code>或<code>&amp;</code>是无法使<code>ngrok</code>后台运行的<br>需使用<code>screen</code></p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">\# apt-get install screen</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">使用</span></span><br><span class="line">screen -S [命名] [需放入后台的命令]</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">使用 ctrl+A+D 让其运行在后台</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看screen 后台进程</span></span><br><span class="line">screen -ls</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重新连接后台进程</span></span><br><span class="line">screen -r [进程id]</span><br><span class="line"></span><br></pre></td></tr></table></figure></li></ul><h2 id="可能遇到的异常"><a href="#可能遇到的异常" class="headerlink" title="可能遇到的异常"></a>可能遇到的异常</h2><ul><li><p>Go-1.2.1语言版本不支持<code>go version</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">github.com/gorilla/websocket</span></span><br><span class="line">src/github.com/gorilla/websocket/client.go:361: unknown tls.Config field &#x27;GetCertificate&#x27; in struct literal</span><br><span class="line">src/github.com/gorilla/websocket/client.go:370: unknown tls.Config field &#x27;ClientSessionCache&#x27; in struct literal</span><br><span class="line">src/github.com/gorilla/websocket/client.go:373: unknown tls.Config field &#x27;CurvePreferences&#x27; in struct literal</span><br><span class="line">make: *** [client] Error 2</span><br></pre></td></tr></table></figure><p><a href="https://golang.org/doc/install?download=go1.7.linux-amd64.tar.gz">官方Go-64的安装</a></p></li><li><p>Go编译器找不到<code>go-bindata</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">GOOS=&quot;&quot; GOARCH=&quot;&quot; go get github.com/jteeuwen/go-bindata/go-bindata</span><br><span class="line">/bin/sh: 1: go: not found</span><br><span class="line">make: *** [bin/go-bindata] Error 127</span><br></pre></td></tr></table></figure></li></ul><ol><li><p>请注意配置好<code>GOROOT</code>和<code>GOPATH</code></p><blockquote><p><code>GOROOT</code>为安装GO的目录<br><code>GOPATH</code>自定义一个GO插件下载目录</p></blockquote></li><li><p>执行以下shell下载插件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">go get -u github.com/jteeuwen/go-bindata/...</span><br></pre></td></tr></table></figure><p>END:)</p></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;Ngrok 是一款内部端口转发，对于微信类似的开发很有用的😆&lt;br&gt;可参照墙内(花生壳 or nat123)&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="Ngrok" scheme="https://hocg.in/tags/Ngrok/"/>
    
    <category term="Tip" scheme="https://hocg.in/tags/Tip/"/>
    
  </entry>
  
  <entry>
    <title>Nexus 入门</title>
    <link href="https://hocg.in/2016/08/24/Nexus%E5%85%A5%E9%97%A8/"/>
    <id>https://hocg.in/2016/08/24/Nexus%E5%85%A5%E9%97%A8/</id>
    <published>2016-08-24T19:03:01.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>适合<code>nexus</code>入门，不是手机，不是手机，不是手机　．．ｏ（╯□╰）ｏ</p><span id="more"></span><h2 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h2><ul><li>Ubuntu-14.04.1</li><li>jdk1.8.0_102</li><li><a href="https://sonatype-download.global.ssl.fastly.net/nexus/oss/nexus-2.12.0-01-bundle.tar.gz">nexus-2.12.0-01</a>|<a href="http://www.sonatype.org/nexus/">官网</a></li><li>域名:<code>nexus.hocg.in</code></li></ul><h2 id="前置条件"><a href="#前置条件" class="headerlink" title="前置条件"></a>前置条件</h2><ul><li>安装完jdk并配置好环境变量 <code>eg: java查看是否成功</code></li></ul><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p><strong>温馨提示:</strong> 以下操作都是在<code>/opt</code>目录下</p><h3 id="下载-amp-解压"><a href="#下载-amp-解压" class="headerlink" title="下载&amp;解压"></a>下载&amp;解压</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载</span></span><br><span class="line">wget https://sonatype-download.global.ssl.fastly.net/nexus/oss/nexus-2.12.0-01-bundle.tar.gz</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">解压</span></span><br><span class="line">tar -zxvf nexus-2.12.0-01-bundle.tar.gz</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清理</span></span><br><span class="line">rm -rf *.gz</span><br></pre></td></tr></table></figure><h3 id="文件-x2F-目录详解"><a href="#文件-x2F-目录详解" class="headerlink" title="文件&#x2F;目录详解"></a>文件&#x2F;目录详解</h3><ul><li><code>nexus-2.12.0-01</code> 程序目录</li><li><code>sonatype-work</code> 仓库目录(内包含仓库配置及jar包仓库)</li></ul><h3 id="基本操作"><a href="#基本操作" class="headerlink" title="基本操作"></a>基本操作</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./nexus-2.12.0-01/bin/nexus &#123; console | start | stop | restart | status | dump &#125;</span><br></pre></td></tr></table></figure><p><code>访问 http://nexus.hocg.in:8081/nexus</code></p><blockquote><p>默认账号:admin 默认密码: admin123</p></blockquote><h2 id="如何使用"><a href="#如何使用" class="headerlink" title="如何使用"></a>如何使用</h2><h3 id="Maven-中配置仓库"><a href="#Maven-中配置仓库" class="headerlink" title="Maven 中配置仓库"></a>Maven 中配置仓库</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">repositories</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">repository</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">id</span>&gt;</span>Nexus<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">name</span>&gt;</span>Nexus<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://nexus.hocg.in:8081/nexus/content/groups/public/<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">repository</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">repositories</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><h3 id="如何修改默认8081端口"><a href="#如何修改默认8081端口" class="headerlink" title="如何修改默认8081端口"></a>如何修改默认<code>8081</code>端口</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">vim /opt/nexus-2.12.0-01/conf/nexus.properties</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改application-port=8081项</span></span><br></pre></td></tr></table></figure><h3 id="如何创建用户"><a href="#如何创建用户" class="headerlink" title="如何创建用户"></a>如何创建用户</h3><p>登陆系统后，左侧<code>Security &gt; Users</code>中创建</p><h3 id="如何使用构建账号"><a href="#如何使用构建账号" class="headerlink" title="如何使用构建账号"></a>如何使用<code>构建账号</code></h3><p>修改<code>Settings.xml</code>文件 (<strong>Maven</strong>)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;servers&gt;</span><br><span class="line">&lt;server&gt;</span><br><span class="line">&lt;id&gt;nexus.hocg.in&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">&lt;/servers&gt;</span><br></pre></td></tr></table></figure><h3 id="如何修改用户密码"><a href="#如何修改用户密码" class="headerlink" title="如何修改用户密码"></a>如何修改用户密码</h3><p>登陆系统后，顶部<code>点击用户名 &gt; Profile</code>中修改</p><h3 id="如何建立与中央仓库的索引"><a href="#如何建立与中央仓库的索引" class="headerlink" title="如何建立与中央仓库的索引"></a>如何建立与中央仓库的索引</h3><p><img src="https://hocg.in/i/%E5%A6%82%E4%BD%95%E5%BB%BA%E7%AB%8B%E4%B8%8E%E4%B8%AD%E5%A4%AE%E4%BB%93%E5%BA%93%E7%9A%84%E7%B4%A2%E5%BC%95.png" alt="image"></p><blockquote><p><strong>Note:</strong> Nexus会自动建立任务计划,一般远程仓库都比较大，构建会比较多，因此索引文件会很大，请确保磁盘大小充足.</p></blockquote><h2 id="可能出现的报错"><a href="#可能出现的报错" class="headerlink" title="可能出现的报错"></a>可能出现的报错</h2><ul><li><strong>1</strong> WARNING - NOT RECOMMENDED TO RUN AS ROOT , 原因是提醒你是否确认用<code>root</code>用户运行<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">\# ./nexus-2.12.0-01/bin/nexus restart</span><br><span class="line">****************************************</span><br><span class="line">WARNING - NOT RECOMMENDED TO RUN AS ROOT</span><br><span class="line">****************************************</span><br><span class="line">Stopping Nexus OSS...</span><br><span class="line">Nexus OSS was not running.</span><br><span class="line">Starting Nexus OSS...</span><br><span class="line">Started Nexus OSS.</span><br></pre></td></tr></table></figure>解决:<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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">vim ./nexus-2.12.0-01/bin/nexus</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">加入系统变量</span></span><br><span class="line">vi /etc/profile</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">加入<span class="built_in">export</span> RUN_AS_USER=root</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改</span></span><br><span class="line">RUN_AS_USER=root</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动</span></span><br><span class="line">./nexus-2.12.0-01/bin/nexus start</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看是否启动成功</span></span><br><span class="line">./nexus-2.12.0-01/bin/nexus status</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">稍等几分钟再访问</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;适合&lt;code&gt;nexus&lt;/code&gt;入门，不是手机，不是手机，不是手机　．．ｏ（╯□╰）ｏ&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Nexus" scheme="https://hocg.in/tags/Nexus/"/>
    
  </entry>
  
  <entry>
    <title>Android L 及以上版本Rom包中提取apk</title>
    <link href="https://hocg.in/2016/08/07/Android-L-%E5%8F%8A%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%ACRom%E5%8C%85%E4%B8%AD%E6%8F%90%E5%8F%96apk/"/>
    <id>https://hocg.in/2016/08/07/Android-L-%E5%8F%8A%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%ACRom%E5%8C%85%E4%B8%AD%E6%8F%90%E5%8F%96apk/</id>
    <published>2016-08-07T19:19:29.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>提取想要的apk， 例如CM ROM包中的含天气的时钟不错！</p><span id="more"></span><h2 id="以往版本"><a href="#以往版本" class="headerlink" title="以往版本"></a>以往版本</h2><blockquote><p>Android Rom包只需解压后，取出system包即可取出内部apk</p></blockquote><h2 id="Now"><a href="#Now" class="headerlink" title="Now"></a>Now</h2><blockquote><p>解压后可以发现，文件发生了改变并且<code>system.new.dat</code>此文件是不支持直接解压的。</p></blockquote><h3 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h3><p>系统: win10<br>工具: <a href="http://cdn.hocgin.top/Extractor%20and%20Repacker%204.0.rar">下载</a></p><blockquote><p>环境自备</p></blockquote><h3 id="操作步骤"><a href="#操作步骤" class="headerlink" title="操作步骤"></a>操作步骤</h3><ol><li>普通方式解压ROM</li><li>运行下载工具中.bat文件<code>Extractor.bat</code></li><li>根据提示选择<code>1</code>，并复制<code>system.new.dat</code>, <code>system.transfer.list</code>，<code>file_contexts</code>三个文件到bat文件所在目录</li><li>按任意键继续</li><li>完成后可以得到一个<code>system</code>文件夹</li><li>嘿嘿嘿..</li></ol><h3 id="问题"><a href="#问题" class="headerlink" title="问题!"></a>问题!</h3><ol><li>有可能在你安装apk的时候出现<code>应用未安装</code>的情况</li></ol><ul><li>可以尝试重新对apk进行签名</li><li>检查是否已经安装过该apk</li></ul><p>End</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;提取想要的apk， 例如CM ROM包中的含天气的时钟不错！&lt;/p&gt;</summary>
    
    
    
    <category term="Android" scheme="https://hocg.in/categories/Android/"/>
    
    
    <category term="Android" scheme="https://hocg.in/tags/Android/"/>
    
    <category term="手机" scheme="https://hocg.in/tags/%E6%89%8B%E6%9C%BA/"/>
    
  </entry>
  
  <entry>
    <title>模块设计之对接同步订单模块</title>
    <link href="https://hocg.in/2016/08/02/%E6%A8%A1%E5%9D%97%E8%AE%BE%E8%AE%A1%E4%B9%8B%E5%AF%B9%E6%8E%A5%E5%90%8C%E6%AD%A5%E8%AE%A2%E5%8D%95%E6%A8%A1%E5%9D%97/"/>
    <id>https://hocg.in/2016/08/02/%E6%A8%A1%E5%9D%97%E8%AE%BE%E8%AE%A1%E4%B9%8B%E5%AF%B9%E6%8E%A5%E5%90%8C%E6%AD%A5%E8%AE%A2%E5%8D%95%E6%A8%A1%E5%9D%97/</id>
    <published>2016-08-02T10:47:06.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>实习期间设计的对接同步订单的某块, 缅怀..<br>设计日期(2016.6)</p><span id="more"></span><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote><p><strong>#对接同步订单模块#</strong> 该部分是我入职后自主设计的一个模块，因为初期预计对接5家平台的订单，并考虑到后期可能对接更多平台和平台订单数量等，所以扩展性和性能方面是很值得深思的问题。</p></blockquote><h2 id="开发周期-20day"><a href="#开发周期-20day" class="headerlink" title="开发周期 (20day)"></a>开发周期 (20day)</h2><blockquote><p>前期需求的多次变更，大大的浪费了开发周期.</p></blockquote><ul><li>库表设计</li><li>接口整理和整合设计(主要是对接平台的接口整合等)</li><li>代码编写</li></ul><h2 id="业务流程图"><a href="#业务流程图" class="headerlink" title="业务流程图"></a>业务流程图</h2><h3 id="表"><a href="#表" class="headerlink" title="表"></a>表</h3><ul><li>商品表,<strong>存储商品信息, 主要配合方案匹配</strong></li><li>授权表,<strong>存储用户授权信息，主要用于token管理</strong></li><li>平台配置表,<strong>存储平台key信息</strong></li><li>方案表,<strong>已存在，存储方案信息</strong></li></ul><h3 id="v1版"><a href="#v1版" class="headerlink" title="v1版"></a>v1版</h3><h4 id="思路图"><a href="#思路图" class="headerlink" title="思路图"></a>思路图</h4><p><img src="http://cdn.hocgin.top/%E6%80%BB%E4%BD%93%E6%80%9D%E8%B7%AF-v1-op.png" alt="总体思路-v1-op.png"></p><h4 id="业务图"><a href="#业务图" class="headerlink" title="业务图"></a>业务图</h4><p><img src="http://cdn.hocgin.top/%E4%B8%9A%E5%8A%A1-v1-op.png" alt="总体思路-v1-now.png"></p><p>原先，该部分设计是不考虑对订单数据进行缓存处理的，但后期需求多次变更被迫进行数据缓存，因此再原先的基础上建立了线程池并对同步订单部分进行异步线程处理，因此增加了一张订单缓存表和事件队列表。</p><hr><h3 id="v2版"><a href="#v2版" class="headerlink" title="v2版"></a>v2版</h3><h4 id="思路图-1"><a href="#思路图-1" class="headerlink" title="思路图"></a>思路图</h4><p><img src="http://cdn.hocgin.top/%E6%80%BB%E4%BD%93%E6%80%9D%E8%B7%AF-v2-now.png" alt="总体思路-v2-op.png"></p><h4 id="业务图-1"><a href="#业务图-1" class="headerlink" title="业务图"></a>业务图</h4><p><img src="http://cdn.hocgin.top/%E4%B8%9A%E5%8A%A1-v2-now.png" alt="总体思路-v2-now.png"></p><blockquote><p>后面又对缓存表进行了数据去重防止表数据爆炸性增长。</p></blockquote><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li>把公共抽离出来，中间新增转化层可以很好的解决代码复用的问题.</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;实习期间设计的对接同步订单的某块, 缅怀..&lt;br&gt;设计日期(2016.6)&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="设计思路" scheme="https://hocg.in/tags/%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF/"/>
    
  </entry>
  
  <entry>
    <title>模块设计之消息模块</title>
    <link href="https://hocg.in/2016/07/30/%E6%A8%A1%E5%9D%97%E8%AE%BE%E8%AE%A1%E4%B9%8B%E6%B6%88%E6%81%AF%E6%A8%A1%E5%9D%97/"/>
    <id>https://hocg.in/2016/07/30/%E6%A8%A1%E5%9D%97%E8%AE%BE%E8%AE%A1%E4%B9%8B%E6%B6%88%E6%81%AF%E6%A8%A1%E5%9D%97/</id>
    <published>2016-07-30T19:25:56.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>  新手上路，小心撞车..</p><span id="more"></span><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote><p><strong>#消息模块#</strong> 这是我刚入职时所接触的第一个模块，也算是比较大的模块了。这个模块的业务是负责整个项目所有的消息出入口，包含短信发送，APP推送，邮件发送以及前后端人员站内消息。当时设计的时候需求架构比较简单而且时间紧迫(π__π)，没有从根本理清业务和功能后期存在的扩展。因此，这篇文章是记录当时架构的思路和需要改善的地方。</p></blockquote><h2 id="开发周期-10day"><a href="#开发周期-10day" class="headerlink" title="开发周期 (10day)"></a>开发周期 (10day)</h2><ul><li>库表设计</li><li>接口整理和整合设计(短信&amp;友盟&amp;邮件等)</li><li>代码编写</li></ul><h2 id="业务流程图"><a href="#业务流程图" class="headerlink" title="业务流程图"></a>业务流程图</h2><h3 id="表"><a href="#表" class="headerlink" title="表"></a>表</h3><ul><li>消息记录表, <strong>主要负责消息出入口记录</strong></li><li>事件触发表, <strong>主要对消息进行控制，例如: 触发订单变更推送到用户&#x2F;运营人员 and so on</strong></li><li>消息状态表, <strong>主要负责消息发送的状态，包含定时发送，撤销发送 and so on</strong></li></ul><h3 id="图"><a href="#图" class="headerlink" title="图"></a>图</h3><p><img src="http://cdn.hocgin.top/%E4%B8%9A%E5%8A%A1-now.png" alt="当前业务流程图"></p><h2 id="类流程图"><a href="#类流程图" class="headerlink" title="类流程图"></a>类流程图</h2><p><img src="http://cdn.hocgin.top/%E7%B1%BB-now.png" alt="当前类流程图"></p><p>如图，此模式主要是利用工厂模式, 提供多种消息通道实例，由不同的消息通道对自身通道消息进行处理，类似于把西瓜，牛肉，白菜等送入不同的工厂进行加工，但是又由食品质量控制中心对其进行记录和检验。</p><p><strong>优点</strong>: 后期便于扩展更多的通道模式<br><strong>缺点</strong>: 各个模式是靠类型区别的，不便于进行细节化处理(例如，对某部分APP推送进行定制化，进入某个Activity等细节化定制)</p><h2 id="进一步优化类流程图"><a href="#进一步优化类流程图" class="headerlink" title="进一步优化类流程图"></a>进一步优化类流程图</h2><blockquote><p>使用Route进行更细节的定制化处理<br>更多实战，<a href="https://github.com/chanjarster/weixin-java-tools">推荐</a></p></blockquote><h3 id="图-1"><a href="#图-1" class="headerlink" title="图"></a>图</h3><p><img src="http://cdn.hocgin.top/%E7%B1%BB-op.png" alt="当前类流程图"></p><blockquote><p>囧，单看图可能细分不出两者的差别，附上一段代码实例</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 路由规则初始化，用于定义匹配规则</span></span><br><span class="line"><span class="type">NoticeRouter</span> <span class="variable">router</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">NoticeRouter</span>();</span><br><span class="line">route.rule()</span><br><span class="line">    .noticeType(Notice.SMS)</span><br><span class="line">    <span class="comment">// ... 更多细节规则匹配</span></span><br><span class="line">    .handler(smsHandler)</span><br><span class="line">    .end()</span><br><span class="line">    .rule()</span><br><span class="line">    .noticeType(Notice.EMail)</span><br><span class="line">    <span class="comment">// ... 更多细节规则匹配</span></span><br><span class="line">    .handler(emailHandler)</span><br><span class="line">    .end()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 将通知实体通知路由处理</span></span><br><span class="line">router.route(message)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li>充分考虑后期业务需求 (就算非必须的业务需求)<blockquote><p>不要妄想需求是恒久不变的，需求&#x3D;小三，扩展&#x3D;真爱</p></blockquote></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;  新手上路，小心撞车..&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="设计思路" scheme="https://hocg.in/tags/%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF/"/>
    
  </entry>
  
  <entry>
    <title>Mac的使用</title>
    <link href="https://hocg.in/2016/07/02/Mac-%E4%BD%BF%E7%94%A8/"/>
    <id>https://hocg.in/2016/07/02/Mac-%E4%BD%BF%E7%94%A8/</id>
    <published>2016-07-02T10:47:06.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>  留坑，刚刚起步，梳理中ing。</p><span id="more"></span><h3 id="小技巧"><a href="#小技巧" class="headerlink" title="小技巧"></a>小技巧</h3><ul><li>在Dock 隐藏 iTerm2<br>隐藏:<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/libexec/PlistBuddy -c &quot;Add :LSUIElement bool true&quot; /Applications/iTerm.app/Contents/Info.plist</span><br></pre></td></tr></table></figure>显示:<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/libexec/PlistBuddy -c &quot;Delete :LSUIElement&quot; /Applications/iTerm.app/Contents/Info.plist</span><br></pre></td></tr></table></figure></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;  留坑，刚刚起步，梳理中ing。&lt;/p&gt;</summary>
    
    
    
    <category term="OS" scheme="https://hocg.in/categories/OS/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Mac" scheme="https://hocg.in/tags/Mac/"/>
    
  </entry>
  
  <entry>
    <title>谈JVM，各种过程</title>
    <link href="https://hocg.in/2016/06/12/%E8%B0%88JVM-%E5%90%84%E7%A7%8D%E8%BF%87%E7%A8%8B/"/>
    <id>https://hocg.in/2016/06/12/%E8%B0%88JVM-%E5%90%84%E7%A7%8D%E8%BF%87%E7%A8%8B/</id>
    <published>2016-06-12T19:37:49.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>谈谈JVM 各种过程， XMind等我整理一下，稍后贴出 囧～<br>欢迎指教..<br><strong>update:</strong> 2016-08-03 14:44:12 更新了图</p><span id="more"></span><h3 id="总思路"><a href="#总思路" class="headerlink" title="总思路"></a>总思路</h3><p>编译过程 -&gt; 运行过程[类加载器过程(类的装载过程) -&gt; 执行过程]</p><h4 id="图"><a href="#图" class="headerlink" title="图"></a>图</h4><p><img src="http://cdn.hocgin.top/%E6%80%BB%E6%80%9D%E8%B7%AF-v1.png" alt="总思路-v1.png"></p><h3 id="编译过程"><a href="#编译过程" class="headerlink" title="编译过程"></a>编译过程</h3><p>.java文件 -javac编译-&gt; .class文件       {-JIT编译(转化+优化)-&gt; 本地方法}[执行过程，当方法执行频率高]</p><h4 id="图-1"><a href="#图-1" class="headerlink" title="图"></a>图</h4><p><img src="http://cdn.hocgin.top/%E7%BC%96%E8%AF%91%E8%BF%87%E7%A8%8B.png" alt="编译过程.png"></p><hr><h3 id="运行过程"><a href="#运行过程" class="headerlink" title="运行过程"></a>运行过程</h3><p>类加载器 -&gt; (执行引擎 -&gt; 本地库接口)[Java 运行时数据区] -&gt; 本地方法库</p><h4 id="图-2"><a href="#图-2" class="headerlink" title="图"></a>图</h4><p><img src="http://cdn.hocgin.top/%E8%BF%90%E8%A1%8C%E8%BF%87%E7%A8%8B.png" alt="运行过程.png"></p><hr><h3 id="类加载器过程"><a href="#类加载器过程" class="headerlink" title="类加载器过程"></a><strong>类加载器</strong>过程</h3><p>[启动]类加载器(JNI) -&gt; [扩展]类加载器 -&gt; [系统]类加载器 -&gt; [自定义]类加载器</p><h4 id="图-3"><a href="#图-3" class="headerlink" title="图"></a>图</h4><p><img src="http://cdn.hocgin.top/%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8%E8%BF%87%E7%A8%8B.png" alt="类加载器过程.png"></p><hr><h3 id="类装载过程"><a href="#类装载过程" class="headerlink" title="类装载过程"></a><strong>类</strong>装载过程</h3><p>加载文件到JVM内存 -&gt; (校验语言规范 -&gt; 分配结构存储类的信息 -&gt; 该类常量池中符号更改为直接引用)[Linking] -&gt; 类初始化</p><h4 id="图-4"><a href="#图-4" class="headerlink" title="图"></a>图</h4><p><img src="http://cdn.hocgin.top/%E7%B1%BB%E8%A3%85%E8%BD%BD%E8%BF%87%E7%A8%8B.png" alt="类装载过程.png"></p><hr><h3 id="执行引擎执行过程-逐行读取指令"><a href="#执行引擎执行过程-逐行读取指令" class="headerlink" title="执行引擎执行过程(逐行读取指令)"></a><strong>执行引擎</strong>执行过程(逐行读取指令)</h3><p>Thread启动 -生成-&gt; JVM栈 -执行方法-&gt; 压入栈帧(包含 局部变量数组&amp;操作数栈&amp;运行时常量池) -&gt; 逐行读取指令&amp;&amp;解释(JVM栈帧 程序计数器存放下一条指令) -&gt; {JIT(转化+优化)-&gt; 本地方法}[当方法执行频率高] -执行&amp;运算-&gt; 结果(存放 操作数栈中) -&gt; 推出栈帧</p><h4 id="图-5"><a href="#图-5" class="headerlink" title="图"></a>图</h4><p><img src="http://cdn.hocgin.top/%E6%89%A7%E8%A1%8C%E5%BC%95%E6%93%8E%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B.png" alt="执行引擎执行过程.png"></p><hr><h3 id="Java-运行时数据区-贯穿整个执行过程"><a href="#Java-运行时数据区-贯穿整个执行过程" class="headerlink" title="Java 运行时数据区(贯穿整个执行过程)"></a>Java 运行时数据区(贯穿整个执行过程)</h3><p>共享型数据区：方法区(含运行时常量池[存放方法&amp;变量的实际<strong>地址</strong>])、堆(存放对象实例)<br>隔离型数据区：JVM 栈、本地方法栈(JNI)、程序计数器</p><h4 id="图-6"><a href="#图-6" class="headerlink" title="图"></a>图</h4><p><img src="http://cdn.hocgin.top/%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E5%9B%BE.png" alt="运行时数据图.png"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;谈谈JVM 各种过程， XMind等我整理一下，稍后贴出 囧～&lt;br&gt;欢迎指教..&lt;br&gt;&lt;strong&gt;update:&lt;/strong&gt; 2016-08-03 14:44:12 更新了图&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="JVM" scheme="https://hocg.in/tags/JVM/"/>
    
  </entry>
  
  <entry>
    <title>谈JVM，字节码</title>
    <link href="https://hocg.in/2016/06/12/%E8%B0%88JVM-%E5%AD%97%E8%8A%82%E7%A0%81/"/>
    <id>https://hocg.in/2016/06/12/%E8%B0%88JVM-%E5%AD%97%E8%8A%82%E7%A0%81/</id>
    <published>2016-06-12T19:37:49.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>谈谈JVM，最近在研究破解jar，有这方面经验的麻烦指导一下思路..</p><span id="more"></span><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="http://www.yangyong.me/java-class%E6%96%87%E4%BB%B6%E5%92%8C%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%AD%97%E8%8A%82%E7%A0%81%E6%8C%87%E4%BB%A4-%E5%A6%82%E4%BD%95%E6%9F%A5%E7%9C%8Bclass%E6%96%87%E4%BB%B6/#viewclass">参考1</a><br><a href="http://blog.csdn.net/sprayabc/article/details/8576605">指令整理</a></p><h2 id="常用指令"><a href="#常用指令" class="headerlink" title="常用指令"></a>常用指令</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">反编译查看`类文件`所有信息</span></span><br><span class="line">javap -verbose [class]</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="局部变量类型"><a href="#局部变量类型" class="headerlink" title="局部变量类型"></a>局部变量类型</h2><table><thead><tr><th>特殊字符表示</th><th>类型</th><th>描述</th></tr></thead><tbody><tr><td>c</td><td>char</td><td>char类型</td></tr><tr><td>i</td><td>int</td><td>int类型</td></tr><tr><td>l</td><td>long</td><td>long类型</td></tr><tr><td>s</td><td>short</td><td>short类型</td></tr><tr><td>b</td><td>byte</td><td>byte类型</td></tr><tr><td>f</td><td>float</td><td>float类型</td></tr><tr><td>z</td><td>boolean</td><td>布尔类型</td></tr><tr><td>a</td><td>reference</td><td>引用</td></tr></tbody></table><h2 id="方法信息"><a href="#方法信息" class="headerlink" title="方法信息"></a>方法信息</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">L1</span><br><span class="line">    LOCALVARIABLE this LMain; L0 L1 0</span><br><span class="line">    LOCALVARIABLE a I L0 L1 1</span><br><span class="line">    MAXSTACK = 0</span><br><span class="line">    MAXLOCALS = 2</span><br></pre></td></tr></table></figure><p>局部变量参数 LOCALVARIABLE<br>局部表大小 MAXLOCALS<br>操作数栈大小 MAXSTACK</p><h2 id="指令"><a href="#指令" class="headerlink" title="指令"></a>指令</h2><h3 id="运算指令"><a href="#运算指令" class="headerlink" title="运算指令"></a>运算指令</h3><blockquote><p>算术指令用于对两个<code>操作数栈</code>上的值进行某种特定运算，并把结果重新存入到<code>操作栈</code>顶。</p></blockquote><ul><li>加法指令:iadd,ladd,fadd,dadd</li><li>减法指令:isub,lsub,fsub,dsub</li><li>乘法指令:imul,lmul,fmul,dmul</li><li>除法指令:idiv,ldiv,fdiv,ddiv</li><li>求余指令:irem,lrem,frem,drem</li><li>取反指令:ineg,leng,fneg,dneg</li><li>位移指令:ishl,ishr,iushr,lshl,lshr,lushr</li><li>按位或指令:ior,lor</li><li>按位与指令:iand,land</li><li>按位异或指令:ixor,lxor</li><li>局部变量自增指令:iinc</li><li>比较指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp</li></ul><h3 id="加载和存储指令"><a href="#加载和存储指令" class="headerlink" title="加载和存储指令"></a>加载和存储指令</h3><blockquote><p>用于<code>局部变量表</code>和<code>操作数栈</code>之间来回传输</p></blockquote><ul><li>将一个局部变量加载到操作数栈的指令包括：iload,iload_&lt;n&gt;，lload、lload_&lt;n&gt;、float、fload_&lt;n&gt;、dload、dload_&lt;n&gt;，aload、aload_&lt;n&gt;。</li><li>将一个数值从操作数栈存储到局部变量标的指令：istore,istore_&lt;n&gt;,lstore,lstore_&lt;n&gt;,fstore,fstore_&lt;n&gt;,dstore,dstore_&lt;n&gt;,astore,astore_&lt;n&gt;</li><li>将常量加载到操作数栈的指令：bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_&lt;i&gt;,lconst_&lt;l&gt;,fconst_&lt;f&gt;,dconst_&lt;d&gt;</li><li>局部变量表的访问索引指令:wide<br>  一部分以尖括号结尾的指令代表了一组指令，如iload_&lt;i&gt;，代表了iload_0,iload_1等，这几组指令都是带有一个操作数的通用指令。</li></ul><h3 id="运算指令-1"><a href="#运算指令-1" class="headerlink" title="运算指令"></a>运算指令</h3><blockquote><p>对两个<code>操作数栈</code>上的值进行某种特定运算，并把结果重新存入到<code>操作栈</code>顶</p></blockquote><ul><li>加法指令:iadd,ladd,fadd,dadd</li><li>减法指令:isub,lsub,fsub,dsub</li><li>乘法指令:imul,lmul,fmul,dmul</li><li>除法指令:idiv,ldiv,fdiv,ddiv</li><li>求余指令:irem,lrem,frem,drem</li><li>取反指令:ineg,leng,fneg,dneg</li><li>位移指令:ishl,ishr,iushr,lshl,lshr,lushr</li><li>按位或指令:ior,lor</li><li>按位与指令:iand,land</li><li>按位异或指令:ixor,lxor</li><li>局部变量自增指令:iinc</li><li>比较指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp</li></ul><h3 id="类型转换指令"><a href="#类型转换指令" class="headerlink" title="类型转换指令"></a>类型转换指令</h3><blockquote><p>将两种Java虚拟机数值类型相互转换</p></blockquote><p>JVM支持宽化类型转换(小范围类型向大范围类型转换)：</p><ul><li>int类型到long,float,double类型</li><li>long类型到float,double类型</li><li>float到double类型</li></ul><h3 id="对象创建与操作"><a href="#对象创建与操作" class="headerlink" title="对象创建与操作"></a>对象创建与操作</h3><blockquote><p>虽然类实例和数组都是对象，Java虚拟机对类实例和数组的创建与操作使用了不同的字节码指令。</p></blockquote><ul><li>创建实例的指令:new</li><li>创建数组的指令:newarray,anewarray,multianewarray</li><li>访问字段指令:getfield,putfield,getstatic,putstatic</li><li>把数组元素加载到操作数栈指令:baload,caload,saload,iaload,laload,faload,daload,aaload</li><li>将操作数栈的数值存储到数组元素中执行:bastore,castore,castore,sastore,iastore,fastore,dastore,aastore</li><li>取数组长度指令:arraylength</li><li>检查实例类型指令:instanceof,checkcast</li></ul><h3 id="操作数栈管理指令"><a href="#操作数栈管理指令" class="headerlink" title="操作数栈管理指令"></a>操作数栈管理指令</h3><p>直接操作操作数栈的指令：pop,pop2,dup,dup2,dup_x1,dup2_x1,dup_x2,dup2_x2和swap</p><blockquote><p>NOTE: 压入栈顶(DUP)&#x2F;弹出栈顶(POP)</p></blockquote><h3 id="控制转移指令"><a href="#控制转移指令" class="headerlink" title="控制转移指令"></a>控制转移指令</h3><ul><li>条件分支:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnotnull,if_cmpeq,if_icmpne,if_icmlt,if_icmpgt等</li><li>复合条件分支:tableswitch,lookupswitch</li><li>无条件分支:goto,goto_w,jsr,jsr_w,ret</li></ul><h3 id="方法调用和返回指令"><a href="#方法调用和返回指令" class="headerlink" title="方法调用和返回指令"></a>方法调用和返回指令</h3><ul><li>invokevirtual指令:调用对象的实例方法，根据对象的实际类型进行分派(虚拟机分派)。</li><li>invokeinterface指令:调用接口方法，在运行时搜索一个实现这个接口方法的对象，找出合适的方法进行调用。</li><li>invokespecial:调用需要特殊处理的实例方法，包括实例初始化方法，私有方法和父类方法</li><li>invokestatic:调用类方法(static)</li><li>方法返回指令是根据返回值的类型区分的，包括ireturn(返回值是boolean,byte,char,short和int),lreturn,freturn,drturn和areturn，另外一个return供void方法，实例初始化方法，类和接口的类初始化i方法使用。</li></ul><h3 id="同步"><a href="#同步" class="headerlink" title="同步"></a>同步</h3><h2 id="Eg"><a href="#Eg" class="headerlink" title="Eg:"></a>Eg:</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line">// class version 52.0 (52)</span><br><span class="line">// access flags 0x21</span><br><span class="line">public class Main &#123;</span><br><span class="line"></span><br><span class="line">  // compiled from: Main.java</span><br><span class="line"></span><br><span class="line">  // access flags 0x11</span><br><span class="line">  public final I simpleField = 100</span><br><span class="line"></span><br><span class="line">  // access flags 0x0</span><br><span class="line">  &lt;init&gt;()V</span><br><span class="line">   L0</span><br><span class="line">    LINENUMBER 12 L0</span><br><span class="line">    ALOAD 0</span><br><span class="line">    INVOKESPECIAL java/lang/Object.&lt;init&gt; ()V</span><br><span class="line">   L1</span><br><span class="line">    LINENUMBER 10 L1</span><br><span class="line">    ALOAD 0</span><br><span class="line">    BIPUSH 100</span><br><span class="line">    PUTFIELD Main.simpleField : I</span><br><span class="line">   L2</span><br><span class="line">    LINENUMBER 13 L2</span><br><span class="line">    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;</span><br><span class="line">    BIPUSH 100</span><br><span class="line">    INVOKEVIRTUAL java/io/PrintStream.print (I)V</span><br><span class="line">   L3</span><br><span class="line">    LINENUMBER 14 L3</span><br><span class="line">    RETURN</span><br><span class="line">   L4</span><br><span class="line">    LOCALVARIABLE this LMain; L0 L4 0</span><br><span class="line">    MAXSTACK = 2</span><br><span class="line">    MAXLOCALS = 1</span><br><span class="line"></span><br><span class="line">  // access flags 0x9</span><br><span class="line">  public static main([Ljava/lang/String;)V</span><br><span class="line">   L0</span><br><span class="line">    LINENUMBER 16 L0</span><br><span class="line">    NEW Main</span><br><span class="line">    DUP</span><br><span class="line">    INVOKESPECIAL Main.&lt;init&gt; ()V</span><br><span class="line">    ASTORE 1</span><br><span class="line">   L1</span><br><span class="line">    LINENUMBER 17 L1</span><br><span class="line">    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;</span><br><span class="line">    LDC &quot;--&gt;&quot;</span><br><span class="line">    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V</span><br><span class="line">   L2</span><br><span class="line">    LINENUMBER 19 L2</span><br><span class="line">    RETURN</span><br><span class="line">   L3</span><br><span class="line">    LOCALVARIABLE args [Ljava/lang/String; L0 L3 0</span><br><span class="line">    LOCALVARIABLE main LMain; L1 L3 1</span><br><span class="line">    MAXSTACK = 2</span><br><span class="line">    MAXLOCALS = 2</span><br><span class="line"></span><br><span class="line">  // access flags 0x21</span><br><span class="line">  public synchronized a(I)V throws java/lang/Exception </span><br><span class="line">   L0</span><br><span class="line">    LINENUMBER 23 L0</span><br><span class="line">    RETURN</span><br><span class="line">   L1</span><br><span class="line">    LOCALVARIABLE this LMain; L0 L1 0</span><br><span class="line">    LOCALVARIABLE a I L0 L1 1</span><br><span class="line">    MAXSTACK = 0</span><br><span class="line">    MAXLOCALS = 2</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;谈谈JVM，最近在研究破解jar，有这方面经验的麻烦指导一下思路..&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="Java" scheme="https://hocg.in/tags/Java/"/>
    
    <category term="JVM" scheme="https://hocg.in/tags/JVM/"/>
    
  </entry>
  
  <entry>
    <title>关于HTTPS</title>
    <link href="https://hocg.in/2016/06/02/Https-%E7%AD%BE%E8%AF%81/"/>
    <id>https://hocg.in/2016/06/02/Https-%E7%AD%BE%E8%AF%81/</id>
    <published>2016-06-02T11:22:43.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>这是一篇关于<code>HTTPS</code>的日常使用记录，例如:博客HTTPS化~<br>来吧!年轻人!<del>装逼</del>HTTPS时代到了</p><span id="more"></span><h3 id="关于https"><a href="#关于https" class="headerlink" title="关于https"></a>关于https</h3><p><a href="https://en.wikipedia.org/wiki/HTTPS">什么是HTTPS ?</a></p><blockquote><p>通俗的讲：隐私安全</p></blockquote><h3 id="GitHub-page-使用https"><a href="#GitHub-page-使用https" class="headerlink" title="GitHub page 使用https"></a>GitHub page 使用https</h3><p>主要是使用 <a href="https://kloudsec.com/github-pages/new">Kloudsec</a></p><ol><li>申请账号，填入待解析的域名</li><li>把<code>DNS解析</code>转到该网站提供的地址</li><li>验证邮箱并填入<code>GitHub page IP</code></li><li>开启相关服务</li></ol><ul><li><code>PROTECTION</code> -&gt; <code>SSL Encryption</code></li><li><code>PLUGIN STORE</code><br><a href="https://hocg.in/">成品</a><br><strong>NOTE: 2016年09月04日 发现<code>Kloudsec</code>已经倒闭了</strong><br>现在使用的是<a href="https://www.cloudflare.com/">Cloudflare</a><br>具体使用注册时有引导教程(<code>需把域名解析服务器改为cloudflare的</code>).</li></ul><h3 id="自己搭建的blog"><a href="#自己搭建的blog" class="headerlink" title="自己搭建的blog"></a>自己搭建的blog</h3><p>免费的使用 <a href="https://www.startssl.com/">Startssl</a><br><a href="https://blog.lutty.me/">成品</a></p><h3 id="TOMCAT-配置https环境"><a href="#TOMCAT-配置https环境" class="headerlink" title="TOMCAT 配置https环境"></a>TOMCAT 配置https环境</h3><p><a href="http://blog.csdn.net/small____fish/article/details/8214938"> keytool 教程</a><br>外网回调可尝试使用<a href="http://www.nat123.com/">nat123</a></p><h3 id="自己VPS使用HTTPS"><a href="#自己VPS使用HTTPS" class="headerlink" title="自己VPS使用HTTPS"></a>自己VPS使用<code>HTTPS</code></h3><p><a href="https://laravel-china.org/topics/2766">Let’s Encrypt</a></p><p>:)</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;这是一篇关于&lt;code&gt;HTTPS&lt;/code&gt;的日常使用记录，例如:博客HTTPS化~&lt;br&gt;来吧!年轻人!&lt;del&gt;装逼&lt;/del&gt;HTTPS时代到了&lt;/p&gt;</summary>
    
    
    
    <category term="Server" scheme="https://hocg.in/categories/Server/"/>
    
    
    <category term="HTTPS" scheme="https://hocg.in/tags/HTTPS/"/>
    
  </entry>
  
  <entry>
    <title>ES6 新特性</title>
    <link href="https://hocg.in/2016/05/10/ES6-%E6%96%B0%E7%89%B9%E6%80%A7/"/>
    <id>https://hocg.in/2016/05/10/ES6-%E6%96%B0%E7%89%B9%E6%80%A7/</id>
    <published>2016-05-10T10:28:29.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>NodeJS 的构建工具层出不穷，因此了解一下陈旧事物的进展。</p><span id="more"></span><h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p>es6: ecmscript6</p><h1 id="新特性"><a href="#新特性" class="headerlink" title="新特性"></a>新特性</h1><ul><li>let 块级作用域, <code>注: es5中var声明的上全局范围的</code></li><li>const 常量</li><li>class 类</li><li>extends 继承</li><li>super 指代父类的实例</li><li>arrow functions 语法糖<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 语法: (参数) =&gt; &#123;执行代码&#125;</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">function</span>(<span class="params">i</span>)&#123; <span class="keyword">return</span> i + <span class="number">1</span>; &#125; <span class="comment">//ES5</span></span><br><span class="line">(i) =&gt; &#123; i + <span class="number">1</span> &#125; <span class="comment">//ES6</span></span><br></pre></td></tr></table></figure></li><li>template string 模版字符  <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 语法: `$&#123;变量&#125;`</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"> <span class="keyword">const</span> name = <span class="string">&#x27;hocgin&#x27;</span>;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`this is template strnig</span></span><br><span class="line"><span class="string"> &lt;b&gt;<span class="subst">$&#123;name&#125;</span>&lt;/b&gt;</span></span><br><span class="line"><span class="string"> `</span>);</span><br></pre></td></tr></table></figure></li><li>destructuring   <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> cat = <span class="string">&#x27;ken&#x27;</span></span><br><span class="line"><span class="keyword">let</span> dog = <span class="string">&#x27;lili&#x27;</span></span><br><span class="line"><span class="keyword">let</span> zoo = &#123;cat, dog&#125;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(zoo)  <span class="comment">//Object &#123;cat: &quot;ken&quot;, dog: &quot;lili&quot;&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> dog = &#123;<span class="attr">type</span>: <span class="string">&#x27;animal&#x27;</span>, <span class="attr">many</span>: <span class="number">2</span>&#125;</span><br><span class="line"><span class="keyword">let</span> &#123; type, many&#125; = dog</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(type, many)   <span class="comment">//animal 2</span></span><br></pre></td></tr></table></figure></li><li>default 默认值<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 语法:</span></span><br><span class="line"><span class="comment"> * function &lt;method name&gt;(param = &lt;default value&gt;) &#123;</span></span><br><span class="line"><span class="comment"> *    ...</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">animal</span>(<span class="params">type = <span class="string">&#x27;cat&#x27;</span></span>)&#123;</span><br><span class="line">     <span class="variable language_">console</span>.<span class="title function_">log</span>(type)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="title function_">animal</span>();</span><br></pre></td></tr></table></figure></li><li>rest 可变参数<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 语法:</span></span><br><span class="line"><span class="comment"> * function &lt;method name&gt;(...params) &#123;</span></span><br><span class="line"><span class="comment"> *    ...</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">animals</span>(<span class="params">...types</span>)&#123;</span><br><span class="line">     <span class="variable language_">console</span>.<span class="title function_">log</span>(types)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="title function_">animals</span>(<span class="string">&#x27;cat&#x27;</span>, <span class="string">&#x27;dog&#x27;</span>, <span class="string">&#x27;fish&#x27;</span>);</span><br></pre></td></tr></table></figure></li><li>import export 模块设计<blockquote><p>es6 把一个文件当作一个模块, 一个模块可<code>export</code>多个变量, 因此不同的<code>export</code><br>可对应不同的<code>import</code></p></blockquote></li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 导出模块</span></span><br><span class="line"><span class="keyword">export</span> animal</span><br><span class="line"><span class="comment">// 导入模块 - 变量为 animal</span></span><br><span class="line"><span class="keyword">import</span> animal <span class="keyword">from</span> <span class="string">&#x27;./content&#x27;</span></span><br><span class="line"><span class="comment">//--------------------</span></span><br><span class="line"><span class="comment">// 导出模块</span></span><br><span class="line"><span class="keyword">export</span> &#123;dog, cat&#125;</span><br><span class="line"><span class="comment">// 导入模块 - 变量为 [dog, cat]</span></span><br><span class="line"><span class="keyword">import</span> &#123;dog, cat&#125; <span class="keyword">from</span> <span class="string">&#x27;./content&#x27;</span></span><br><span class="line"><span class="comment">//--------------------</span></span><br><span class="line"><span class="keyword">export</span> &#123;dog, cat&#125;</span><br><span class="line"><span class="comment">// 全部导入</span></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> animal <span class="keyword">from</span> <span class="string">&#x27;./content&#x27;</span></span><br><span class="line"><span class="comment">// or</span></span><br><span class="line"><span class="variable language_">module</span> animal form <span class="string">&#x27;./content&#x27;</span></span><br><span class="line"><span class="comment">//--------------------</span></span><br><span class="line"><span class="comment">// 默认导出, 一个模块只能使用 export default 一次</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="string">&#x27;dog dog&#x27;</span></span><br><span class="line"><span class="keyword">import</span> animal <span class="keyword">from</span> <span class="string">&#x27;./content&#x27;</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;NodeJS 的构建工具层出不穷，因此了解一下陈旧事物的进展。&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="NodeJS" scheme="https://hocg.in/tags/NodeJS/"/>
    
    <category term="Ubuntu" scheme="https://hocg.in/tags/Ubuntu/"/>
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
  </entry>
  
  <entry>
    <title>使用Maven下载jar包 linux版</title>
    <link href="https://hocg.in/2016/04/25/%E4%BD%BF%E7%94%A8Maven%E4%B8%8B%E8%BD%BDjar%E5%8C%85-linux%E7%89%88/"/>
    <id>https://hocg.in/2016/04/25/%E4%BD%BF%E7%94%A8Maven%E4%B8%8B%E8%BD%BDjar%E5%8C%85-linux%E7%89%88/</id>
    <published>2016-04-25T09:38:49.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>这只是学习Shell的小脚本, 练手工具罢了.. 折腾!折腾啊</p><span id="more"></span><h2 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Green4nodeJS</span><br><span class="line">├── down.sh // 下载shell，o(╯□╰)o其实就是一条shell</span><br><span class="line">└── pom.xml // 正常maven配置</span><br></pre></td></tr></table></figure><h2 id="文件内容"><a href="#文件内容" class="headerlink" title="文件内容"></a>文件内容</h2><p><code>down.sh</code> 内容：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/sh</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Author: hocgin@gmail.com</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">-------------Use--------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">sh down.sh</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">------------------------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">运行pom.xml 下载jar</span></span><br><span class="line">NOW_PATH=$(cd &quot;$(dirname &quot;$0&quot;)&quot;; pwd)</span><br><span class="line">POM_XML=$NOW_PATH&quot;/pom.xml&quot;</span><br><span class="line">TARGET_DIR=$NOW_PATH&quot;/target&quot;</span><br><span class="line">mvn -f $POM_XML dependency:copy-dependencies</span><br><span class="line">sudo chmod -R 777 $TARGET_DIR</span><br></pre></td></tr></table></figure><p><code>pom.xml</code> 内容：</p><blockquote><p>正常maven的pom.xml内容</p></blockquote><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span> <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 项目的名称 start --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>temp.download<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>temp-download<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 项目的名称 end --&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 要下载的jar start --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.json<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>json<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">version</span>&gt;</span>20160212<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">     <span class="comment">&lt;!-- 要下载的jar end --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><p>完成</p><h2 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">source init.sh</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Or</span></span><br><span class="line">. init.sh</span><br><span class="line"></span><br><span class="line">cd hocgin.github.io</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">尽情hexo吧</span></span><br></pre></td></tr></table></figure><p>End</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;这只是学习Shell的小脚本, 练手工具罢了.. 折腾!折腾啊&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Maven" scheme="https://hocg.in/tags/Maven/"/>
    
    <category term="Shell" scheme="https://hocg.in/tags/Shell/"/>
    
  </entry>
  
  <entry>
    <title>绿化NodeJS for linux版</title>
    <link href="https://hocg.in/2016/04/25/%E7%BB%BF%E5%8C%96nodejs-for-linux%E7%89%88/"/>
    <id>https://hocg.in/2016/04/25/%E7%BB%BF%E5%8C%96nodejs-for-linux%E7%89%88/</id>
    <published>2016-04-25T09:38:49.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>起因，为了方便hexo发布博客，所以想把NodeJS绿化在U盘上..<br>谁叫网上只有win版的呢！自己码起来～<br>绿化 o(╯□╰)o</p><span id="more"></span><h2 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><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">Green4nodeJS</span><br><span class="line">├── hocgin.github.io // github博客目录</span><br><span class="line">├── node // nodejs基本目录</span><br><span class="line">│   ├── node-linux // nodejs源文件</span><br><span class="line">│   ├── cache // 创建一个空文件夹，即可</span><br><span class="line">│   ├── init-module // 创建一个空文件夹，即可</span><br><span class="line">│   └── userconfig // 创建一个空文件夹，即可</span><br><span class="line">└── init.sh // 初始化shell文件 *重要</span><br></pre></td></tr></table></figure><h2 id="初始化文件"><a href="#初始化文件" class="headerlink" title="初始化文件"></a>初始化文件</h2><blockquote><p>主要是加载配置环境，初始化变量</p></blockquote><p><code>init.sh</code> 内容</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Author: hocgin@gmail.com</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">-------------Use--------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">source</span> init.sh or . init.sh</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">------------------------------</span></span><br><span class="line">NOW_PATH=$(cd &quot;$(dirname &quot;$0&quot;)&quot;; pwd)</span><br><span class="line">NODE_NAME=&quot;node-linux&quot;</span><br><span class="line">NODE_HOME=$NOW_PATH&quot;/node/&quot;$NODE_NAME</span><br><span class="line">NODE_PATH=$NODE_HOME&quot;/bin&quot;</span><br><span class="line">NPM_PATH=$NODE_HOME&quot;/lib/node_modules/npm/bin&quot;</span><br><span class="line">sudo chmod +x -R $NPM_PATH&quot;/.&quot;</span><br><span class="line">export PATH=$PATH:$NODE_PATH:$NPM_PATH</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">&quot;/home/hocgin/.npmrc&quot;</span></span></span><br><span class="line">npm set userconfig $NOW_PATH&quot;/node/userconfig&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">&quot;/home/hocgin/.npm-init.js&quot;</span></span></span><br><span class="line">npm set init-module $NOW_PATH&quot;/node/init-module&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="string">&quot;/home/hocgin/.npm&quot;</span></span></span><br><span class="line">npm set cache  $NOW_PATH&quot;/node/cache&quot;</span><br></pre></td></tr></table></figure><p>修改 <code>/node/node-linux/lib/node_modules/npm/bin/npm</code> 文件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">NPM_CLI_JS=<span class="string">&quot;<span class="variable">$basedir</span>/node_modules/npm/bin/npm-cli.js&quot;</span></span></span><br><span class="line">NPM_CLI_JS=&quot;$basedir/npm-cli.js&quot;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>完成</p><h2 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">source init.sh</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Or</span></span><br><span class="line">. init.sh</span><br><span class="line"></span><br><span class="line">cd hocgin.github.io</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">尽情hexo吧</span></span><br></pre></td></tr></table></figure><p><code>注: 安装module时请加上 -g</code></p><p>End</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;起因，为了方便hexo发布博客，所以想把NodeJS绿化在U盘上..&lt;br&gt;谁叫网上只有win版的呢！自己码起来～&lt;br&gt;绿化 o(╯□╰)o&lt;/p&gt;</summary>
    
    
    
    <category term="Coder" scheme="https://hocg.in/categories/Coder/"/>
    
    
    <category term="NodeJS" scheme="https://hocg.in/tags/NodeJS/"/>
    
    <category term="Ubuntu" scheme="https://hocg.in/tags/Ubuntu/"/>
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
  </entry>
  
  <entry>
    <title>hexo 功能扩展</title>
    <link href="https://hocg.in/2016/03/26/hexo-%E5%8A%9F%E8%83%BD%E6%89%A9%E5%B1%95/"/>
    <id>https://hocg.in/2016/03/26/hexo-%E5%8A%9F%E8%83%BD%E6%89%A9%E5%B1%95/</id>
    <published>2016-03-26T13:44:28.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>这是自己参照hexo进行私人订制的教程，也是实战的记录，感觉还不错，成品可参照本博客.. （如果我以后没换的话😶）</p><span id="more"></span><h2 id="须知"><a href="#须知" class="headerlink" title="须知"></a>须知</h2><p><code>站点目录</code>: &#x2F;<br><code>主题目录</code>: &#x2F;themes&#x2F;[主题名]<br><code>主题配置文件</code>: &#x2F;themes&#x2F;[主题名]&#x2F;_config.yml<br><code>站点配置文件</code>: &#x2F;_config.yml  </p><h2 id="添加微信公众号二维码"><a href="#添加微信公众号二维码" class="headerlink" title="添加微信公众号二维码"></a>添加微信公众号二维码</h2><p>首先，打开<code>主题目录</code>下的 <code>layout/_macro/post.swig</code><br>然后，找到节点<code>footer</code>加入以下代码</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;! -- 添加微信图标 start --&gt;</span><br><span class="line">      &#123;% if theme.wechat_subscriber.enable %&#125;</span><br><span class="line">        &#123;% if !is_home() %&#125;</span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;hocgin-container&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;folder&quot;</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;paper&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">img</span> <span class="attr">width</span>=<span class="string">&quot;100%&quot;</span> <span class="attr">src</span>=<span class="string">&quot;&#123;&#123; theme.wechat_subscriber.qcode &#125;&#125;&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;hocgin-description&quot;</span>&gt;</span>&#123;&#123; theme.wechat_subscriber.description &#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        &#123;% endif %&#125;</span><br><span class="line">      &#123;% endif %&#125;</span><br><span class="line">&lt;! -- 添加微信图标 end --&gt;</span><br></pre></td></tr></table></figure><p>其次，到<code>主题目录</code>下的<code>source/css</code>创建文件夹<code>_hocgin</code>并在它之下创建css文件<code>customize-hocgin.css</code>以下是文件内容：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.hocgin-container</span> *, *<span class="selector-pseudo">:before</span>, *<span class="selector-pseudo">:after</span> &#123;</span><br><span class="line">  <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.hocgin-container</span> &#123;</span><br><span class="line">  <span class="attribute">position</span>: relative;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.hocgin-container</span> &gt; <span class="selector-class">.folder</span> &#123;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">220px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">180px</span>;</span><br><span class="line">  <span class="attribute">left</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">110px</span>);</span><br><span class="line">  <span class="attribute">top</span>: <span class="built_in">calc</span>(<span class="number">70%</span> - <span class="number">90px</span>);</span><br><span class="line">  <span class="attribute">position</span>: relative;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.hocgin-container</span> &gt; <span class="selector-class">.folder</span> &gt; <span class="selector-class">.paper</span> &#123;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">1</span>;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">200px</span>;</span><br><span class="line">  <span class="attribute">top</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">111px</span>);</span><br><span class="line">  <span class="attribute">left</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">100px</span>);</span><br><span class="line">  <span class="attribute">transition</span>: top <span class="number">0.5s</span>, opacity <span class="number">0.4s</span>;</span><br><span class="line">  <span class="attribute">font-family</span>: Verdana, Tahoma, sans-serif;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">0.1em</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">1em</span>;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#644812</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#fde1ab</span>;</span><br><span class="line">  -moz-<span class="attribute">box-shadow</span>: <span class="number">10px</span> <span class="number">10px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.2</span>);</span><br><span class="line">  -webkit-<span class="attribute">box-shadow</span>: <span class="number">10px</span> <span class="number">10px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.2</span>);</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">10px</span> <span class="number">10px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.2</span>);</span><br><span class="line">  -moz-<span class="attribute">border-radius</span>: <span class="number">5px</span>;</span><br><span class="line">  -webkit-<span class="attribute">border-radius</span>: <span class="number">5px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">5px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.hocgin-container</span> &gt; <span class="selector-class">.folder</span><span class="selector-pseudo">:hover</span> &gt; <span class="selector-class">.paper</span> &#123;</span><br><span class="line">  <span class="attribute">top</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">150px</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.hocgin-container</span> &gt; <span class="selector-class">.folder</span><span class="selector-class">.opened</span> &gt; <span class="selector-class">.paper</span> &#123;</span><br><span class="line">  <span class="attribute">top</span>: <span class="built_in">calc</span>(-<span class="number">250px</span>);</span><br><span class="line">  <span class="attribute">opacity</span>: .<span class="number">9</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.hocgin-description</span> &#123;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">margin-top</span>: <span class="number">4px</span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>保存后，找到<code>主题目录</code>下<code>source/css/main.styl</code><strong>(注：别的主题可能不一样)</strong> 追加</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">// --------------------------------------------------</span><br><span class="line"><span class="keyword">@import</span> <span class="string">&quot;_hocgin/customize-hocgin.css&quot;</span>;</span><br></pre></td></tr></table></figure><p>最后，修改<code>主题配置文件</code> 追加</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># Customize args -- Hocgin</span><br><span class="line">wechat_subscriber:</span><br><span class="line">  enable: true</span><br><span class="line">  qcode: [url]</span><br><span class="line">  description: 欢迎您扫一扫上面的微信公众号，订阅我的博客！</span><br></pre></td></tr></table></figure><h3 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h3><p><a href="http://hocg.in/">http://hocg.in</a></p><hr><h2 id="底部加入打赏功能"><a href="#底部加入打赏功能" class="headerlink" title="底部加入打赏功能"></a>底部加入打赏功能</h2><p>首先，打开<code>主题目录</code>下的 <code>layout/_macro/post.swig</code><br>然后，找到节点<code>footer</code>加入以下代码</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">    &lt;! -- 添加打赏图标 start --&gt;</span><br><span class="line">    &#123;% if theme.pay_money.enable %&#125;</span><br><span class="line">      &#123;% if !is_home() %&#125;</span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;hocgin-money&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;money-reward&quot;</span>&gt;</span></span><br><span class="line">    赏</span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;money-pay&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">img</span> <span class="attr">width</span>=<span class="string">&quot;100%&quot;</span> <span class="attr">src</span>=<span class="string">&quot;&#123;&#123; theme.pay_money.weixin_qcode &#125;&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;money-pay&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">img</span> <span class="attr">width</span>=<span class="string">&quot;100%&quot;</span> <span class="attr">src</span>=<span class="string">&quot;&#123;&#123; theme.pay_money.alipay_qcode &#125;&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line">      &#123;% endif %&#125;</span><br><span class="line">    &#123;% endif %&#125;</span><br><span class="line">    &lt;! -- 添加打赏图标 end --&gt;</span><br></pre></td></tr></table></figure><p>其次，到<code>主题目录</code>下的<code>source/css</code>创建文件夹<code>_hocgin</code>并在它之下创建css文件<code>money-customize-hocgin.css</code>以下是文件内容：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.hocgin-money</span> *, *<span class="selector-pseudo">:before</span>, *<span class="selector-pseudo">:after</span> &#123;</span><br><span class="line">    <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.hocgin-money</span> &gt; <span class="selector-class">.money-reward</span> &#123;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">2.4rem</span>;</span><br><span class="line">    <span class="attribute">line-height</span>: <span class="number">4.6rem</span>;</span><br><span class="line">    <span class="attribute">display</span>: block;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">4.6rem</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">4.6rem</span>;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">0</span> auto;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line">    -webkit-user-select: none;</span><br><span class="line">    <span class="attribute">text-align</span>: center;</span><br><span class="line">    <span class="attribute">vertical-align</span>: middle;</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#f1b60e</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">50%</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="number">#fccd60</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">-webkit-gradient</span>(linear, left top, left bottom, <span class="built_in">color-stop</span>(<span class="number">0</span>, <span class="number">#fccd60</span>), <span class="built_in">color-stop</span>(<span class="number">100%</span>, <span class="number">#fbae12</span>), <span class="built_in">color-stop</span>(<span class="number">100%</span>, <span class="number">#2989d8</span>), <span class="built_in">color-stop</span>(<span class="number">100%</span>, <span class="number">#207cca</span>));</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">-webkit-linear-gradient</span>(top, <span class="number">#fccd60</span> <span class="number">0</span>, <span class="number">#fbae12</span> <span class="number">100%</span>, <span class="number">#2989d8</span> <span class="number">100%</span>, <span class="number">#207cca</span> <span class="number">100%</span>);</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(to bottom, <span class="number">#fccd60</span> <span class="number">0</span>, <span class="number">#fbae12</span> <span class="number">100%</span>, <span class="number">#2989d8</span> <span class="number">100%</span>, <span class="number">#207cca</span> <span class="number">100%</span>);</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.hocgin-money</span> &gt; <span class="selector-class">.money-reward</span> &gt; <span class="selector-class">.money-pay</span> &#123;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">200px</span>;</span><br><span class="line">    <span class="attribute">visibility</span>: hidden;</span><br><span class="line">    <span class="attribute">top</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">100px</span>);</span><br><span class="line">    <span class="attribute">left</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">100px</span>);</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">transition</span>: top <span class="number">0.5s</span>, opacity <span class="number">0.4s</span>;</span><br><span class="line">    <span class="attribute">font-family</span>: Verdana, Tahoma, sans-serif;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">0.1em</span>;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">1em</span>;</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#644812</span>;</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="number">#fff</span>;</span><br><span class="line">    -moz-<span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">1px</span> <span class="number">1px</span> <span class="number">1px</span> <span class="number">#efefef</span>;</span><br><span class="line">    -webkit-<span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">1px</span> <span class="number">1px</span> <span class="number">1px</span> <span class="number">#efefef</span>;</span><br><span class="line">    <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">1px</span> <span class="number">1px</span> <span class="number">1px</span> <span class="number">#efefef</span>;</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#e6e6e6</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.hocgin-money</span> &gt; <span class="selector-class">.money-reward</span><span class="selector-pseudo">:hover</span> &gt; <span class="selector-class">.money-pay</span> &#123;</span><br><span class="line">    <span class="attribute">visibility</span>: visible;</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">1</span>;</span><br><span class="line">    <span class="attribute">z-index</span>: <span class="number">10</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.hocgin-money</span> &gt; <span class="selector-class">.money-reward</span><span class="selector-pseudo">:hover</span> &gt; <span class="selector-class">.money-pay</span><span class="selector-pseudo">:nth-child</span>(<span class="number">1</span>) &#123;</span><br><span class="line">    <span class="attribute">top</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">250px</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.hocgin-money</span> &gt; <span class="selector-class">.money-reward</span><span class="selector-pseudo">:hover</span> &gt; <span class="selector-class">.money-pay</span><span class="selector-pseudo">:nth-child</span>(<span class="number">2</span>) &#123;</span><br><span class="line">    <span class="attribute">top</span>: <span class="built_in">calc</span>(<span class="number">50%</span> + <span class="number">50px</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>保存后，找到<code>主题目录</code>下<code>source/css/main.styl</code><strong>(注：别的主题可能不一样)</strong> 追加</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">// --------------------------------------------------</span><br><span class="line"><span class="keyword">@import</span> <span class="string">&quot;_hocgin/money-customize-hocgin.css&quot;</span>;</span><br></pre></td></tr></table></figure><p>最后，修改<code>主题配置文件</code> 追加</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># Customize args -- Hocgin</span><br><span class="line">pay_money:</span><br><span class="line">  enable: true</span><br><span class="line">  weixin_qcode: http://cdn.hocgin.top/img/un/ali.pay.500.png</span><br><span class="line">  alipay_qcode: http://cdn.hocgin.top/img/un/ali.pay.500.png</span><br></pre></td></tr></table></figure><h3 id="已知bug"><a href="#已知bug" class="headerlink" title="已知bug"></a>已知bug</h3><ol><li>因为没使用js(也不想使用)，安卓设备需要<code>长按</code>才能出现效果，而苹果设备无法显示效果，欢迎大家修复。┌|*´∀｀|┘</li></ol><h3 id="效果-1"><a href="#效果-1" class="headerlink" title="效果"></a>效果</h3><p><a href="http://hocg.in/">http://hocg.in</a></p><hr><h2 id="防止百度转码"><a href="#防止百度转码" class="headerlink" title="防止百度转码"></a>防止百度转码</h2><p><code>主题目录</code>下 <code>\layout\_partials\head.swig</code></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">”Cache-Control”</span> <span class="attr">content</span>=<span class="string">”no-transform”</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">”Cache-Control”</span> <span class="attr">content</span>=<span class="string">”no-siteapp”</span> /&gt;</span></span><br></pre></td></tr></table></figure><hr><h2 id="添加搜索功能-2016年06月04日"><a href="#添加搜索功能-2016年06月04日" class="headerlink" title="添加搜索功能 2016年06月04日"></a>添加搜索功能 <code>2016年06月04日</code></h2><ol><li>安装hexo数据生成插件</li></ol><blockquote><p>Json格式的，有利于自主编写(暂时只介绍原生支持的，如果想自己编写下面的可以不用看)</p></blockquote><p><a href="https://github.com/alexbruno/hexo-generator-json-content">hexo-generator-json-content</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">npm i -S hexo-generator-json-content</span></span><br></pre></td></tr></table></figure><blockquote><p>NexT 原生支持，不想折腾的可以使用</p></blockquote><p><a href="https://github.com/PaicHyperionDev/hexo-generator-search">hexo-generator-search</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">npm install hexo-generator-search --save</span></span><br></pre></td></tr></table></figure><p><code>站点配置文件</code> 新增</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># Search</span><br><span class="line">search:</span><br><span class="line">  path: search.xml</span><br><span class="line">  field: post</span><br></pre></td></tr></table></figure><p>OK！</p><blockquote><p>待续ing</p></blockquote><hr><h2 id="结合服务器，实现自动部署"><a href="#结合服务器，实现自动部署" class="headerlink" title="结合服务器，实现自动部署"></a>结合服务器，实现自动部署</h2><hr><h2 id="多说css美化"><a href="#多说css美化" class="headerlink" title="多说css美化"></a>多说css美化</h2>]]></content>
    
    
    <summary type="html">&lt;p&gt;这是自己参照hexo进行私人订制的教程，也是实战的记录，感觉还不错，成品可参照本博客.. （如果我以后没换的话😶）&lt;/p&gt;</summary>
    
    
    
    <category term="Web" scheme="https://hocg.in/categories/Web/"/>
    
    
    <category term="HTML5" scheme="https://hocg.in/tags/HTML5/"/>
    
    <category term="Hexo" scheme="https://hocg.in/tags/Hexo/"/>
    
    <category term="CSS3" scheme="https://hocg.in/tags/CSS3/"/>
    
  </entry>
  
  <entry>
    <title>安装完Ubuntu后,我该做什么</title>
    <link href="https://hocg.in/2016/03/20/%E5%AE%89%E8%A3%85%E5%AE%8CUbuntu%E5%90%8E-%E6%88%91%E8%AF%A5%E5%81%9A%E4%BB%80%E4%B9%88/"/>
    <id>https://hocg.in/2016/03/20/%E5%AE%89%E8%A3%85%E5%AE%8CUbuntu%E5%90%8E-%E6%88%91%E8%AF%A5%E5%81%9A%E4%BB%80%E4%B9%88/</id>
    <published>2016-03-20T14:34:20.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>这是一篇我对Ubuntu日常使用和优化的整理，也是一篇借鉴前人的文章，还有一些可能会遇到的疑难杂病的“偏方”，希望对你有帮助:)<br><strong>update</strong>: 新增<code>undistract-me</code>终端命令完成提醒插件</p><span id="more"></span><h2 id="yuan获取"><a href="#yuan获取" class="headerlink" title="yuan获取"></a>yuan获取</h2><p>官方列表： <a href="http://wiki.ubuntu.org.cn/%E6%BA%90%E5%88%97%E8%A1%A8">http://wiki.ubuntu.org.cn/%E6%BA%90%E5%88%97%E8%A1%A8</a><br>网易163： <a href="http://mirrors.163.com/.help/ubuntu.html">http://mirrors.163.com/.help/ubuntu.html</a></p><hr><h2 id="移除"><a href="#移除" class="headerlink" title="移除"></a>移除</h2><blockquote><p>删除libreoffice</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get remove libreoffice-common</span><br></pre></td></tr></table></figure><blockquote><p>删除Amazon的链接s</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get remove unity-webapps-common</span><br></pre></td></tr></table></figure><blockquote><p>删掉基本不用的自带软件</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get remove thunderbird totem rhythmbox empathy brasero simple-scan gnome-mahjongg aisleriot gnome-mines cheese transmission-common gnome-orca webbrowser-app gnome-sudoku  landscape-client-ui-install</span><br><span class="line">sudo apt-get remove onboard deja-dup</span><br></pre></td></tr></table></figure><blockquote><p>shang xia zuoyou</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get remove vim-common</span><br><span class="line">sudo apt-get install vim</span><br></pre></td></tr></table></figure><hr><h2 id="字体"><a href="#字体" class="headerlink" title="字体"></a>字体</h2><p>monaco<code>苹果字体</code><br><a href="https://github.com/cstrap/monaco-font">https://github.com/cstrap/monaco-font</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -kL https://raw.github.com/cstrap/monaco-font/master/install-font-ubuntu.sh | bash</span><br></pre></td></tr></table></figure><p>consolas<code>微软字体</code></p><hr><h2 id="Gnome3"><a href="#Gnome3" class="headerlink" title="Gnome3"></a>Gnome3</h2><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><h4 id="1-安装Gnome3桌面"><a href="#1-安装Gnome3桌面" class="headerlink" title="1.安装Gnome3桌面"></a>1.安装Gnome3桌面</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo add-apt-repository ppa:gnome3-team/gnome3</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install ppa-purge</span><br><span class="line">sudo ppa-purge ppa:gnome3-team/gnome3</span><br><span class="line">sudo apt-get dist-upgrade</span><br><span class="line">sudo apt-get install gnome-themes-standard ubuntu-desktop gnome-shell</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">删除</span></span><br><span class="line">sudo apt-get install ppa-purge</span><br><span class="line">sudo ppa-purge ppa:gnome3-team/gnome3</span><br></pre></td></tr></table></figure><h4 id="2-Gnome3系统"><a href="#2-Gnome3系统" class="headerlink" title="2.Gnome3系统"></a>2.Gnome3系统</h4><p><a href="https://ubuntugnome.org/download/">下载</a></p><h3 id="主题"><a href="#主题" class="headerlink" title="主题"></a>主题</h3><p><code>主题文件位置：~/.themes 或 /usr/share/themes</code></p><h4 id="1-Paper"><a href="#1-Paper" class="headerlink" title="1.Paper"></a>1.Paper</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下拉git</span></span><br><span class="line">git clone https://github.com/snwh/paper-gtk-theme.git</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">运行安装脚本</span></span><br><span class="line">sh ./install-gtk-theme.sh</span><br></pre></td></tr></table></figure><h4 id="2-Numix-Circle"><a href="#2-Numix-Circle" class="headerlink" title="2.Numix-Circle"></a>2.Numix-Circle</h4><blockquote><p>很赞</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo apt-add-repository ppa:numix/ppa</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install numix-icon-theme-circle</span><br></pre></td></tr></table></figure><h3 id="插件支持"><a href="#插件支持" class="headerlink" title="插件支持"></a>插件支持</h3><blockquote><p>gnome-tweak-tool Gnome3的调节软件<br>可直接管理插件</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install gnome-tweak-tool</span><br></pre></td></tr></table></figure><p><code>插件下载网站: https://extensions.gnome.org/</code></p><ol><li>使用Chrome 插件</li><li>系统安装chrome-gnome-shell</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo add-apt-repository ppa:ne0sight/chrome-gnome-shell</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">trusty</span></span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install chrome-gnome-shell</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>插件列表</strong></p><h2 id="名称-描述-推荐—-—-Autohide-battery-可以在电池充满的情况下隐藏电池图标-推荐Battery-status-可以显示当前电池电量以及可以使用的时间-推荐Dash-to-dock-在屏幕左边显示一个快速启动条-推荐Freon-显示当前磁盘，显卡，CPU等等温度-不推荐，推荐SysPeekLock-Keys-显示当前的-Num-Lock-Caps-Lock-的状态-推荐Refesh-wifi-connections-在-wifi-列表上显示一个刷新图标-推荐status-title-bar-讲状态条上的标题改为当前窗口的标题-推荐Coverflow-Alt-Tab-类似WIN-7切换特效-太显眼，不推荐OpenWeather-天气预报-推荐NetSpeed-显示网速-不推荐，推荐SysPeeksystem-monitor-显示当前系统信息-太显眼，不推荐Dynamic-Top-Bar-在当前没有最大化窗口时使顶栏透明-推荐Impatience-Gnome-Shell-动画提速-推荐Better-Volume-Indicator-透过鼠标滚轮操作更便捷地调整音量-推荐Media-player-indicator-显示音乐播放器的状态-推荐Workspaces-to-dock-将工作区转变为一个可自动隐藏的停靠栏-推荐Panel-OSD-修改通知显示位置-推荐Clipboard-Indicator-剪贴板指示器-推荐Caffeine-禁止自动挂起或锁屏-推荐Transmission-Daemon-Indicator-Transmission面板指示器-推荐，需要Transmission-DaemonIcon-Hider-显示-x2F-隐藏顶栏图标-推荐Top-Panel-Workspace-Scroll-在顶栏上滚动鼠标中键来快速切换工作区。在topbar按住shift-滚轮-推荐Drop-Down-Terminal-终端快捷方式-推荐Windows-Blur-Effects-给未激活的窗口添加模糊效果-不推荐Modern-Calc-功能齐全的计算器扩展-没找到EasyScreenCast-录屏工具-推荐Place-status-indicator-快速访问一些文件夹-推荐，没装上Removable-drive-menu-显示连接到电脑的usb设备-推荐User-themes-用来启用自定义的shell主题-推荐，没装上Workspace-indicator-在顶栏显示当前示工作区的序号-推荐touchpad-indicator-插入鼠标时自动使触摸板失效-推荐"><a href="#名称-描述-推荐—-—-Autohide-battery-可以在电池充满的情况下隐藏电池图标-推荐Battery-status-可以显示当前电池电量以及可以使用的时间-推荐Dash-to-dock-在屏幕左边显示一个快速启动条-推荐Freon-显示当前磁盘，显卡，CPU等等温度-不推荐，推荐SysPeekLock-Keys-显示当前的-Num-Lock-Caps-Lock-的状态-推荐Refesh-wifi-connections-在-wifi-列表上显示一个刷新图标-推荐status-title-bar-讲状态条上的标题改为当前窗口的标题-推荐Coverflow-Alt-Tab-类似WIN-7切换特效-太显眼，不推荐OpenWeather-天气预报-推荐NetSpeed-显示网速-不推荐，推荐SysPeeksystem-monitor-显示当前系统信息-太显眼，不推荐Dynamic-Top-Bar-在当前没有最大化窗口时使顶栏透明-推荐Impatience-Gnome-Shell-动画提速-推荐Better-Volume-Indicator-透过鼠标滚轮操作更便捷地调整音量-推荐Media-player-indicator-显示音乐播放器的状态-推荐Workspaces-to-dock-将工作区转变为一个可自动隐藏的停靠栏-推荐Panel-OSD-修改通知显示位置-推荐Clipboard-Indicator-剪贴板指示器-推荐Caffeine-禁止自动挂起或锁屏-推荐Transmission-Daemon-Indicator-Transmission面板指示器-推荐，需要Transmission-DaemonIcon-Hider-显示-x2F-隐藏顶栏图标-推荐Top-Panel-Workspace-Scroll-在顶栏上滚动鼠标中键来快速切换工作区。在topbar按住shift-滚轮-推荐Drop-Down-Terminal-终端快捷方式-推荐Windows-Blur-Effects-给未激活的窗口添加模糊效果-不推荐Modern-Calc-功能齐全的计算器扩展-没找到EasyScreenCast-录屏工具-推荐Place-status-indicator-快速访问一些文件夹-推荐，没装上Removable-drive-menu-显示连接到电脑的usb设备-推荐User-themes-用来启用自定义的shell主题-推荐，没装上Workspace-indicator-在顶栏显示当前示工作区的序号-推荐touchpad-indicator-插入鼠标时自动使触摸板失效-推荐" class="headerlink" title="名称|描述|推荐—-|—-|Autohide battery       |    可以在电池充满的情况下隐藏电池图标 | 推荐Battery status               |  可以显示当前电池电量以及可以使用的时间 | 推荐Dash to dock               |     在屏幕左边显示一个快速启动条 | 推荐Freon                     |    显示当前磁盘，显卡，CPU等等温度|不推荐，推荐SysPeekLock Keys                 |   显示当前的 Num Lock, Caps Lock 的状态 | 推荐Refesh wifi connections    |   在 wifi 列表上显示一个刷新图标 | 推荐status title bar           |   讲状态条上的标题改为当前窗口的标题 | 推荐Coverflow Alt-Tab | 类似WIN 7切换特效 | 太显眼，不推荐OpenWeather | 天气预报 |推荐NetSpeed | 显示网速 |不推荐，推荐SysPeeksystem-monitor| 显示当前系统信息| 太显眼，不推荐Dynamic Top Bar| 在当前没有最大化窗口时使顶栏透明|推荐Impatience | Gnome Shell 动画提速|推荐Better Volume Indicator |透过鼠标滚轮操作更便捷地调整音量|推荐Media player indicator | 显示音乐播放器的状态|推荐Workspaces-to-dock| 将工作区转变为一个可自动隐藏的停靠栏|推荐Panel OSD| 修改通知显示位置|推荐Clipboard Indicator| 剪贴板指示器 | 推荐Caffeine |禁止自动挂起或锁屏 | 推荐Transmission Daemon Indicator |Transmission面板指示器 | 推荐，需要Transmission DaemonIcon Hider |显示&#x2F;隐藏顶栏图标|推荐Top Panel Workspace Scroll| 在顶栏上滚动鼠标中键来快速切换工作区。在topbar按住shift+滚轮|推荐Drop Down Terminal|终端快捷方式|推荐Windows Blur Effects|给未激活的窗口添加模糊效果|不推荐Modern Calc|功能齐全的计算器扩展|没找到EasyScreenCast|录屏工具|推荐Place status indicator | 快速访问一些文件夹|推荐，没装上Removable drive menu | 显示连接到电脑的usb设备|推荐User themes | 用来启用自定义的shell主题 |推荐，没装上Workspace indicator | 在顶栏显示当前示工作区的序号|推荐touchpad-indicator | 插入鼠标时自动使触摸板失效|推荐"></a>名称|描述|推荐<br>—-|—-|<br>Autohide battery       |    可以在电池充满的情况下隐藏电池图标 | 推荐<br>Battery status               |  可以显示当前电池电量以及可以使用的时间 | 推荐<br>Dash to dock               |     在屏幕左边显示一个快速启动条 | 推荐<br>Freon                     |    显示当前磁盘，显卡，CPU等等温度|不推荐，推荐SysPeek<br>Lock Keys                 |   显示当前的 Num Lock, Caps Lock 的状态 | 推荐<br>Refesh wifi connections    |   在 wifi 列表上显示一个刷新图标 | 推荐<br>status title bar           |   讲状态条上的标题改为当前窗口的标题 | 推荐<br>Coverflow Alt-Tab | 类似WIN 7切换特效 | 太显眼，不推荐<br>OpenWeather | 天气预报 |推荐<br>NetSpeed | 显示网速 |不推荐，推荐SysPeek<br>system-monitor| 显示当前系统信息| 太显眼，不推荐<br>Dynamic Top Bar| 在当前没有最大化窗口时使顶栏透明|推荐<br>Impatience | Gnome Shell 动画提速|推荐<br>Better Volume Indicator |透过鼠标滚轮操作更便捷地调整音量|推荐<br>Media player indicator | 显示音乐播放器的状态|推荐<br>Workspaces-to-dock| 将工作区转变为一个可自动隐藏的停靠栏|推荐<br>Panel OSD| 修改通知显示位置|推荐<br>Clipboard Indicator| 剪贴板指示器 | 推荐<br>Caffeine |禁止自动挂起或锁屏 | 推荐<br>Transmission Daemon Indicator |Transmission面板指示器 | 推荐，需要Transmission Daemon<br>Icon Hider |显示&#x2F;隐藏顶栏图标|推荐<br>Top Panel Workspace Scroll| 在顶栏上滚动鼠标中键来快速切换工作区。在topbar按住shift+滚轮|推荐<br>Drop Down Terminal|终端快捷方式|推荐<br>Windows Blur Effects|给未激活的窗口添加模糊效果|不推荐<br>Modern Calc|功能齐全的计算器扩展|没找到<br>EasyScreenCast|录屏工具|推荐<br>Place status indicator | 快速访问一些文件夹|推荐，没装上<br>Removable drive menu | 显示连接到电脑的usb设备|推荐<br>User themes | 用来启用自定义的shell主题 |推荐，没装上<br>Workspace indicator | 在顶栏显示当前示工作区的序号|推荐<br>touchpad-indicator | 插入鼠标时自动使触摸板失效|推荐</h2><h2 id="壁纸"><a href="#壁纸" class="headerlink" title="壁纸"></a>壁纸</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1.安装archibold</span></span><br><span class="line">curl -L -O http://archibold.io/sh/archibold</span><br><span class="line">chmod +x archibold</span><br><span class="line">sudo mv archibold /usr/bin</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">2.执行</span></span><br><span class="line">archibold login-background [壁纸的位置]</span><br></pre></td></tr></table></figure><p>此外还可以让桌面和锁屏界面使用动态壁纸，动态壁纸由一个xml文件构成，就像这样：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">background</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">starttime</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">year</span>&gt;</span>2011<span class="tag">&lt;/<span class="name">year</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">month</span>&gt;</span>11<span class="tag">&lt;/<span class="name">month</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">day</span>&gt;</span>24<span class="tag">&lt;/<span class="name">day</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">hour</span>&gt;</span>7<span class="tag">&lt;/<span class="name">hour</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">minute</span>&gt;</span>00<span class="tag">&lt;/<span class="name">minute</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">second</span>&gt;</span>00<span class="tag">&lt;/<span class="name">second</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">starttime</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">static</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">duration</span>&gt;</span>3600.0<span class="tag">&lt;/<span class="name">duration</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">file</span>&gt;</span>picture1.jpg<span class="tag">&lt;/<span class="name">file</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">static</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">transition</span> <span class="attr">type</span>=<span class="string">&quot;overlay&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">duration</span>&gt;</span>18000.0<span class="tag">&lt;/<span class="name">duration</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">from</span>&gt;</span>picture1.jpg<span class="tag">&lt;/<span class="name">from</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">to</span>&gt;</span>/picture2.jpg<span class="tag">&lt;/<span class="name">to</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">transition</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">static</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">duration</span>&gt;</span>18000.0<span class="tag">&lt;/<span class="name">duration</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">file</span>&gt;</span>picture2.jpg<span class="tag">&lt;/<span class="name">file</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">static</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">transition</span> <span class="attr">type</span>=<span class="string">&quot;overlay&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">duration</span>&gt;</span>21600.0<span class="tag">&lt;/<span class="name">duration</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">from</span>&gt;</span>picture2.jpg<span class="tag">&lt;/<span class="name">from</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">to</span>&gt;</span>picture1.jpg<span class="tag">&lt;/<span class="name">to</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">transition</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">background</span>&gt;</span></span><br></pre></td></tr></table></figure><p>简单解释以下这个xml文件的含义：</p><p><code>starttime</code>：这个部分规定了壁纸切换起始时间，设置成过去的某个时间即可(设置成2020年就要等到2020年才会有效果)<br><code>static</code>：这个部分表示在duration规定的时间(以秒为单位)中壁纸都是file中给定的那张图片<br><code>transition</code>：这个部分表示在duration规定的时间内壁纸从from中的图片切换到to中的图片你可以添加任意多个static+transition的组合，只需要最后一个transition切换回最初的static那张图片就可以循环更换壁纸了。  </p><p>那么如何启用这样的xml文件呢，单凭系统设置无法办到，我们需要使用dconf系统配置编辑器。<br>首先打开dconf编辑器，展开<code>org–gnome–desktop–background</code>这一项，可以看到其中的<code>picture-uri</code>修这一项的默认值是<code>file:///usr/share/backgrounds/gnome/adwaita-timed.xml</code>，这个就是你刚装好桌面是的默认壁纸啦，将其改成你的xml文件就可以了。<br>锁屏界面的壁纸更换方法也一样，只不过把<code>org–gnome–desktop–background</code>改成<code>org–gnome–desktop–screensaver</code>而已</p><hr><h2 id="软件安装"><a href="#软件安装" class="headerlink" title="软件安装"></a>软件安装</h2><h3 id="指令安装"><a href="#指令安装" class="headerlink" title="指令安装"></a>指令安装</h3><blockquote><p>命令面板小提示</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo apt update</span><br><span class="line">sudo apt install python3-dev python3-pip</span><br><span class="line">sudo -H pip3 install thefuck</span><br></pre></td></tr></table></figure><blockquote><p>科学上网 Client-SS</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo add-apt-repository ppa:hzwhuang/ss-qt5</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install shadowsocks-qt5</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装 pip</span></span><br><span class="line">sudo pip install genpac</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载自动翻墙列表</span></span><br><span class="line">genpac -p &quot;SOCKS5 127.0.0.1:1080&quot; --gfwlist-proxy=&quot;SOCKS5 127.0.0.1:1080&quot; --output=&quot;~/Documents/autoproxy.pac&quot; --gfwlist-url=&quot;https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt&quot; --user-rule-from=&quot;user-rules.txt&quot;</span><br></pre></td></tr></table></figure><p><strong>添加开机启动</strong><br>command：<code>/usr/bin/ss-qt5</code></p><blockquote><p>屏幕截图 Shutter</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo apt-get install Shutter</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">打开</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">搜索 Shutter</span></span><br></pre></td></tr></table></figure><blockquote><p>音视频解码 ubuntu-restricted extras</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo apt-get install ubuntu-restricted-extras</span><br></pre></td></tr></table></figure><blockquote><p>终端命令执行完成提醒</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo apt-get install undistract-me</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置</span></span><br><span class="line">vim ~/.bashrc</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新增如下两行</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">. /usr/share/undistract-me/long-running.bash</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">notify_when_long_running_commands_finish_install</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生效</span></span><br><span class="line">source ~/.bashrc</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试</span></span><br><span class="line">sleep 11</span><br><span class="line"></span><br></pre></td></tr></table></figure><blockquote><p>GNOME MPV 代替VLC播放器</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo add-apt-repository ppa:xuzhen666/gnome-mpv</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install gnome-mpv</span><br></pre></td></tr></table></figure><blockquote><p>视频播放 VLC播放器</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo add-apt-repository ppa:videolan/master-daily</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install vlc</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">使用</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">搜索 vlc</span></span><br></pre></td></tr></table></figure><blockquote><p>Grub引导 Grub Customizer<br>可配置启动界面，启动项等</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo add-apt-repository ppa:danielrichter2007/grub-customizer</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install grub-customizer</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">使用</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">搜索 Grub Customizer</span></span><br></pre></td></tr></table></figure><blockquote><p>Office WPS</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo apt-get install wps-office</span><br></pre></td></tr></table></figure><blockquote><p>[小插件]指示器性能 SysPeek</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo add-apt-repository ppa:nilarimogard/webupd8  </span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install syspeeka</span><br></pre></td></tr></table></figure><blockquote><p>Synapse 快速启动器</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo add-apt-repository ppa:synapse-core/testing</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install synapse</span><br></pre></td></tr></table></figure><blockquote><p>Uget一款下载工具，配合 aria2 插件使用效果出色<br>curl + area2 + axel</p></blockquote><p>地址：<a href="http://baike.renwuyi.com/2014-11/2153.html">参考</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo add-apt-repository ppa:plushuang-tw/uget-stable</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install uget</span><br></pre></td></tr></table></figure><blockquote><p>redshift类似 f.lux 的屏幕色温调整工具</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo apt-get install redshift-gtk</span><br></pre></td></tr></table></figure><p><strong>添加开机启动</strong><br>command：<code>redshift-gtk -l 39.92:116.46 -t 5500:4500</code></p><blockquote><p>Go For It 一款整合了待办事项与计时器的生产力应用。</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 安装</span><br><span class="line">sudo add-apt-repository ppa:mank319/go-for-it</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install go-for-it</span><br></pre></td></tr></table></figure><blockquote><p>Catfish 一款优雅迅捷的文件搜索工具</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">sudo apt-get install catfish</span><br></pre></td></tr></table></figure><blockquote><p>神级命令行软件 Tmux <a href="http://www.wushxin.top/2016/03/28/%E4%BD%BF%E7%94%A8tmux.html">说明</a></p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install tmux</span><br></pre></td></tr></table></figure><blockquote><p><code>cat</code>代码高亮</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 安装</span><br><span class="line">pip install pygments</span><br></pre></td></tr></table></figure><p>配置<br>～&#x2F;.bashrc<br>加入<code>alias cat=&#39;pygmentize -O style=monokai -f console256 -g&#39;</code></p><h3 id="软件包安装"><a href="#软件包安装" class="headerlink" title="软件包安装"></a>软件包安装</h3><p><a href="http://ubuntu-tweak.com/">系统管理 UbuntuTweak</a><br><code>打开：搜索 Ubuntu Tweak</code><br><a href="https://www.jianguoyun.com/">同步软件 坚果云</a><br><code>打开：搜索 Nutstore</code><br><a href="https://github.com/LiuLang/bcloud-packages">百度网盘桌面客户端 BCloud</a><br><a href="https://launchpad.net/indicator-stickynotes">便签</a><br><a href="http://keepass.info/">MarkDown编辑软件 HarooPad</a><br><a href="http://pad.haroopress.com/">密码管理器 keepass2</a><br><a href="http://pinyin.sogou.com/linux/?r=pinyin">搜狗输入法</a><br><a href="http://cidian.youdao.com/multi.html#linuxAll">有道词典</a><br><a href="http://www.vmware.com/products/workstation/">VMware Workstation</a><br><a href="http://www.google.cn/chrome/browser/">Chrome</a><br><a href="https://github.com/cosven/FeelUOwn">网易音乐</a><br><a href="http://fabforce.net/dbdesigner4/">数据库设计软件 DBdesigner4</a> - <a href="http://josemarfuregattideabreusilva.blogspot.com/2015/04/installing-dbdesigner-405-on-ubuntu.html">问题1</a></p><hr><h3 id="听起来不错"><a href="#听起来不错" class="headerlink" title="听起来不错"></a>听起来不错</h3><ol><li>Deluge Bittorrent 客户端</li><li>Nutty网络监测工具。</li><li>Synaptic 新立得软件包管理器</li><li>UNetbootin启动盘制作工具</li><li>Gpick拾色器。</li><li>gpaint 微软画图</li><li>ddm 驱动管理器</li><li>Navicat <code>o(╯□╰)o 竟然是wine的</code></li><li>XMind</li></ol><h2 id="小技巧"><a href="#小技巧" class="headerlink" title="小技巧"></a>小技巧</h2><h3 id="关闭系统检测报告"><a href="#关闭系统检测报告" class="headerlink" title="关闭系统检测报告"></a>关闭系统检测报告</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo gedit /etc/default/apport</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改enabled=0</span></span><br></pre></td></tr></table></figure><h3 id="开机自动开启数字键"><a href="#开机自动开启数字键" class="headerlink" title="开机自动开启数字键"></a>开机自动开启数字键</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install numlockx</span><br><span class="line">sudo vim /etc/gdm/Init/Default</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">-----------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在文件最后<span class="built_in">exit</span> 0的前面添加：</span></span><br><span class="line">  if [ -x /usr/bin/numlockx ]; then</span><br><span class="line">      numlockx on</span><br><span class="line">  fi</span><br></pre></td></tr></table></figure><p>重启即可</p><h3 id="插入鼠标时自动使触摸板失效"><a href="#插入鼠标时自动使触摸板失效" class="headerlink" title="插入鼠标时自动使触摸板失效"></a>插入鼠标时自动使触摸板失效</h3><p>安装Touchpad Indicator (触摸板开关）  </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo add-apt-repository ppa:atareao/atareao  </span><br><span class="line">sudo apt-get update  </span><br><span class="line">sudo apt-get install touchpad-indicator</span><br></pre></td></tr></table></figure><p> 搜索 touchpad indicator</p><h3 id="遇到显示俩个输入法图标情况"><a href="#遇到显示俩个输入法图标情况" class="headerlink" title="遇到显示俩个输入法图标情况"></a>遇到显示俩个输入法图标情况</h3><p><code>有一定原因是自启项启动了一个</code></p><h3 id="黑屏"><a href="#黑屏" class="headerlink" title="黑屏"></a>黑屏</h3><p><code>95% 是和显卡驱动有关</code></p><h3 id="Chrome-每次打开都要求输入密码"><a href="#Chrome-每次打开都要求输入密码" class="headerlink" title="Chrome 每次打开都要求输入密码"></a>Chrome 每次打开都要求输入密码</h3><p>一、删除现在的密钥环<br>  视图-&gt;根据密码环 在密码区会有一个“登录”为名字的密钥环，右击将其删除。<br>二、添加新的密钥环<br>  终端输入seahorse打开管理密钥环的软件，文件-&gt;新建-&gt;密码和密钥-&gt;输入名字(这里是以”chrome”为例)。密码设置为空</p><h3 id="添加源安装后，not-fount-XX"><a href="#添加源安装后，not-fount-XX" class="headerlink" title="添加源安装后，not fount XX"></a>添加源安装后，not fount XX</h3><p>一、 试着访问该链接<br>二、如果可以手动找到该路径，那便可以修改<code>/etc/apt/source.list.d/</code>目录下你添加的安装源文件<br><strong>例如</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/apt/sources.list.d/sogoupinyin.list</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">显示内容</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">deb http://archive.ubuntukylin.com:10006/ubuntukylin trusty main</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">可修改链接部分。</span></span><br></pre></td></tr></table></figure><h3 id="网卡驱动-Realtek-RTL8723AE-无线网卡驱动"><a href="#网卡驱动-Realtek-RTL8723AE-无线网卡驱动" class="headerlink" title="网卡驱动 Realtek RTL8723AE 无线网卡驱动"></a>网卡驱动 <code>Realtek RTL8723AE 无线网卡驱动</code></h3><p><strong>第一种</strong>(闭源驱动)：  </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install linux-firmware-nonfree</span><br></pre></td></tr></table></figure><p><strong>第二种</strong>(第三方驱动，PPA安装)：  </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo add-apt-repository ppa:hanipouspilot/rtlwifi</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install rtlwifi-new-dkms</span><br></pre></td></tr></table></figure><h3 id="当遇到产品无法输入中文的时候"><a href="#当遇到产品无法输入中文的时候" class="headerlink" title="当遇到产品无法输入中文的时候"></a>当遇到产品无法输入中文的时候</h3><p>先尝试卸载ibus，如果还是不可以试试在xxx.sh的启动脚本中添加如下：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">XMODIFIERS=&quot;@im=fcitx&quot;</span><br><span class="line">export XMODIFIERS</span><br></pre></td></tr></table></figure><p>到</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">---------------------------------------------------------------------</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Run the IDE.</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">---------------------------------------------------------------------</span></span><br></pre></td></tr></table></figure><p>之前。<br><strong>通用</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo mv /usr/bin/ibus-daemon /usr/bin/ibus-daemon.fix</span><br></pre></td></tr></table></figure><h3 id="解决LC-CTYPE-cannot-change-locale-en-US-UTF-8-错误"><a href="#解决LC-CTYPE-cannot-change-locale-en-US-UTF-8-错误" class="headerlink" title="解决LC_CTYPE: cannot change locale (en_US.UTF-8) 错误"></a>解决<code>LC_CTYPE: cannot change locale (en_US.UTF-8)</code> 错误</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">增加en_US.UTF-8</span></span><br><span class="line">locale-gen en_US.UTF-8</span><br></pre></td></tr></table></figure><h3 id="修复VMware故障，闪退"><a href="#修复VMware故障，闪退" class="headerlink" title="修复VMware故障，闪退"></a>修复<code>VMware</code>故障，闪退</h3><ol><li>下载<a href="http://cdn.hocgin.top/Uefi.priv">Uefi.priv</a>、<a href="http://cdn.hocgin.top/fix.sh">fix.sh</a>、<a href="http://cdn.hocgin.top/Uefi.der">Uefi.der</a>至于同一目录.</li><li>执行  <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh fix.sh</span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;这是一篇我对Ubuntu日常使用和优化的整理，也是一篇借鉴前人的文章，还有一些可能会遇到的疑难杂病的“偏方”，希望对你有帮助:)&lt;br&gt;&lt;strong&gt;update&lt;/strong&gt;: 新增&lt;code&gt;undistract-me&lt;/code&gt;终端命令完成提醒插件&lt;/p&gt;</summary>
    
    
    
    <category term="OS" scheme="https://hocg.in/categories/OS/"/>
    
    
    <category term="Ubuntu" scheme="https://hocg.in/tags/Ubuntu/"/>
    
    <category term="Tips" scheme="https://hocg.in/tags/Tips/"/>
    
    <category term="Gnome" scheme="https://hocg.in/tags/Gnome/"/>
    
  </entry>
  
  <entry>
    <title>hexo 使用小记</title>
    <link href="https://hocg.in/2016/03/15/hexo-%E4%BD%BF%E7%94%A8/"/>
    <id>https://hocg.in/2016/03/15/hexo-%E4%BD%BF%E7%94%A8/</id>
    <published>2016-03-15T21:31:42.000Z</published>
    <updated>2023-07-02T05:18:54.912Z</updated>
    
    <content type="html"><![CDATA[<p>  这是一篇关于如何使用hexo的收集Box <strong>&gt;</strong> 不定期更新吧！<br>  <strong>update</strong> 2017年01月12日10:33:55</p><span id="more"></span><blockquote><p>参照 <a href="https://hexo.io/zh-cn/docs/tag-plugins.html">hexo 官方文档</a><br>参照 <a href="http://theme-next.iissnan.com/theme-settings.html">next 主题</a><br>参照 <a href="https://github.com/iissnan/hexo-theme-next/wiki/%E5%88%9B%E5%BB%BA%E5%88%86%E7%B1%BB%E9%A1%B5%E9%9D%A2">next 主题 for github</a><br>参照 <a href="http://www.tuicool.com/articles/AfQnQjy/">更多扩展使用</a></p></blockquote><h2 id="md文档头部"><a href="#md文档头部" class="headerlink" title="md文档头部"></a>md文档头部</h2><table><thead><tr><th>参数</th><th>描述</th><th>默认值</th></tr></thead><tbody><tr><td>layout</td><td>布局</td><td>有哪些layout呢，请到 scaffolds 目录下查看，这些文件名称就是layout名称</td></tr><tr><td>title</td><td>标题</td><td></td></tr><tr><td>date</td><td>建立日期</td><td>文件建立日期</td></tr><tr><td>updated</td><td>更新日期</td><td>文件更新日期</td></tr><tr><td>comments</td><td>开启文章的评论功能</td><td>true</td></tr><tr><td>tags</td><td>标签（不适用于分页）</td><td></td></tr><tr><td>categories</td><td>分类（不适用于分页）</td><td></td></tr><tr><td>permalink</td><td>覆盖文章网址</td><td></td></tr><tr><td>description</td><td>添加本页描述</td><td>默认所有</td></tr><tr><td>photos</td><td>添加图片</td><td></td></tr></tbody></table><h2 id="hexo-基础命令"><a href="#hexo-基础命令" class="headerlink" title="hexo 基础命令"></a>hexo 基础命令</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">清除</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">hexo clean</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">上传 GitHub</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">hexo deploy</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建文章</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">hexo new <span class="string">&quot;postName&quot;</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建页面</span></span><br><span class="line">hexo new page &quot;pageName&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成静态页面至public目录</span></span><br><span class="line">hexo generate</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">开启预览访问端口（默认端口4000，<span class="string">&#x27;ctrl + c&#x27;</span>关闭server）</span></span><br><span class="line">hexo server</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">将.deploy目录部署到GitHub</span></span><br><span class="line">hexo deploy</span><br></pre></td></tr></table></figure><h2 id="md-扩展"><a href="#md-扩展" class="headerlink" title=".md 扩展"></a>.md 扩展</h2><ol><li><p>扩大图片宽度</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% fi image-url, alt, title %&#125;</span><br></pre></td></tr></table></figure></li><li><p>显示 更多按钮</p><figure class="highlight md"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">以上是摘要</span><br><span class="line">&lt;!--more--&gt;</span><br><span class="line">以下是余下全文</span><br></pre></td></tr></table></figure></li><li><p>使用标签别名</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% cq %&#125; 标签别名 &#123;% endcq %&#125;</span><br></pre></td></tr></table></figure></li></ol><h2 id="可能遇到的问题"><a href="#可能遇到的问题" class="headerlink" title="可能遇到的问题"></a>可能遇到的问题</h2><ol><li>当你发布的<code>.md</code>文件中携带逗号<code>,</code>(已知)，在<code>多说</code>评论插件中将无法识别评论条数(就是文章顶部那个)<blockquote><p>借鉴办法：替换文件命名，将逗号已<code>_</code>或<code> </code>分隔</p></blockquote></li></ol><h2 id="换电脑后-如何迁移？"><a href="#换电脑后-如何迁移？" class="headerlink" title="换电脑后, 如何迁移？"></a>换电脑后, 如何迁移？</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">// 为了使用hexo d来部署到git上，需要安装</span><br><span class="line">npm install hexo-deployer-git --save</span><br><span class="line">// 为了建立RSS订阅，需要安装</span><br><span class="line">npm install hexo-generator-feed --save</span><br><span class="line">// 为了建立站点地图，需要安装</span><br><span class="line">npm install hexo-generator-sitemap --save</span><br></pre></td></tr></table></figure><ul><li>可能会遇到 ‘.&#x2F;build&#x2F;Release&#x2F;DTraceProviderBindings’] code: ‘MODULE_NOT_FOUND’</li></ul><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo --no-optional</span><br></pre></td></tr></table></figure><h2 id="End"><a href="#End" class="headerlink" title="End"></a>End</h2>]]></content>
    
    
    <summary type="html">&lt;p&gt;  这是一篇关于如何使用hexo的收集Box &lt;strong&gt;&amp;gt;&lt;/strong&gt; 不定期更新吧！&lt;br&gt;  &lt;strong&gt;update&lt;/strong&gt; 2017年01月12日10:33:55&lt;/p&gt;</summary>
    
    
    
    <category term="Other" scheme="https://hocg.in/categories/Other/"/>
    
    
    <category term="Hexo" scheme="https://hocg.in/tags/Hexo/"/>
    
  </entry>
  
</feed>
