<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Clive Blog</title>
    <link>https://cliveyuan.cn</link>
    <description>博客系统,Blade框架,Clive</description>
    <language>zh-CN</language>
    <item>
      <title>JAVA基础</title>
      <link>https://cliveyuan.cn/article/87</link>
      <content:encoded>&lt;p&gt;&lt;strong&gt;什么是jvm：J&lt;/strong&gt;ava 虚拟机（JVM）是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现（Windows，Linux，macOS），目的是使用相同的字节码，它们都会给出相同的结果&lt;/p&gt; &lt;h1&gt;1.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-01.html#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%AF%B4-java-%E8%AF%AD%E8%A8%80-%E7%BC%96%E8%AF%91%E4%B8%8E%E8%A7%A3%E9%87%8A%E5%B9%B6%E5%AD%98" target="_blank"&gt;为什么说 Java 语言“编译与解释并存”？&lt;/a&gt;&lt;/h1&gt; &lt;p&gt; 编译型：&lt;a href="https://zh.wikipedia.org/wiki/%E7%B7%A8%E8%AD%AF%E8%AA%9E%E8%A8%80" target="_blank"&gt;编译型语言&lt;/a&gt;会通过&lt;a href="https://zh.wikipedia.org/wiki/%E7%B7%A8%E8%AD%AF%E5%99%A8" target="_blank"&gt;编译器&lt;/a&gt;将源代码一次性翻译成可被该平台执行的机器码。一般情况下，编译语言的执行速度比较快，开发效率比较低。&lt;/p&gt; &lt;p&gt; 解释型：&lt;a href="https://zh.wikipedia.org/wiki/%E7%9B%B4%E8%AD%AF%E8%AA%9E%E8%A8%80" target="_blank"&gt;解释型语言open in new window&lt;/a&gt;会通过&lt;a href="https://zh.wikipedia.org/wiki/%E7%9B%B4%E8%AD%AF%E5%99%A8" target="_blank"&gt;解释器open in new window&lt;/a&gt;一句一句的将代码解释（interpret）为机器代码后再执行。解释型语言开发效率比较快，执行速度比较慢。常见的解释性语言有 Python、JavaScript、PHP 等等。&lt;/p&gt; &lt;p&gt; 这是因为 Java 语言既具有编译型语言的特征，也具有解释型语言的特征。因为 Java 程序要经过先编译，后解释两个步骤，由 Java 编写的程序需要先经过编译步骤，生成字节码（&lt;code&gt;.class&lt;/code&gt; 文件），这种字节码必须由 Java 解释器来解释执行&lt;/p&gt; &lt;hr /&gt; &lt;h1&gt;2.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-01.html#aot-%E6%9C%89%E4%BB%80%E4%B9%88%E4%BC%98%E7%82%B9-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E5%85%A8%E9%83%A8%E4%BD%BF%E7%94%A8-aot-%E5%91%A2" target="_blank"&gt;AOT 有什么优点？为什么不全部使用 AOT 呢？&lt;/a&gt;&lt;/h1&gt; &lt;p&gt;JDK 9 引入了一种新的编译模式 &lt;strong&gt;AOT(Ahead of Time Compilation)&lt;/strong&gt; 。和 JIT 不同的是，这种编译模式会在程序被执行前就将其编译成机器码，属于静态编译（C、 C++，Rust，Go 等语言就是静态编译）。AOT 避免了 JIT 预热等各方面的开销，可以提高 Java 程序的启动速度，避免预热时间长。并且，AOT 还能减少内存占用和增强 Java 程序的安全性（AOT 编译后的代码不容易被反编译和修改），特别适合云原生场景。&lt;/p&gt; &lt;p&gt;缺点：AOT 编译无法支持 Java 的一些动态特性，如反射、动态代理、动态加载、JNI（Java Native Interface）等。然而，很多框架和库（如 Spring、CGLIB）都用到了这些特性。如果只使用 AOT 编译，那就没办法使用这些框架和库了，或者说需要针对性地去做适配和优化&lt;/p&gt; &lt;hr /&gt; &lt;p&gt;CGLIB 动态代理使用的是 ASM 技术，而这种技术大致原理是运行时直接在内存中生成并加载修改后的字节码文件也就是 &lt;code&gt;.class&lt;/code&gt; 文件，如果全部使用 AOT 提前编译，也就不能使用 ASM 技术了。为了支持类似的动态特性，所以选择使用 JIT 即时编译器。&lt;/p&gt; &lt;h1&gt;3.基本数据类型大小&lt;/h1&gt; &lt;p&gt;byte:1字节&lt;/p&gt; &lt;p&gt;short:2字节&lt;/p&gt; &lt;p&gt;int:4字节&lt;/p&gt; &lt;p&gt;long:8字节&lt;/p&gt; &lt;p&gt;char:2字节&lt;/p&gt; &lt;p&gt;float:4字节&lt;/p&gt; &lt;p&gt;double:8字节 &lt;/p&gt; &lt;p&gt;&lt;code&gt;Byte&lt;/code&gt;,&lt;code&gt;Short&lt;/code&gt;,&lt;code&gt;Integer&lt;/code&gt;,&lt;code&gt;Long&lt;/code&gt; 这 4 种包装类默认创建了数值 &lt;strong&gt;[-128，127]&lt;/strong&gt; 的相应类型的缓存数据，&lt;code&gt;Character&lt;/code&gt; 创建了数值在 &lt;strong&gt;[0,127]&lt;/strong&gt; 范围的缓存数据，&lt;code&gt;Boolean&lt;/code&gt; 直接返回 &lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt;。&lt;/p&gt; &lt;hr /&gt; &lt;p&gt;&lt;strong&gt;为什么说是几乎所有对象实例都存在于堆中呢？&lt;/strong&gt; 这是因为 HotSpot 虚拟机引入了 JIT 优化之后，会对对象进行逃逸分析，如果发现某一个对象并没有逃逸到方法外部，那么就可能通过标量替换来实现栈上分配，而避免堆上分配内存&lt;/p&gt; &lt;h1&gt;4.字符型常量和字符串常量的区别?&lt;/h1&gt; &lt;ol&gt; &lt;li&gt;形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的 0 个或若干个字符&lt;/li&gt; &lt;li&gt;含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)&lt;/li&gt; &lt;li&gt;占内存大小 字符常量只占 2 个字节; 字符串常量占若干个字节 (注意： char 在 Java 中占两个字节)&lt;/li&gt; &lt;/ol&gt; &lt;h1&gt;5.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-02.html#%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%9B%B8%E7%AD%89%E5%92%8C%E5%BC%95%E7%94%A8%E7%9B%B8%E7%AD%89%E7%9A%84%E5%8C%BA%E5%88%AB" target="_blank"&gt;对象的相等和引用相等的区别&lt;/a&gt;&lt;/h1&gt; &lt;ul&gt; &lt;li&gt;对象的相等一般比较的是内存中存放的内容是否相等。&lt;/li&gt; &lt;li&gt;引用相等一般比较的是他们指向的内存地址是否相等。&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;6.深拷贝 vs 浅拷贝vs引用拷贝&lt;/h1&gt; &lt;ol&gt; &lt;li&gt;浅拷贝：对基本数据类型进行值传递，对引用数据类型进行引用传递般的拷贝，此为浅拷贝。&lt;/li&gt; &lt;li&gt;深拷贝：对基本数据类型进行值传递，对引用数据类型，创建一个新的对象，并复制其内容，此为深拷贝。&lt;/li&gt; &lt;li&gt;引用拷贝：简单来说，引用拷贝就是两个不同的引用指向同一个对象。&lt;/li&gt; &lt;li&gt;==clone接口实现：浅克隆：创建新的引用地址，基本数据类型值传递，引用数据类型引用传递==&lt;/li&gt; &lt;/ol&gt; &lt;h1&gt;7.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-02.html#object-%E7%B1%BB%E7%9A%84%E5%B8%B8%E8%A7%81%E6%96%B9%E6%B3%95%E6%9C%89%E5%93%AA%E4%BA%9B" target="_blank"&gt;Object 类的常见方法有哪些？&lt;/a&gt;&lt;/h1&gt; &lt;p&gt;getClass,clone,equals,hashCode,wait,join,toString,notify,notifyAll,finalize(实例被垃圾回收器回收的时候触发的操作)&lt;/p&gt; &lt;h1&gt;8.Java 序列化中如果有些字段不想进行序列化，怎么办？&lt;/h1&gt; &lt;p&gt;用关键字transient:阻止实例中那些用此关键字修饰的的变量序列化；当对象被反序列化时，被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量，不能修饰类和方法。&lt;/p&gt; &lt;h1&gt;9.s&lt;code&gt;tring&lt;/code&gt; 的底层实现由 &lt;code&gt;char[]&lt;/code&gt; 改成了 &lt;code&gt;byte[]&lt;/code&gt; ?&lt;/h1&gt; &lt;p&gt;&lt;strong&gt;Java 9 为何要将 &lt;code&gt;String&lt;/code&gt; 的底层实现由 &lt;code&gt;char[]&lt;/code&gt; 改成了 &lt;code&gt;byte[]&lt;/code&gt; ?  编码占位问题&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;新版的 String 其实支持两个编码方案：Latin-1 和 UTF-16。&lt;/p&gt; &lt;h1&gt;10.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-02.html#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%E6%B1%A0%E7%9A%84%E4%BD%9C%E7%94%A8%E4%BA%86%E8%A7%A3%E5%90%97" target="_blank"&gt;字符串常量池的作用了解吗？&lt;/a&gt;&lt;/h1&gt; &lt;p&gt;&lt;strong&gt;字符串常量池&lt;/strong&gt; 是 JVM 为了提升性能和减少内存消耗针对字符串（String 类）专门开辟的一块区域，主要目的是为了避免字符串的重复创建。&lt;/p&gt; &lt;h1&gt;11.字符型常量和字符串常量的区别?&lt;/h1&gt; &lt;ol&gt; &lt;li&gt;形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的 0 个或若干个字符&lt;/li&gt; &lt;li&gt;含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)&lt;/li&gt; &lt;li&gt;占内存大小 字符常量只占 2 个字节; 字符串常量占若干个字节 (注意： char 在 Java 中占两个字节),&lt;/li&gt; &lt;/ol&gt; &lt;h1&gt;12.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-02.html#string-intern-%E6%96%B9%E6%B3%95%E6%9C%89%E4%BB%80%E4%B9%88%E4%BD%9C%E7%94%A8" target="_blank"&gt;String#intern 方法有什么作用?&lt;/a&gt;&lt;/h1&gt; &lt;p&gt;&lt;code&gt;String.intern()&lt;/code&gt; 是一个 native（本地）方法，其作用是将指定的字符串对象的引用保存在字符串常量池中，可以简单分为两种情况：&lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;p&gt;如果字符串常量池中保存了对应的字符串对象的引用，就直接返回该引用。&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;如果字符串常量池中没有保存了对应的字符串对象的引用，那就在常量池中创建一个指向该字符串对象的引用并返回。&lt;/p&gt; &lt;pre&gt;&lt;code class="language-java"&gt;*   // 在堆中创建字符串对象”Java“     // 将字符串对象”Java“的引用保存在字符串常量池中     String s1 = &amp;quot;Java&amp;quot;;     // 直接返回字符串常量池中字符串对象”Java“对应的引用     String s2 = s1.intern();     // 会在堆中在单独创建一个字符串对象     String s3 = new String(&amp;quot;Java&amp;quot;);     // 直接返回字符串常量池中字符串对象”Java“对应的引用     String s4 = s3.intern();     // s1 和 s2 指向的是堆中的同一个对象     System.out.println(s1 == s2); // true     // s3 和 s4 指向的是堆中不同的对象     System.out.println(s3 == s4); // false     // s1 和 s4 指向的是堆中的同一个对象     System.out.println(s1 == s4); //true &lt;/code&gt;&lt;/pre&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;13.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-03.html#exception-%E5%92%8C-error-%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB" target="_blank"&gt;Exception 和 Error 有什么区别？&lt;/a&gt;&lt;/h1&gt; &lt;p&gt;所有的异常都有一个共同的祖先 &lt;code&gt;java.lang&lt;/code&gt; 包中的 &lt;code&gt;Throwable&lt;/code&gt; 类。&lt;code&gt;Throwable&lt;/code&gt; 类有两个重要的子类:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;&lt;code&gt;Exception&lt;/code&gt;&lt;/strong&gt; :程序本身可以处理的异常，可以通过 &lt;code&gt;catch&lt;/code&gt; 来进行捕获。&lt;code&gt;Exception&lt;/code&gt; 又可以分为 Checked Exception (受检查异常，必须处理) 和 Unchecked Exception (不受检查异常，可以不处理)。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;&lt;code&gt;Error&lt;/code&gt;&lt;/strong&gt;：&lt;code&gt;Error&lt;/code&gt; 属于程序无法处理的错误 ，我们没办法通过 &lt;code&gt;catch&lt;/code&gt; 来进行捕获不建议通过&lt;code&gt;catch&lt;/code&gt;捕获 。例如 Java 虚拟机运行错误（&lt;code&gt;Virtual MachineError&lt;/code&gt;）、虚拟机内存不够错误(&lt;code&gt;OutOfMemoryError&lt;/code&gt;)、类定义错误（&lt;code&gt;NoClassDefFoundError&lt;/code&gt;）等 。这些异常发生时，Java 虚拟机（JVM）一般会选择线程终止。&lt;/li&gt; &lt;/ul&gt; &lt;hr /&gt; &lt;h3&gt;&lt;a href="#checked-exception-和-unchecked-exception-有什么区别" target="_blank"&gt;Checked Exception 和 Unchecked Exception 有什么区别？&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;&lt;strong&gt;Checked Exception&lt;/strong&gt; 即 受检查异常 ，Java 代码在编译过程中，如果受检查异常没有被 &lt;code&gt;catch&lt;/code&gt;或者&lt;code&gt;throws&lt;/code&gt; 关键字处理的话，就没办法通过编译。&lt;/p&gt; &lt;hr /&gt; &lt;h1&gt;14.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-03.html#finally-%E4%B8%AD%E7%9A%84%E4%BB%A3%E7%A0%81%E4%B8%80%E5%AE%9A%E4%BC%9A%E6%89%A7%E8%A1%8C%E5%90%97" target="_blank"&gt;finally 中的代码一定会执行吗？&lt;/a&gt;&lt;/h1&gt; &lt;p&gt;不一定的！在某些情况下，finally 中的代码不会被执行。&lt;/p&gt; &lt;p&gt;就比如说 finally 之前虚拟机被终止运行的话，finally 中的代码就不会被执行。&lt;/p&gt; &lt;ol&gt; &lt;li&gt;程序所在的线程死亡。&lt;/li&gt; &lt;li&gt;关闭 CPU。&lt;/li&gt; &lt;/ol&gt; &lt;h1&gt;15.泛型&lt;/h1&gt; &lt;p&gt;&lt;strong&gt;Java 泛型（generics）是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制，该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型，也就是说所操作的数据类型被指定为一个参数。&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;什么是泛型：泛型的本质就是参数化类型。也就是，将一个数据类型指定为参数。&lt;/p&gt; &lt;p&gt;泛型擦除： 泛型信息只存在于代码编译阶段，在进入 JVM 之前，与泛型相关的信息会被擦除掉，专业术语叫做类型擦除。&lt;/p&gt; &lt;p&gt;引入泛型有什么好处呢？&lt;/p&gt; &lt;h1&gt;16.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-03.html#spi" target="_blank"&gt;SPI&lt;/a&gt;机制&lt;/h1&gt; &lt;p&gt;&lt;strong&gt;专门提供给服务提供者或者扩展框架功能的开发者去使用的一个接口。&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;很多框架都使用了 Java 的 SPI 机制，比如：Spring 框架、数据库加载驱动、日志接口、以及 Dubbo 的扩展实现等等。&lt;/p&gt; &lt;h3&gt;&lt;a href="#spi-的优缺点" target="_blank"&gt;SPI 的优缺点？&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;通过 SPI 机制能够大大地提高接口设计的灵活性，但是 SPI 机制也存在一些缺点，比如：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;需要遍历加载所有的实现类，不能做到按需加载，这样效率还是相对较低的。&lt;/li&gt; &lt;li&gt;当多个 &lt;code&gt;ServiceLoader&lt;/code&gt; 同时 &lt;code&gt;load&lt;/code&gt; 时，会有并发问题。&lt;/li&gt; &lt;/ul&gt; &lt;hr /&gt; &lt;h1&gt;17.序列号&amp;amp;反序列化&lt;/h1&gt; &lt;p&gt;&lt;strong&gt;序列化的主要目的是通过网络传输对象或者说是将对象存储到文件系统、数据库、内存中。&lt;/strong&gt;&lt;/p&gt; &lt;h2&gt;（1）&lt;code&gt;serialVersionUID&lt;/code&gt;&lt;/h2&gt; &lt;p&gt;序列化号 &lt;code&gt;serialVersionUID&lt;/code&gt; 属于版本控制的作用。反序列化时，会检查 &lt;code&gt;serialVersionUID&lt;/code&gt; 是否和当前类的 &lt;code&gt;serialVersionUID&lt;/code&gt; 一致。如果 &lt;code&gt;serialVersionUID&lt;/code&gt; 不一致则会抛出 &lt;code&gt;InvalidClassException&lt;/code&gt; 异常。&lt;/p&gt; &lt;p&gt;推荐每个序列化类都手动指定其 &lt;code&gt;serialVersionUID&lt;/code&gt;，如果不手动指定，那么编译器会动态生成默认的 &lt;code&gt;serialVersionUID&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;serialVersionUID 不是被 static 变量修饰了吗？为什么还会被“序列化”？&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;static&lt;/code&gt; 修饰的变量是静态变量，属于类而非类的实例，本身是不会被序列化的。然而，&lt;code&gt;serialVersionUID&lt;/code&gt; 是一个特例，&lt;code&gt;serialVersionUID&lt;/code&gt; 的序列化做了特殊处理。当一个对象被序列化时，&lt;code&gt;serialVersionUID&lt;/code&gt; 会被写入到序列化的二进制流中；在反序列化时，也会解析它并做一致性判断，以此来验证序列化对象的版本一致性。如果两者不匹配，反序列化过程将抛出 &lt;code&gt;InvalidClassException&lt;/code&gt;，因为这通常意味着序列化的类的定义已经发生了更改，可能不再兼容。&lt;/p&gt; &lt;hr /&gt; &lt;p&gt;也就是说，&lt;code&gt;serialVersionUID&lt;/code&gt; 只是用来被 JVM 识别，实际并没有被序列化。&lt;/p&gt; &lt;h2&gt;&lt;strong&gt;（2）如果有些字段不想进行序列化怎么办？&lt;/strong&gt;&lt;/h2&gt; &lt;p&gt;对于不想进行序列化的变量，可以使用 &lt;code&gt;transient&lt;/code&gt; 关键字修饰。&lt;/p&gt; &lt;p&gt;&lt;code&gt;transient&lt;/code&gt; 关键字的作用是：阻止实例中那些用此关键字修饰的的变量序列化；当对象被反序列化时，被 &lt;code&gt;transient&lt;/code&gt; 修饰的变量值不会被持久化和恢复。&lt;/p&gt; &lt;p&gt;关于 &lt;code&gt;transient&lt;/code&gt; 还有几点注意：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;transient&lt;/code&gt; 只能修饰变量，不能修饰类和方法。&lt;/li&gt; &lt;li&gt;&lt;code&gt;transient&lt;/code&gt; 修饰的变量，在反序列化后变量值将会被置成类型的默认值。例如，如果是修饰 &lt;code&gt;int&lt;/code&gt; 类型，那么反序列后结果就是 &lt;code&gt;0&lt;/code&gt;。&lt;/li&gt; &lt;li&gt;&lt;code&gt;static&lt;/code&gt; 变量因为不属于任何对象(Object)，所以无论有没有 &lt;code&gt;transient&lt;/code&gt; 关键字修饰，均不会被序列化。&lt;/li&gt; &lt;/ul&gt; &lt;hr /&gt; &lt;p&gt;&lt;strong&gt;为什么不推荐使用 JDK 自带的序列化？不支持跨语言调用；性能差；存在安全问题；&lt;/strong&gt;&lt;/p&gt; &lt;h1&gt;18.IO流&lt;/h1&gt; &lt;p&gt;IO 即 &lt;code&gt;Input/Output&lt;/code&gt;，输入和输出。数据输入到计算机内存的过程即输入，反之输出到外部存储（比如数据库，文件，远程主机）的过程即输出&lt;/p&gt; &lt;h2&gt;1.&lt;a href="https://javaguide.cn/java/basis/java-basic-questions-03.html#i-o-%E6%B5%81%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E4%B8%BA%E5%AD%97%E8%8A%82%E6%B5%81%E5%92%8C%E5%AD%97%E7%AC%A6%E6%B5%81%E5%91%A2" target="_blank"&gt;I/O 流为什么要分为字节流和字符流呢?&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;问题本质想问：&lt;strong&gt;不管是文件读写还是网络发送接收，信息的最小存储单元都是字节，那为什么 I/O 流操作要分为字节流操作和字符流操作呢？&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;字符流是由 Java 虚拟机将字节转换得到的，这个过程还算是比较耗时；&lt;/li&gt; &lt;li&gt;如果我们不知道编码类型的话，使用字节流的过程中很容易出现乱码问题&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;19.java的Unsafe类&lt;/h1&gt; &lt;h1&gt;20.创建对象的三个步骤&lt;/h1&gt; &lt;p&gt; 1.类加载检查 &lt;/p&gt; &lt;p&gt; 2.分配内存空间&lt;/p&gt; &lt;p&gt; 3.类的初始化&lt;/p&gt; &lt;p&gt; 4.设置对象头&lt;/p&gt; &lt;p&gt; 5.执行init方式  &lt;/p&gt; &lt;h1&gt;21.成员变量与局部变量的区别有哪些？&lt;/h1&gt; &lt;ol&gt; &lt;li&gt;从语法形式上看:成员变量是属于类的，而局部变量是在代码块或方法中定义的变量或是方法的参数；成员变量可以被 public,private,static 等修饰符所修饰，而局部变量不能被访问控制修饰符及 static 所修饰；但是，成员变量和局部变量都能被 final 所修饰。&lt;/li&gt; &lt;li&gt;从变量在内存中的存储方式来看:如果成员变量是使用static修饰的，那么这个成员变量是属于类的，如果没有使用static修饰，这个成员变量是属于实例的。而对象存在于堆内存，局部变量则存在于栈内存。&lt;/li&gt; &lt;li&gt;从变量在内存中的生存时间上看:成员变量是对象的一部分，它随着对象的创建而存在，而局部变量随着方法的调用而自动消失。&lt;/li&gt; &lt;li&gt;成员变量如果没有被赋初值:则会自动以类型的默认值而赋值（一种情况例外:被 final 修饰的成员变量也必须显式地赋值），而局部变量则不会自动赋值。&lt;/li&gt; &lt;/ol&gt; &lt;h1&gt;22.面向对象和面向过程的区别&lt;/h1&gt; &lt;p&gt;面向过程性能比面向对象高，是因为java属于半编译型语言，不是cpu可以直接运行的语言&lt;/p&gt; &lt;p&gt;面向对象 ：面向对象易维护、易复用、易扩展。&lt;/p&gt; &lt;h1&gt;23.==和 equals 的区别&lt;/h1&gt; &lt;ul&gt; &lt;li&gt;==比较的是内存地址，基本数据则是值，equals比较的是引用对象的值&lt;/li&gt; &lt;li&gt;equals 没有被重写时等价于“==”，比较对象。&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;24、为什么 Java 中只有值传递？&lt;/h1&gt; &lt;p&gt;Java 程序设计语言对对象采用的不是引用调用，实际上，对象引用是按 值传递的。&lt;/p&gt;</content:encoded>
      <pubDate>Thu, 12 Sep 2024 06:10:00 GMT</pubDate>
    </item>
    <item>
      <title>【转】解决Jenkins用shell脚本部署后，jar包启动失败的问题</title>
      <link>https://cliveyuan.cn/article/86</link>
      <content:encoded>&lt;p&gt;原文：&lt;a href="https://blog.csdn.net/fenduo/article/details/114937832"&gt;https://blog.csdn.net/fenduo/article/details/114937832&lt;/a&gt;&lt;a href="https://blog.csdn.net/fenduo/article/details/114937832"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;使用root账号登录，在本地执行.sh脚本文件没有任何问题。&lt;/p&gt;&lt;p&gt;但是jenkins部署时死活不行，并且错误很奇怪，只有kill进程和拷jar包成功了。。。起服务就是起不来。&lt;/p&gt;&lt;p&gt;产生原因：&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;shell脚本发布时，会衍生进程，Jenkins默认会自动杀掉衍生进程&lt;/font&gt;&lt;/p&gt;&lt;p&gt;解决方案1：&lt;/p&gt;&lt;p&gt;在执行shell脚本前，加个build_ID参数即可&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;BUILD_ID=DONTKILLME&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;解决方案2： 执行的脚本中加这一段也可以&lt;/p&gt;&lt;p&gt; ```&lt;/p&gt;&lt;p&gt;#项目jar包名称&lt;/p&gt;&lt;p&gt;APP_NAME=smcc-0.0.1-SNAPSHOT.jar&lt;/p&gt;&lt;p&gt;#重启命令&lt;/p&gt;&lt;p&gt;pid=`ps -ef | grep $APP_NAME | grep -v grep |awk '{print $2}'`&lt;/p&gt;&lt;p&gt;if [ $pid ]; then&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; echo :App&amp;nbsp; is&amp;nbsp; running pid=$pid&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; kill -9 $pid&lt;/p&gt;&lt;p&gt;fi&lt;/p&gt;&lt;p&gt;BUILD_ID=DONTKILLME&lt;/p&gt;&lt;p&gt;nohup java -jar $APP_NAME&amp;gt; sm.log 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/p&gt;&lt;p&gt;```&lt;/p&gt;</content:encoded>
      <pubDate>Fri, 05 Jan 2024 07:02:00 GMT</pubDate>
    </item>
    <item>
      <title>2023届·1024闯关赢大奖-攻略</title>
      <link>https://cliveyuan.cn/article/85</link>
      <content:encoded>&lt;p&gt;&lt;img style="width: 750px;" src="https://cliveyuan.cn/upload/2023/10/0ojns7d8qshfqq6rg095ktf582.jpg"&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;活动地址：&lt;a href="http://1024.cliveyuan.cn/"&gt;http://1024.cliveyuan.cn/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;攻略视频：&lt;/p&gt;&lt;p&gt;&lt;video controls="" src="https://file.youmizuan.com/download/1024.mp4" width="640" height="360" class="note-video-clip"&gt;&lt;/video&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 25 Oct 2023 02:33:00 GMT</pubDate>
    </item>
    <item>
      <title>SpringBoot中使用策略模式优雅干掉if-else</title>
      <link>https://cliveyuan.cn/article/84</link>
      <content:encoded>&lt;h1&gt;前言&lt;/h1&gt; &lt;p&gt;在阅读了一篇微信公众号文章&lt;a href="https://mp.weixin.qq.com/s/DPNpKGM4GT6iPNFE_cKS4Q" target="_blank"&gt;《用设计模式干掉 if-else，太优雅了！》&lt;/a&gt;后，考虑到在SpringBoot项目中真实使用时，策略是IoC管理的而不是每次都由工厂创建，所以按自己的思路实现了一版比较简单的方案。&lt;/p&gt; &lt;h1&gt;代码&lt;/h1&gt; &lt;h2&gt;代码清单&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;TypeEnum.java // 类型枚举类 ReceiptReq.java // 接口请求入参 ReceiptHandleStrategy.java // 接口 DefaultReceiptHandleStrategy.java // 默认接口实现 MT1101ReceiptHandleStrategy.java // MT1101类型对应的接口实现 Mt2101ReceiptHandleStrategy.java // MT2101类型对应的接口实现 ReceiptStrategyTest.java // 测试类 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;枚举类&lt;code&gt;TypeEnum.java&lt;/code&gt;&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;package cn.cliveyuan.learn.test.strategy;  /**  * @author Clive Yuan  * @date 2023-10-20 16:32  */ public enum TypeEnum {     MT1101, MT2101, MT4101, MT8104, MT8105, MT9999 } &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;接口请求入参类&lt;code&gt;ReceiptReq.java&lt;/code&gt;&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;package cn.cliveyuan.learn.test.strategy;  import lombok.Data;  /**  * @author Clive Yuan  * @date 2023-10-20 16:32  */ @Data public class ReceiptReq {     private TypeEnum typeEnum;     private String data; } &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;接口类&lt;code&gt;ReceiptHandleStrategy.java&lt;/code&gt;&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;package cn.cliveyuan.learn.test.strategy;  /**  * @author Clive Yuan  * @date 2023-10-20 16:33  */ public interface ReceiptHandleStrategy {      /**      * 获取类型枚举 (每个类型实现类中指定)      */     TypeEnum getType();      /**      * 处理业务逻辑      */     void handleReceipt(ReceiptReq receipt); }  &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;默认接口实现类&lt;code&gt;DefaultReceiptHandleStrategy.java&lt;/code&gt;&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;package cn.cliveyuan.learn.test.strategy;  import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component;  import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects;  /**  * @author Clive Yuan  * @date 2023-10-20 16:34  */ @Component @Primary // 默认实现 public class DefaultReceiptHandleStrategy implements ReceiptHandleStrategy {     /**      * 从IoC容器中获取所有实现了ReceiptHandleStrategy接口的Bean      */     @Resource     private List&amp;lt;ReceiptHandleStrategy&amp;gt; receiptHandleStrategyList;     /**      * 定义一个静态Map用于存储类型枚举对应的实现      */     private static final Map&amp;lt;TypeEnum, ReceiptHandleStrategy&amp;gt; STRATEGY_MAP = new HashMap&amp;lt;&amp;gt;();      /**      * 初始化      * 遍历所有接口实现类,获取其类型并存入Map中      */     @PostConstruct     public void init() {         for (ReceiptHandleStrategy receiptHandleStrategy : receiptHandleStrategyList) {             // 跳过type为空的实现类,即当前默认实现类DefaultReceiptHandleStrategy             if (Objects.isNull(receiptHandleStrategy.getType())) continue;             STRATEGY_MAP.put(receiptHandleStrategy.getType(), receiptHandleStrategy);         }     }      @Override     public TypeEnum getType() {         // 当前为默认实现,这个类型不必填写         return null;     }      @Override     public void handleReceipt(ReceiptReq receipt) {         // 从Map中获取对应类型的实现类         ReceiptHandleStrategy receiptHandleStrategy = STRATEGY_MAP.get(receipt.getTypeEnum());         // 判断是否为空         if (Objects.isNull(receiptHandleStrategy)) {             throw new RuntimeException(&amp;quot;Not support this type:&amp;quot; + receipt.getTypeEnum());         }         // 调用对应接口         receiptHandleStrategy.handleReceipt(receipt);     } }  &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;MT1101类型对应的接口实现类&lt;code&gt;MT1101ReceiptHandleStrategy.java&lt;/code&gt;&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;package cn.cliveyuan.learn.test.strategy;  import org.springframework.stereotype.Component;  /**  * @author Clive Yuan  * @date 2023-10-20 16:34  */ @Component public class MT1101ReceiptHandleStrategy implements ReceiptHandleStrategy {     @Override     public TypeEnum getType() {         // 填写对应的类型枚举         return TypeEnum.MT1101;     }      @Override     public void handleReceipt(ReceiptReq receipt) {         // 处理对应的业务场景         System.out.println(&amp;quot;解析报文MT1101:&amp;quot; + receipt.getData());     } }  &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;MT2101类型对应的接口实现类&lt;code&gt;Mt2101ReceiptHandleStrategy.java&lt;/code&gt;&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;package cn.cliveyuan.learn.test.strategy;  import org.springframework.stereotype.Component;  /**  * @author Clive Yuan  * @date 2023-10-20 16:34  */ @Component public class Mt2101ReceiptHandleStrategy implements ReceiptHandleStrategy {     @Override     public TypeEnum getType() {         // 填写对应的类型枚举         return TypeEnum.MT2101;     }      @Override     public void handleReceipt(ReceiptReq receipt) {         // 处理对应的业务场景         System.out.println(&amp;quot;解析报文MT2101:&amp;quot; + receipt.getData());     } }  &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;测试类&lt;code&gt;ReceiptStrategyTest.java&lt;/code&gt;&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;package cn.cliveyuan.learn.test.strategy;  import cn.cliveyuan.learn.test.BaseTest; import org.junit.Test;  import javax.annotation.Resource;  /**  * @author Clive Yuan  * @date 2023-10-20 16:36  */ public class ReceiptStrategyTest extends BaseTest {     @Resource     private ReceiptHandleStrategy receiptHandleStrategy;      @Test     public void test_01() {         ReceiptReq receipt = new ReceiptReq();         receipt.setTypeEnum(TypeEnum.MT1101);         receipt.setData(&amp;quot;Hi, MT1101&amp;quot;);         receiptHandleStrategy.handleReceipt(receipt);     }     @Test     public void test_02() {         ReceiptReq receipt = new ReceiptReq();         receipt.setTypeEnum(TypeEnum.MT2101);         receipt.setData(&amp;quot;Hi, MT2101&amp;quot;);         receiptHandleStrategy.handleReceipt(receipt);     }     @Test     public void test_03() {         ReceiptReq receipt = new ReceiptReq();         receipt.setTypeEnum(TypeEnum.MT4101);         receipt.setData(&amp;quot;Hi, MT4101&amp;quot;);         receiptHandleStrategy.handleReceipt(receipt);     } }  &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;基础测试类&lt;code&gt;BaseTest.java&lt;/code&gt;&lt;/h2&gt; &lt;pre&gt;&lt;code class="language-java"&gt;package cn.cliveyuan.learn.test;   /**  * 基本测试  * @author Clive Yuan  * @date 2023-10-20 16:36  */  import cn.cliveyuan.learn.Application; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = Application.class) public class BaseTest { }  &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;测试结果&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;test_01: 解析报文MT1101:Hi, MT1101 test_02: 解析报文MT2101:Hi, MT2101 test_03: java.lang.RuntimeException: Not support this type:MT4101 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;扩展性&lt;/h1&gt; &lt;p&gt;如果要新加一个处理类型，只需2步：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;在类型枚举&lt;code&gt;TypeEnum.java&lt;/code&gt;中新增枚举值&lt;/li&gt; &lt;li&gt;新增一个接口&lt;code&gt;ReceiptHandleStrategy&lt;/code&gt;的实现，并填写对应的类型枚举&lt;/li&gt; &lt;/ol&gt; &lt;h1&gt;结语&lt;/h1&gt; &lt;p&gt;&lt;code&gt;ReceiptHandleStrategy&lt;/code&gt;接口调用时只需要依赖这个接口即可，因为默认实现加了&lt;code&gt;@Primary&lt;/code&gt;注解就会默认调用这个实现处理，并根据类型枚举路由到对应的实现，在实现的类里面就可以方便地依赖其他Bean做业务处理了。 你对这种方式有什么看法呢？ 评论区见^_^&lt;/p&gt; &lt;p&gt;@Author: Clive 博客地址：&lt;a href="https://cliveyuan.cn/" target="_blank"&gt;cliveyuan.cn&lt;/a&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Fri, 20 Oct 2023 08:49:00 GMT</pubDate>
    </item>
    <item>
      <title>【转】一文教你搞定所有前端鉴权与后端鉴权方案，让你不再迷惘</title>
      <link>https://cliveyuan.cn/article/83</link>
      <content:encoded>&lt;p&gt;原文地址：&lt;a href="https://juejin.cn/post/7129298214959710244"&gt;https://juejin.cn/post/7129298214959710244&lt;/a&gt;&lt;a href="https://juejin.cn/post/7129298214959710244"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;h1 data-id="heading-0"&gt;前言&lt;/h1&gt; &lt;p&gt;大家好，我是&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fjeddygong" target="_blank" title="https://github.com/jeddygong" ref="nofollow noopener noreferrer"&gt;易师傅&lt;/a&gt;，还记得之前在面试的时候，有一位面试官就问了，关于前端鉴权这块，&lt;code&gt;Token、Cookie、Session、JWT、单点登录&lt;/code&gt;是什么？有什么作用？你一般是怎么做的？以及你是怎么存储的呢？那你又是怎么保证 &lt;code&gt;它&lt;/code&gt; 的安全的呢？&lt;/p&gt; &lt;p&gt;一顿连问下来，我是焦头又烂额，欲言而又止.......&lt;/p&gt; &lt;p&gt;其实鉴权的方法有很多，下面我总结了常用的 &lt;code&gt;10种鉴权方法&lt;/code&gt;，那么哪一种是最适合你的系统呢？哪一种又最安全呢？&lt;/p&gt; &lt;p&gt;那就让我们从下文慢慢探索寻找答案吧 ~&lt;/p&gt; &lt;h1 data-id="heading-1"&gt;通过这篇文章你将学到什么？&lt;/h1&gt; &lt;p&gt;&lt;img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/22d959e4f1cd4cda8af6debbc030f65c~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="前端鉴权的副本.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;p&gt;在介绍鉴权方法之前，我们先要了解的是：&lt;code&gt;什么是认证、授权、鉴权、权限控制&lt;/code&gt;以及他们之间的关系，有了他们做铺垫，那么我们才能做到从始至终的了解透彻 ~&lt;/p&gt; &lt;h1 data-id="heading-2"&gt;什么是认证？&lt;/h1&gt; &lt;p&gt;&lt;code&gt;认证(Identification)&lt;/code&gt; 是指根据声明者所特有的识别信息，确认声明者的身份。&lt;/p&gt; &lt;p&gt;白话文的意思就是：&lt;code&gt;你需要用身份证证明你自己是你自己&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;比如我们常见的认证技术：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;身份证&lt;/li&gt; &lt;li&gt;用户名和密码&lt;/li&gt; &lt;li&gt;用户手机：手机短信、手机二维码扫描、手势密码&lt;/li&gt; &lt;li&gt;用户的电子邮箱&lt;/li&gt; &lt;li&gt;用户的生物学特征：指纹、语音、眼睛虹膜&lt;/li&gt; &lt;li&gt;用户的大数据识别&lt;/li&gt; &lt;li&gt;等等&lt;/li&gt; &lt;/ul&gt; &lt;h1 data-id="heading-3"&gt;什么是授权？&lt;/h1&gt; &lt;p&gt;&lt;code&gt;授权(Authorization)&lt;/code&gt;： 在信息安全领域是指&lt;code&gt;资源所有者&lt;/code&gt;委派&lt;code&gt;执行者&lt;/code&gt;，赋予&lt;code&gt;执行者&lt;/code&gt;指定范围的资源操作权限，以便对资源的相关操作。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;在现实生活领域例如：&lt;/strong&gt; 银行卡（由银行派发）、门禁卡（由物业管理处派发）、钥匙（由房东派发），这些都是现实生活中授权的实现方式。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;在互联网领域例如：&lt;/strong&gt; web 服务器的 session 机制、web 浏览器的 cookie 机制、颁发授权令牌（token）等都是一个授权的机制。&lt;/p&gt; &lt;h1 data-id="heading-4"&gt;什么是鉴权？&lt;/h1&gt; &lt;p&gt;&lt;code&gt;鉴权(Authentication)&lt;/code&gt; 在信息安全领域是指&lt;strong&gt;对于一个声明者所声明的身份权利，对其所声明的真实性进行鉴别确认的过程&lt;/strong&gt;。&lt;/p&gt; &lt;p&gt;若从授权出发，则会更加容易理解鉴权。授权和鉴权是两个上下游相匹配的关系，&lt;strong&gt;先授权，后鉴权&lt;/strong&gt;。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;在现实生活领域：&lt;/strong&gt; 门禁卡需要通过门禁卡识别器，银行卡需要通过银行卡识别器；&lt;/p&gt; &lt;p&gt;&lt;strong&gt;在互联网领域：&lt;/strong&gt; 校验 session/cookie/token 的合法性和有效性&lt;/p&gt; &lt;p&gt;&lt;code&gt;鉴权&lt;/code&gt; 是一个承上启下的一个环节，上游它接受授权的输出，校验其真实性后，然后获取权限（permission），这个将会为下一步的权限控制做好准备。&lt;/p&gt; &lt;h1 data-id="heading-5"&gt;什么是权限控制？&lt;/h1&gt; &lt;p&gt;&lt;code&gt;权限控制(Access/Permission Control)&lt;/code&gt; 将可执行的操作定义为权限列表，然后判断操作是否允许/禁止&lt;/p&gt; &lt;p&gt;对于权限控制，可以分为两部分进行理解：一个是权限，另一个是控制。权限是抽象的逻辑概念，而控制是具体的实现方式。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;在现实生活领域中：&lt;/strong&gt; 以门禁卡的权限实现为例，一个门禁卡，拥有开公司所有的门的权限；一个门禁卡，拥有管理员角色的权限，因而可以开公司所有的门。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;在互联网领域：&lt;/strong&gt; 通过 web 后端服务，来控制接口访问，允许或拒绝访问请求。&lt;/p&gt; &lt;h1 data-id="heading-6"&gt;认证、授权、鉴权和权限控制的关系？&lt;/h1&gt; &lt;p&gt;看到这里，我们应该明白了&lt;code&gt;认证&lt;/code&gt;、&lt;code&gt;授权&lt;/code&gt;、&lt;code&gt;鉴权&lt;/code&gt;和&lt;code&gt;权限控制&lt;/code&gt;这四个环节是一个&lt;code&gt;前后依次发生&lt;/code&gt;、&lt;code&gt;上下游&lt;/code&gt;的关系;&lt;/p&gt; &lt;p&gt;&lt;img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/05c04ab8635340eab46f98585527c79d~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="前端鉴权 1.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;p&gt;需要说明的是，这四个环节在有些时候会同时发生。 例如在下面的几个场景：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;使用门禁卡开门：&lt;/strong&gt; 认证、授权、鉴权、权限控制四个环节一气呵成，在瞬间同时发生&lt;/li&gt; &lt;li&gt;&lt;strong&gt;用户的网站登录：&lt;/strong&gt; 用户在使用用户名和密码进行登录时，认证和授权两个环节一同完成，而鉴权和权限控制则发生在后续的请求访问中，比如在选购物品或支付时。&lt;/li&gt; &lt;/ul&gt; &lt;blockquote&gt; &lt;p&gt;这里提个小问题，供大家思考：&lt;strong&gt;认证和鉴权之间的关系？欢迎大家在评论区讨论&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;既然我们已经了解了他们之间的关系，那么我们应该好好讲讲关于前端鉴权有哪些？以及他们之间存在的差异点又在哪里呢？&lt;/p&gt; &lt;h1 data-id="heading-7"&gt;1. HTTP 基本鉴权&lt;/h1&gt; &lt;p&gt;在 HTTP 中，&lt;code&gt;基本认证方案（Basic Access Authentication)&lt;/code&gt; 是允许客户端（通常指的就是网页浏览器）在请求时，通过用户提供用户名和密码的方式，实现对用户身份的验证。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;因为几乎所有的线上网站都不会走该认证方案，所以该方案大家了解即可&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;1.1 认证流程图&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d577adb5dd164d7880f711c2ec579827~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="1.HTTP基本鉴权.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;h2 data-id="heading-8"&gt;1.2 认证步骤解析&lt;/h2&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;客户端(如浏览器)：&lt;/strong&gt; 向服务器请求一个&lt;code&gt;受限的列表数据或资源&lt;/code&gt;，例如字段如下&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;sql&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-sql code-block-extension-codeShowNum" lang="sql"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;&lt;span class="hljs-keyword"&gt;GET&lt;/span&gt; &lt;span class="hljs-operator"&gt;/&lt;/span&gt;list&lt;span class="hljs-operator"&gt;/&lt;/span&gt; HTTP&lt;span class="hljs-operator"&gt;/&lt;/span&gt;&lt;span class="hljs-number"&gt;1.1&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;&amp;nbsp;Host: www.baidu.com&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;&amp;nbsp;&lt;span class="hljs-keyword"&gt;Authorization&lt;/span&gt;: Basic aHR0cHdhdGNoOmY&lt;span class="hljs-operator"&gt;=&lt;/span&gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;服务器&lt;/strong&gt;：客户端你好，这个资源在安全区 &lt;a href="https://link.juejin.cn?target=http%3A%2F%2Fbaidu.com" target="_blank" title="http://baidu.com" ref="nofollow noopener noreferrer"&gt;baidu.com&lt;/a&gt; 里，是受限资源，需要基本认证；&lt;/p&gt; &lt;p&gt;并且向客户端返回 401 状态码（Unauthorized 未被授权的）以及附带提供了一个认证域 &lt;code&gt;www-Authenticate: Basic realm=”baidu.com”&lt;/code&gt;要求进行身份验证；&lt;/p&gt; &lt;p&gt;其中&lt;code&gt;Basic&lt;/code&gt;&amp;nbsp;就是验证的模式，而&amp;nbsp;&lt;code&gt;realm="baidu.com"&lt;/code&gt;&amp;nbsp;说明客户端需要输入这个安全域的用户名和密码，而不是其他域的&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;ini&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-ini code-block-extension-codeShowNum" lang="ini"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;HTTP/1.1 401 Unauthorized&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;&amp;nbsp;www-Authenticate: Basic &lt;span class="hljs-attr"&gt;realm&lt;/span&gt;= &lt;span class="hljs-string"&gt;"baidu.com"&lt;/span&gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 服务器，我已经携带了用户名和密码给你了，你看一下；（注：如客户端是浏览器，那么此时会自动弹出一个弹窗，让用户输入用户名和密码）；&lt;/p&gt; &lt;p&gt;输入完用户名和密码后，则客户端将用户名及密码以 Base64 加密方式发送给服务器&lt;/p&gt; &lt;p&gt;传送的格式如下 (其中 Basic 内容为：&lt;strong&gt;用户名:密码&amp;nbsp;的 ase64 形式&lt;/strong&gt;)：&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;ini&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-ini code-block-extension-codeShowNum" lang="ini"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt; GET /list/ HTTP/1.1 &lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt; Authorization: Basic &lt;span class="hljs-attr"&gt;Ksid2FuZzp3YW5n&lt;/span&gt;==&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;服务器：&lt;/strong&gt; 客户端你好，我已经校验了&lt;code&gt;Authorization&lt;/code&gt; 字段你的用户名和密码，是正确的，这是你要的资源。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;erlang&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-erlang code-block-extension-codeShowNum" lang="erlang"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt; HTTP/&lt;span class="hljs-number"&gt;1.1&lt;/span&gt; &lt;span class="hljs-number"&gt;200&lt;/span&gt; OK&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt; ...&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;/li&gt; &lt;/ol&gt; &lt;h2 data-id="heading-9"&gt;1.3 优点&lt;/h2&gt; &lt;p&gt;简单，基本所有流行的浏览器都支持&lt;/p&gt; &lt;h2 data-id="heading-10"&gt;1.4 缺点&lt;/h2&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;不安全：&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;由于是基于 HTTP 传输，所以它在网络上几乎是裸奔的，虽然它使用了 Base64 来编码，但这个编码很容易就可以解码出来。&lt;/li&gt; &lt;li&gt;即使认证内容无法被解码为原始的用户名和密码也是不安全的，恶意用户可以再获取了认证内容后使用其不断的享服务器发起请求，这就是所谓的重放攻击。&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;无法主动注销&lt;/strong&gt;：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;由于 HTTP 协议没有提供机制清除浏览器中的 Basic 认证信息，除非标签页或浏览器关闭、或用户清除历史记录。&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ol&gt; &lt;h2 data-id="heading-11"&gt;1.5 使用场景&lt;/h2&gt; &lt;p&gt;内部网络，或者对安全要求不是很高的网络。&lt;/p&gt; &lt;h1 data-id="heading-12"&gt;2. Session-Cookie 鉴权&lt;/h1&gt; &lt;p&gt;&lt;code&gt;Session-Cookie&lt;/code&gt;&amp;nbsp;认证是利用服务端的 &lt;strong&gt;Session（会话&lt;/strong&gt;）和 &lt;strong&gt;浏览器（客户端）&lt;/strong&gt; 的 Cookie 来实现的前后端通信认证模式。&lt;/p&gt; &lt;p&gt;在理解这句话之前我们先简单了解下 &lt;code&gt;什么是 Cookie&lt;/code&gt; 以及 &lt;code&gt;什么是 Session&lt;/code&gt; ？&lt;/p&gt; &lt;h2 data-id="heading-13"&gt;2.1 什么是 Cookie&lt;/h2&gt; &lt;p&gt;众所周知，&lt;code&gt;HTTP 是无状态的协议&lt;/code&gt;（对于事务处理没有记忆能力，每次客户端和服务端会话完成时，服务端不会保存任何会话信息）；&lt;/p&gt; &lt;p&gt;所以为了让服务器区分不同的客户端，就必须主动的去维护一个状态，这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态可以通过 &lt;code&gt;Cookie&lt;/code&gt; 去实现。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;特点：&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Cookie 存储在客户端，可随意篡改，不安全&lt;/li&gt; &lt;li&gt;有大小限制，最大为 4kb&lt;/li&gt; &lt;li&gt;有数量限制，一般一个浏览器对于一个网站只能存不超过 20 个 Cookie，浏览器一般只允许存放 300个 Cookie&lt;/li&gt; &lt;li&gt;Android 和 IOS 对 Cookie 支持性不好&lt;/li&gt; &lt;li&gt;Cookie 是不可跨域的，但是一级域名和二级域名是允许共享使用的（靠的是 domain）&lt;/li&gt; &lt;/ul&gt; &lt;h2 data-id="heading-14"&gt;2.2 什么是 Session&lt;/h2&gt; &lt;p&gt;Session 的抽象概念是会话，是无状态协议通信过程中，为了实现中断/继续操作，将用户和服务器之间的交互进行的一种抽象；&lt;/p&gt; &lt;p&gt;具体来说，是服务器生成的一种 Session 结构，可以通过多种方式保存，如内存、数据库、文件等，大型网站一般有专门的 Session 服务器集群来保存用户会话；&lt;/p&gt; &lt;p&gt;&lt;strong&gt;原理流程：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 用户向服务器首次发送请求；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;服务器：&lt;/strong&gt; 接收到数据并自动为该用户创建特定的 Session / Session ID，来标识用户并跟踪用户当前的会话过程；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 浏览器收到响应获取会话信息，并且会在下一次请求时带上 Session / Session ID；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;服务器：&lt;/strong&gt; 服务器提取后会与本地保存的 Session ID进行对比找到该特定用户的会话，进而获取会话状态；&lt;/li&gt; &lt;li&gt;至此客户端与服务器的通信变成有状态的通信；&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;strong&gt;特点：&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Session 保存在服务器上；&lt;/li&gt; &lt;li&gt;通过服务器自带的加密协议进行；&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;strong&gt;与 Cookie 的差异：&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;安全性：&lt;/strong&gt; Cookie 由于保存在客户端，可随意篡改，Session 则不同存储在服务器端，无法伪造，所以 Session 的安全性更高；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;存取值的类型不同：&lt;/strong&gt; Cookie 只支持字符串数据，Session 可以存任意数据类型；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;有效期不同：&lt;/strong&gt; Cookie 可设置为长时间保持，Session 一般失效时间较短；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;存储大小不同：&lt;/strong&gt; Cookie 保存的数据不能超过 4K；&lt;/li&gt; &lt;/ul&gt; &lt;blockquote&gt; &lt;p&gt;看到这里可能就有同学想到了，&lt;code&gt;Session-Cookie&lt;/code&gt; 是不是就是把 &lt;code&gt;Session&lt;/code&gt; 存储在了客户端的 &lt;code&gt;Cookie&lt;/code&gt; 中呢？&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Bingo&lt;/strong&gt;，的确是这样的，我们接着往下看&lt;/p&gt; &lt;/blockquote&gt; &lt;h2 data-id="heading-15"&gt;2.3 Session-Cookie 的认证流程图&lt;/h2&gt; &lt;p&gt;&lt;img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/62cb87d3cf2c4e958a7a2514913b005b~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="2.Session-Cookie的认证流程图.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;h2 data-id="heading-16"&gt;2.4 Session-Cookie 认证步骤解析&lt;/h2&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 向服务器发送登录信息用户名/密码来请求登录校验；&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;服务器：&lt;/strong&gt; 验证登录的信息，验证通过后自动创建 Session（将 Session 保存在内存中，也可以保存在 Redis 中），然后给这个 Session 生成一个唯一的标识字符串会话身份凭证&amp;nbsp;&lt;code&gt;session_id&lt;/code&gt;(通常称为&amp;nbsp;&lt;code&gt;sid&lt;/code&gt;)，并在响应头&amp;nbsp;&lt;code&gt;Set-Cookie&lt;/code&gt;&amp;nbsp;中设置这个唯一标识符；&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;注：可以使用签名对 &lt;code&gt;sid&lt;/code&gt; 进行加密处理，服务端会根据对应的 &lt;code&gt;secret&lt;/code&gt;&amp;nbsp;密钥进行解密 （非必须步骤）&lt;/p&gt; &lt;/blockquote&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 收到服务器的响应后会解析响应头，并自动将&amp;nbsp;&lt;code&gt;sid&lt;/code&gt;&amp;nbsp;保存在本地 Cookie 中，浏览器在下次 HTTP 请求时请求头会自动附带上该域名下的 Cookie 信息；&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;服务器：&lt;/strong&gt; 接收客户端请求时会去解析请求头 Cookie 中的&amp;nbsp;&lt;code&gt;sid&lt;/code&gt;，然后根据这个&amp;nbsp;&lt;code&gt;sid&lt;/code&gt;&amp;nbsp;去找服务端保存的该客户端的&amp;nbsp;&lt;code&gt;sid&lt;/code&gt;，然后判断该请求是否合法；&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;h2 data-id="heading-17"&gt;2.5 Session-Cookie 的优点&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;Cookie 简单易用&lt;/li&gt; &lt;li&gt;Session 数据存储在服务端，相较于 JWT 方便进行管理，也就是当用户登录和主动注销，只需要添加删除对应的 Session 就可以了，方便管理&lt;/li&gt; &lt;li&gt;只需要后端操作即可，前端可以无感等进行操作；&lt;/li&gt; &lt;/ul&gt; &lt;h2 data-id="heading-18"&gt;2.6 Session-Cookie 的缺点&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;依赖 Cookie，一旦用户在浏览器端禁用 Cookie，那么就 GG 思密达了；&lt;/li&gt; &lt;li&gt;非常不安全，Cookie 将数据暴露在浏览器中，增加了数据被盗的风险（容易被 CSRF 等攻击）；&lt;/li&gt; &lt;li&gt;Session 存储在服务端，增大了服务端的开销，用户量大的时候会大大降低服务器性能；&lt;/li&gt; &lt;li&gt;对移动端的支持性不友好；&lt;/li&gt; &lt;/ul&gt; &lt;h2 data-id="heading-19"&gt;2.7 使用场景&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;一般中大型的网站都适用（除了 APP 移动端）；&lt;/li&gt; &lt;li&gt;由于一般的 Session 需集中存储在内存服务器上（如 Redis），这样就会增加服务器的预算，所以预算不够请谨慎选择；&lt;/li&gt; &lt;/ul&gt; &lt;h2 data-id="heading-20"&gt;2.8 前端常用的 Session 库推荐&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;使用 express：&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fexpressjs%2Fsession" target="_blank" title="https://github.com/expressjs/session" ref="nofollow noopener noreferrer"&gt;express-session&lt;/a&gt;&lt;/li&gt; &lt;li&gt;使用 koa：&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fkoajs%2Fsession" target="_blank" title="https://github.com/koajs/session" ref="nofollow noopener noreferrer"&gt;koa-session&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1 data-id="heading-21"&gt;3. Token 鉴权&lt;/h1&gt; &lt;p&gt;现在我们已经得知，&lt;code&gt;Session-Cookie&lt;/code&gt; 的一些缺点，以及 Session 的维护给服务端造成很大困扰，我们必须找地方存放它，又要考虑分布式的问题，甚至要单独为了它启用一套 Redis 集群。那有没有更好的办法？&lt;/p&gt; &lt;p&gt;那 &lt;code&gt;Token&lt;/code&gt; 就应运而生了&lt;/p&gt; &lt;h2 data-id="heading-22"&gt;3.1 什么是 Token（令牌）&lt;/h2&gt; &lt;p&gt;&lt;code&gt;Token&lt;/code&gt; 是一个令牌，客户端访问服务器时，验证通过后服务端会为其签发一张令牌，之后，客户端就可以携带令牌访问服务器，服务端只需要验证令牌的有效性即可。&lt;/p&gt; &lt;p&gt;一句话概括；&lt;strong&gt;访问资源接口（API）时所需要的资源凭证&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;一般 Token 的组成：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;uid&lt;/strong&gt; (用户唯一的身份标识) + &lt;strong&gt;time&lt;/strong&gt; (当前时间的时间戳) + &lt;strong&gt;sign&lt;/strong&gt; (签名，Token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Token 的认证流程图：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7beef40b29b14043ba5b0cea04d2a72f~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="3.Token的认证流程图.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Token 认证步骤解析：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 输入用户名和密码请求登录校验；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;服务器：&lt;/strong&gt; 收到请求，去验证用户名与密码；验证成功后，服务端会签发一个 Token 并把这个 Token 发送给客户端；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 收到 Token 以后需要把它存储起来，web 端一般会放在 localStorage 或 Cookie 中，移动端原生 APP 一般存储在本地缓存中；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;客户端发送请求：&lt;/strong&gt; 向服务端请求 API 资源的时候，将 Token 通过 HTTP 请求头 Authorization 字段或者其它方式发送给服务端；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;服务器：&lt;/strong&gt; 收到请求，然后去验证客户端请求里面带着的 Token ，如果验证成功，就向客户端返回请求的数据，否则拒绝返还（401）；&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Token 的优点：&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;服务端无状态化、可扩展性好：&lt;/strong&gt; Token 机制在服务端不需要存储会话（Session）信息，因为 Token 自身包含了其所标识用户的相关信息，这有利于在多个服务间共享用户状态&lt;/li&gt; &lt;li&gt;&lt;strong&gt;支持 APP 移动端设备；&lt;/strong&gt;&lt;/li&gt; &lt;li&gt;&lt;strong&gt;安全性好：&lt;/strong&gt; 有效避免 CSRF 攻击（因为不需要 Cookie）&lt;/li&gt; &lt;li&gt;&lt;strong&gt;支持跨程序调用：&lt;/strong&gt; 因为 Cookie 是不允许跨域访问的，而 Token 则不存在这个问题&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;strong&gt;Token 的缺点：&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;配合：&lt;/strong&gt; 需要前后端配合处理；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;占带宽：&lt;/strong&gt; 正常情况下比&amp;nbsp;&lt;code&gt;sid&lt;/code&gt;&amp;nbsp;更大，消耗更多流量，挤占更多宽带&lt;/li&gt; &lt;li&gt;&lt;strong&gt;性能问题：&lt;/strong&gt; 虽说验证 Token 时不用再去访问数据库或远程服务进行权限校验，但是需要对 Token 加解密等操作，所以会更耗性能；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;有效期短：&lt;/strong&gt; 为了避免 Token 被盗用，一般 Token 的有效期会设置的较短，所以就有了 &lt;code&gt;Refresh Token&lt;/code&gt;；&lt;/li&gt; &lt;/ul&gt; &lt;h2 data-id="heading-23"&gt;3.2 什么是 Refresh Token（刷新 Token）&lt;/h2&gt; &lt;p&gt;业务接口用来鉴权的 Token，我们称之为 &lt;code&gt;Access Token&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;为了安全，我们的 &lt;code&gt;Access Token&lt;/code&gt; 有效期一般设置较短，以避免被盗用。但过短的有效期会造成 &lt;code&gt;Access Token&lt;/code&gt; 经常过期，过期后怎么办呢？&lt;/p&gt; &lt;p&gt;一种办法是：&lt;code&gt;刷新 Access Token&lt;/code&gt;，让用户重新登录获取新 Token，会很麻烦；&lt;/p&gt; &lt;p&gt;另外一种办法是：再来一个 Token，一个专门生成 Access Token 的 Token，我们称为 &lt;code&gt;Refresh Token&lt;/code&gt;；&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Access Token：&lt;/strong&gt; 用来访问业务接口，由于有效期足够短，盗用风险小，也可以使请求方式更宽松灵活；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Refresh Token：&lt;/strong&gt; 用来获取 Access Token，有效期可以长一些，通过独立服务和严格的请求方式增加安全性；由于不常验证，也可以如前面的 Session 一样处理；&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;strong&gt;Refresh Token 的认证流程图：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ac396824cc4b4a88b5f57d84c1f856cc~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="3.1RefreshToken的认证流程图.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Refresh Token 认证步骤解析：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 输入用户名和密码请求登录校验；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;服务端：&lt;/strong&gt; 收到请求，验证用户名与密码；验证成功后，服务端会签发一个 &lt;code&gt;Access Token&lt;/code&gt; 和 &lt;code&gt;Refresh Token&lt;/code&gt; 并返回给客户端；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 把 &lt;code&gt;Access Token&lt;/code&gt; 和 &lt;code&gt;Refresh Token&lt;/code&gt; 存储在本地；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;客户端发送请求：&lt;/strong&gt; 请求数据时，携带 &lt;code&gt;Access Token&lt;/code&gt; 传输给服务端；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;服务端：&lt;/strong&gt; &lt;ul&gt; &lt;li&gt;验证 Access Token 有效：正常返回数据&lt;/li&gt; &lt;li&gt;验证 Access Token 过期：拒绝请求&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;strong&gt;客户端&lt;/strong&gt; ( Access Token 已过期) &lt;strong&gt;：&lt;/strong&gt; 则重新传输 Refresh Token 给服务端；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;服务端&lt;/strong&gt; ( Access Token 已过期) &lt;strong&gt;：&lt;/strong&gt; 验证 Refresh Token ，验证成功后返回新的 Access Token 给客户端；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 重新携带新的 Access Token 请求接口；&lt;/li&gt; &lt;/ol&gt; &lt;h2 data-id="heading-24"&gt;3.3 Token 和 Session-Cookie 的区别&lt;/h2&gt; &lt;p&gt;&lt;code&gt;Session-Cookie&lt;/code&gt; 和 &lt;code&gt;Token&lt;/code&gt; 有很多类似的地方，但是 &lt;code&gt;Token&lt;/code&gt; 更像是 &lt;code&gt;Session-Cookie&lt;/code&gt; 的升级改良版。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;存储地不同：&lt;/strong&gt; Session 一般是存储在服务端；Token 是无状态的，一般由前端存储；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;安全性不同：&lt;/strong&gt; Session 和 Token 并不矛盾，作为身份认证 Token 安全性比 Session 好，因为每一个请求都有签名还能防止监听以及重放攻击；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;支持性不同：&lt;/strong&gt; Session-Cookie 认证需要靠浏览器的 Cookie 机制实现，如果遇到原生 NativeAPP 时这种机制就不起作用了，或是浏览器的 Cookie 存储功能被禁用，也是无法使用该认证机制实现鉴权的；而 Token 验证机制丰富了客户端类型。&lt;/li&gt; &lt;/ul&gt; &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;如果你的用户数据可能需要和第三方共享，或者允许第三方调用 API 接口，用 Token 。如果永远只是自己的网站，自己的 App，用什么就无所谓了。&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;h1 data-id="heading-25"&gt;4. JWT（JSON Web Token）鉴权&lt;/h1&gt; &lt;p&gt;通过第三节，我们知道了 &lt;code&gt;Token&lt;/code&gt; 的使用方式以及组成，我们不难发现，服务端验证客户端发送过来的 Token 时，还需要查询数据库获取用户基本信息，然后验证 Token 是否有效；&lt;/p&gt; &lt;p&gt;这样每次请求验证都要查询数据库，增加了查库带来的延迟等性能消耗；&lt;/p&gt; &lt;p&gt;&lt;strong&gt;那么这时候业界常用的 &lt;code&gt;JWT&lt;/code&gt; 就应运而生了！！！&lt;/strong&gt;&lt;/p&gt; &lt;h2 data-id="heading-26"&gt;4.1 什么是 JWT&lt;/h2&gt; &lt;p&gt;&lt;code&gt;JWT&lt;/code&gt; 是 &lt;code&gt;Auth0&lt;/code&gt; 提出的通过 &lt;code&gt;对 JSON 进行加密签名&lt;/code&gt;来实现授权验证的方案；&lt;/p&gt; &lt;p&gt;就是登录成功后将相关用户信息组成 JSON 对象，然后对这个对象进行某种方式的&lt;code&gt;加密&lt;/code&gt;，返回给客户端； 客户端在下次请求时带上这个 Token； 服务端再收到请求时&lt;code&gt;校验 token 合法性&lt;/code&gt;，其实也就是在校验请求的合法性。&lt;/p&gt; &lt;h2 data-id="heading-27"&gt;4.2 JWT 的组成&lt;/h2&gt; &lt;p&gt;JWT 由三部分组成： &lt;code&gt;Header 头部&lt;/code&gt;、 &lt;code&gt;Payload 负载&lt;/code&gt; 和 &lt;code&gt;Signature 签名&lt;/code&gt;&lt;/p&gt; &lt;p&gt;它是一个很长的字符串，中间用点（&lt;code&gt;.&lt;/code&gt;）分隔成三个部分。列如 ：&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs code-block-extension-codeShowNum"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;strong&gt;Header 头部：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在 Header 中通常包含了两部分：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;typ：代表 Token 的类型，这里使用的是 JWT 类型；&lt;/li&gt; &lt;li&gt;alg：使用的 Hash 算法，例如 HMAC SHA256 或 RSA.&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;json&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-json code-block-extension-codeShowNum" lang="json"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;&lt;span class="hljs-punctuation"&gt;{&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;"alg"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-string"&gt;"HS256"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;"typ"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-string"&gt;"JWT"&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;&amp;nbsp;&lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;strong&gt;Payload 负载：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;它包含一些声明 Claim (实体的描述，通常是一个 User 信息，还包括一些其他的元数据) ，用来存放实际需要传递的数据，JWT 规定了7个官方字段：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;iss (issuer)：签发人&lt;/li&gt; &lt;li&gt;exp (expiration time)：过期时间&lt;/li&gt; &lt;li&gt;sub (subject)：主题&lt;/li&gt; &lt;li&gt;aud (audience)：受众&lt;/li&gt; &lt;li&gt;nbf (Not Before)：生效时间&lt;/li&gt; &lt;li&gt;iat (Issued At)：签发时间&lt;/li&gt; &lt;li&gt;jti (JWT ID)：编号&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;除了官方字段，你还可以在这个部分定义私有字段，下面就是一个例子。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;json&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-json code-block-extension-codeShowNum" lang="json"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;&lt;span class="hljs-punctuation"&gt;{&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;"sub"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-string"&gt;"1234567890"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;"name"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-string"&gt;"John Doe"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;"admin"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-literal"&gt;&lt;span class="hljs-keyword"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="5"&gt;&amp;nbsp;&lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;strong&gt;Signature 签名&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Signature 部分是对前两部分的签名，防止数据篡改。&lt;/p&gt; &lt;p&gt;首先，需要指定一个密钥（secret）。这个密钥只有服务器才知道，不能泄露给用户。然后，使用 Header 里面指定的签名算法（默认是 HMAC SHA256），按照下面的公式产生签名。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;scss&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-scss code-block-extension-codeShowNum" lang="scss"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;&lt;span class="hljs-built_in"&gt;HMACSHA256&lt;/span&gt;(&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;&amp;nbsp; &amp;nbsp;base64UrlEncode(header) + "." +&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-built_in"&gt;base64UrlEncode&lt;/span&gt;(payload),&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;&amp;nbsp; &amp;nbsp;secret)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;h2 data-id="heading-28"&gt;4.3 &lt;strong&gt;JWT 的使用方式&lt;/strong&gt;&lt;/h2&gt; &lt;p&gt;客户端收到服务器返回的 JWT，可以储存在 Cookie 里面，也可以储存在 localStorage。&lt;/p&gt; &lt;p&gt;此后，客户端每次与服务器通信，都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送，但是这样不能跨域，所以更好的做法是放在 HTTP 请求的头信息&lt;code&gt;Authorization&lt;/code&gt;字段里面。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;sql&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-sql code-block-extension-codeShowNum" lang="sql"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;&lt;span class="hljs-keyword"&gt;Authorization&lt;/span&gt;: Bearer &lt;span class="hljs-operator"&gt;&amp;lt;&lt;/span&gt;token&lt;span class="hljs-operator"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;h2 data-id="heading-29"&gt;4.4 JWT 的认证流程图&lt;/h2&gt; &lt;p&gt;其实 JWT 的认证流程与 Token 的认证流程差不多，只是不需要再单独去查询数据库查找用户用户；简要概括如下：&lt;/p&gt; &lt;p&gt;&lt;img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b5f2a372f0a5485aa1de361039774b52~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="4.JWT的认证流程图的副本.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;h2 data-id="heading-30"&gt;4.5 JWT 的优点&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;不需要在服务端保存会话信息（RESTful API 的原则之一就是无状态），所以易于应用的扩展，即信息不保存在服务端，不会存在 Session 扩展不方便的情况；&lt;/li&gt; &lt;li&gt;JWT 中的 Payload 负载可以存储常用信息，用于信息交换，有效地使用 JWT，可以降低服务端查询数据库的次数&lt;/li&gt; &lt;/ul&gt; &lt;h2 data-id="heading-31"&gt;4.6 JWT 的缺点&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;加密问题：&lt;/strong&gt; JWT 默认是不加密，但也是可以加密的。生成原始 Token 以后，可以用密钥再加密一次。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;到期问题：&lt;/strong&gt; 由于服务器不保存 Session 状态，因此无法在使用过程中废止某个 Token，或者更改 Token 的权限。也就是说，一旦 JWT 签发了，在到期之前就会始终有效，除非服务器部署额外的逻辑。&lt;/li&gt; &lt;/ul&gt; &lt;h2 data-id="heading-32"&gt;4.7 前端常用的 JWT 库推荐&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;使用 express：&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fauth0%2Fexpress-jwt" target="_blank" title="https://github.com/auth0/express-jwt" ref="nofollow noopener noreferrer"&gt;express-jwt&lt;/a&gt;&lt;/li&gt; &lt;li&gt;使用 koa：&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fkoajs%2Fjwt" target="_blank" title="https://github.com/koajs/jwt" ref="nofollow noopener noreferrer"&gt;koa-jwt&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1 data-id="heading-33"&gt;5. 单点登录（Single Sign On）&lt;/h1&gt; &lt;p&gt;前面我们已经知道了，在同域下的客户端/服务端认证系统中，通过客户端携带凭证，可以维持一段时间内的登录状态。&lt;/p&gt; &lt;p&gt;但随着企业的发展，一个大型系统里可能包含 n 多子系统，用户在操作不同的系统时，需要多次登录，很麻烦，那么&lt;code&gt;单点登录（SSO)&lt;/code&gt; 就可以很好的解决这个问题的，&lt;code&gt;在多个应用系统中，只需要登录一次，就可以访问其他相互信任的应用系统。&lt;/code&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;例如登录天猫，淘宝也会自动登录；&lt;/li&gt; &lt;li&gt;登录百度贴吧，百度网盘也会自动登录；&lt;/li&gt; &lt;/ul&gt; &lt;h2 data-id="heading-34"&gt;5.1 同域下的 SSO（主域名相同）&lt;/h2&gt; &lt;p&gt;当百度网站存在两个相同主域名下的贴吧子系统&amp;nbsp;&lt;code&gt;tieba.baidu.com&lt;/code&gt;&amp;nbsp;和网盘子系统&amp;nbsp;&lt;code&gt;pan.baidu.com&lt;/code&gt;&amp;nbsp;时，以下为他们实现 SSO 的步骤：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 用户访问某个子系统时（例如&amp;nbsp;&lt;code&gt;tieba.baidu.com&lt;/code&gt;），如果没有登录，则跳转至 SSO 认证中心提供的登录页面进行登录；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;服务端：&lt;/strong&gt; 登录认证后，服务端把登录用户的信息存储于 Session 中，并且附加在响应头的&amp;nbsp;&lt;code&gt;Set-Cookie&lt;/code&gt;&amp;nbsp;字段中，设置 Cookie 的 Domain 为 &lt;code&gt;.baidu.com&lt;/code&gt; ；&lt;/li&gt; &lt;li&gt;客户端：再次发送请求时，携带主域名 Domain 下的 Cookie 给服务器，此时服务端就可以通过该 Cookie 来验证登录状态了；&lt;/li&gt; &lt;/ol&gt; &lt;blockquote&gt; &lt;p&gt;其实我们不难发现，这就是我们上面讲的 &lt;code&gt;Session-Cookie 认证&lt;/code&gt; 登录方式； 但如果是不同域呢？毕竟不同域之间 Cookie 是不共享的，那怎么办？&lt;/p&gt; &lt;/blockquote&gt; &lt;h2 data-id="heading-35"&gt;5.2 跨域下的 SSO（主域名不同）&lt;/h2&gt; &lt;p&gt;在我们常见的购物网站天猫 (&lt;a href="https://link.juejin.cn?target=http%3A%2F%2Fwww.tmall.com%2F" target="_blank" title="http://www.tmall.com/" ref="nofollow noopener noreferrer"&gt;tmall.com&lt;/a&gt;) 和 淘宝 (taobao.com) 中，我们只需要登录其中某一个系统，另外一个系统打开后就会默认登录，那么这是怎么做的呢？&lt;/p&gt; &lt;p&gt;那么就有了 &lt;code&gt;CAS（Central Authentication Service）中央授权服务&lt;/code&gt;，那么我们先主要说下 &lt;code&gt;CAS&lt;/code&gt; 的流程；&lt;/p&gt; &lt;p&gt;&lt;strong&gt;单点登录下的 CAS 认证流程图：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7a034d58b8db41c6a9a049bc4c0890b5~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="5.CAS认证流程图.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;单点登录下的 CAS 认证步骤详解：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 开始访问系统 A；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;系统 A：&lt;/strong&gt; 发现用户未登录，重定向至 CAS 认证服务（sso.com），同时 URL 地址参数携带登录成功后回跳到系统 A 的页面链接（&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fsso.com%2Flogin%3FredirectURL%3Dhttps%253A%252F%252Fwww.taobao.com%25EF%25BC%2589%25EF%25BC%259B" target="_blank" title="https://sso.com/login?redirectURL=https%3A%2F%2Fwww.taobao.com%EF%BC%89%EF%BC%9B" ref="nofollow noopener noreferrer"&gt;sso.com/login?redir…&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;strong&gt;CAS 认证服务：&lt;/strong&gt; 发现请求 Cookie 中没有携带登录的票据凭证（TGC），所以 CAS 认证服务判定用户处于&amp;nbsp;&lt;code&gt;未登录&lt;/code&gt;&amp;nbsp;状态，重定向用户页面至 CAS 的登录界面，用户在 CAS 的登录页面上进行登录操作。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 输入用户名密码进行 CAS 系统认证；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;CAS 认证服务：&lt;/strong&gt; 校验用户信息，并且 &lt;code&gt;生成 TGC&lt;/code&gt; 放入自己的 Session 中，同时以 Set-Cookie 形式写入 Domain 为 &lt;code&gt;sso.com&lt;/code&gt; 的域下 ；同时生成一个 &lt;code&gt;授权令牌 ST (Service Ticket)&lt;/code&gt; ，然后重定向至系统 A 的地址，重定向的地址中包含生成的 ST（重定向地址：&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fwww.taobao.com%3Ftoken%3DST-345678%25EF%25BC%2589" target="_blank" title="https://www.taobao.com?token=ST-345678%EF%BC%89" ref="nofollow noopener noreferrer"&gt;www.taobao.com?token=ST-345678）&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;strong&gt;系统 A：&lt;/strong&gt; 拿着 ST 向 CAS 认证服务发送请求，CAS 认证服务验证票据 (ST) 的有效性。验证成功后，系统 A 知道用户已经在 CAS 登录了（其中的 ST 可以保存到 Cookie 或者本地中），系统 A 服务器使用该票据 (ST) 创建与用户的会话，称为局部会话，返回受保护资源；&lt;/li&gt; &lt;/ol&gt; &lt;blockquote&gt; &lt;p&gt;到这里客户端就可以跟系统 A 愉快的交往啦 ~&lt;/p&gt; &lt;/blockquote&gt; &lt;ol start="7"&gt; &lt;li&gt;&lt;strong&gt;客户端：&lt;/strong&gt; 开始访问系统 B；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;系统 B：&lt;/strong&gt; 发现用户未登录，重定向至 SSO 认证服务，并将自己的地址作为参数传递，并附上在 sso.com 域下的 cookie 值是第五步生成的 TGC；&lt;/li&gt; &lt;li&gt;&lt;strong&gt;CAS 认证服务：&lt;/strong&gt; CAS 认证服务中心发现用户已登录，跳转回系统 B 的地址，并附上票据 (ST) ;&lt;/li&gt; &lt;li&gt;&lt;strong&gt;系统 B：&lt;/strong&gt; 拿到票据 (ST)，去 CAS 认证服务验证票据 (ST) 的有效性。验证成功后，客户端也可以跟系统 B 交往了 ~&lt;/li&gt; &lt;/ol&gt; &lt;blockquote&gt; &lt;p&gt;(PS：脚踏两只船，感觉有点渣呀 ~)&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;单点登录下需要注意的点：&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;p&gt;如图中流程所示，我们发现 &lt;code&gt;CAS 认证服务&lt;/code&gt; 在签发的 &lt;code&gt;授权令牌 ST&lt;/code&gt; 后，直接重定向，这样其实是比较容易容易被窃取，那么我们需要在系统 A 或者系统 B 在向 CAS 验证成功 (如图中的第 14 步和第 11 步) 后，再生成另一个新的验证 Token 返回给客户端保存；&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;CAS 一般提供四个接口：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;/login&lt;/code&gt;：登录接口，用于登录到中央授权服务&lt;/li&gt; &lt;li&gt;&lt;code&gt;/logout&lt;/code&gt;：登出接口，用于从中央授权服务中登出&lt;/li&gt; &lt;li&gt;&lt;code&gt;/validate&lt;/code&gt;：用于验证用户是否登录中央授权服务&lt;/li&gt; &lt;li&gt;&lt;code&gt;/serviceValidate&lt;/code&gt;：用于让各个 Service 验证用户是否登录中央授权服务&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;CAS 生成的票据：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;TGT（Ticket Grangting Ticket）&lt;/strong&gt; ：TGT 是 CAS 为用户签发的&amp;nbsp;&lt;code&gt;登录票据&lt;/code&gt;，拥有了 TGT，用户就可以证明自己在 CAS 成功登录过。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;TGC：Ticket Granting Cookie：&lt;/strong&gt; CAS Server 生成TGT放入自己的 Session 中，而 TGC 就是这个 Session 的唯一标识（SessionId），以 Cookie 形式放到浏览器端，是 CAS Server 用来明确用户身份的凭证。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;ST（Service Ticket）&lt;/strong&gt; ：ST 是 CAS 为用户签发的访问某个 Service 的票据。&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h1 data-id="heading-36"&gt;6. OAuth 2.0&lt;/h1&gt; &lt;p&gt;在我们实际浏览网站的时候，当我们登录的时候除了输入当前网站的账号密码外，我们还发现可以通过第三方的 QQ 或者 微信登录，那么这又是如何做到了呢，这就要谈到 &lt;strong&gt;OAuth&lt;/strong&gt; 了。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;OAuth 协议又有 1.0 和 2.0 两个版本，2.0 版整个授权验证流程更简单更安全，也是目前最主要的用户身份验证和授权方式。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2 data-id="heading-37"&gt;6.1 什么是 OAuth 2.0？&lt;/h2&gt; &lt;p&gt;&lt;strong&gt;OAuth&lt;/strong&gt; 是一个开放标准，允许用户授权第三方网站 (CSDN、思否等) 访问他们存储在另外的服务提供者上的信息，而不需要将用户名和密码提供给第三方网站；&lt;/p&gt; &lt;p&gt;常见的提供 OAuth 认证服务的厂商： &lt;code&gt;支付宝、QQ、微信、微博&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;简单说，OAuth 就是一种授权机制。数据的所有者告诉系统，同意授权第三方应用进入系统，获取这些数据。系统从而产生一个短期的进入令牌（Token），用来代替密码，供第三方应用使用。&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;令牌与密码的差异：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;令牌（Token）&lt;/code&gt; 与 &lt;code&gt;密码（Password）&lt;/code&gt; 的作用是一样的，都可以进入系统，但是有三点差异。&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;令牌是短期的，到期会自动失效：&lt;/strong&gt; 用户自己无法修改。密码一般长期有效，用户不修改，就不会发生变化。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;令牌可以被数据所有者撤销，会立即失效。&lt;/strong&gt;&lt;/li&gt; &lt;li&gt;&lt;strong&gt;令牌有权限范围（scope）：&lt;/strong&gt; 对于网络服务来说，只读令牌就比读写令牌更安全。密码一般是完整权限。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;OAuth 2.0 对于如何颁发令牌的细节，规定得非常详细。具体来说，一共分成&lt;strong&gt;四种授权&lt;/strong&gt;模式 &lt;strong&gt;（Authorization Grant）&lt;/strong&gt; ，适用于不同的互联网场景。&lt;/p&gt; &lt;p&gt;无论哪个模式都拥有三个必要角色：&lt;code&gt;客户端&lt;/code&gt;、&lt;code&gt;授权服务器&lt;/code&gt;、&lt;code&gt;资源服务器&lt;/code&gt;，有的还有&lt;code&gt;用户（资源拥有者）&lt;/code&gt;，下面简单介绍下四种授权模式。&lt;/p&gt; &lt;h2 data-id="heading-38"&gt;6.2 授权码模式&lt;/h2&gt; &lt;p&gt;&lt;code&gt;授权码（Authorization Code Grant)&lt;/code&gt; 方式，指的是第三方应用先申请一个授权码，然后再用该码获取令牌。&lt;/p&gt; &lt;p&gt;这种方式是最常用的流程，安全性也最高，它适用于那些&lt;strong&gt;有后端服务&lt;/strong&gt;的 Web 应用。授权码通过前端传送，令牌则是储存在后端，而且所有与资源服务器的通信都在后端完成。这样的前后端分离，可以避免令牌泄漏。&lt;/p&gt; &lt;p&gt;一句话概括：&lt;code&gt;客户端换取授权码，客户端使用授权码换token，客户端使用token访问资源&lt;/code&gt;&lt;/p&gt; &lt;h3 data-id="heading-39"&gt;授权码模式的步骤详解&lt;/h3&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;客户端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;打开网站 A，点击登录按钮，请求 A 服务，A 服务重定向 (重定向地址如下) 至授权服务器 (如QQ、微信授权服务)。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;ini&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-ini code-block-extension-codeShowNum" lang="ini"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt; https://qq.com/oauth/authorize?&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;   &lt;span class="hljs-attr"&gt;response_type&lt;/span&gt;=code&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;   &lt;span class="hljs-attr"&gt;client_id&lt;/span&gt;=CLIENT_ID&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;   &lt;span class="hljs-attr"&gt;redirect_uri&lt;/span&gt;=CALLBACK_URL&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="5"&gt;   &lt;span class="hljs-attr"&gt;scope&lt;/span&gt;=read&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;上面 URL 中，&lt;code&gt;response_type&lt;/code&gt; 参数表示要求返回授权码（&lt;code&gt;code&lt;/code&gt;），&lt;code&gt;client_id&lt;/code&gt; 参数让 B 知道是谁在请求，&lt;code&gt;redirect_uri&lt;/code&gt; 参数是 B 接受或拒绝请求后的跳转网址，&lt;code&gt;scope&lt;/code&gt; 参数表示要求的授权范围（这里是只读）&lt;/p&gt; &lt;p&gt;&lt;img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9db6e408da364a288cd4fa7e3991d966~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="前端鉴权 (4).png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;授权服务器：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;授权服务网站&lt;/code&gt; 会要求用户登录，然后询问是否同意给予 A 网站授权。用户表示同意，这时&lt;code&gt;授权服务网站&lt;/code&gt; 就会跳回 &lt;code&gt;redirect_uri&lt;/code&gt; 参数指定的网址。跳转时，会传回一个授权码，就像下面这样。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;ini&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-ini code-block-extension-codeShowNum" lang="ini"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;https://a.com/callback?&lt;span class="hljs-attr"&gt;code&lt;/span&gt;=AUTHORIZATION_CODE&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;上面 URL 中，&lt;code&gt;code&lt;/code&gt; 参数就是授权码。&lt;/p&gt; &lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0129aaeaf30d4b1eb93955e9c5aa8bef~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="前端鉴权 (5).png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;网站 A 服务器：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;拿到授权码以后，就可以向 &lt;code&gt;授权服务器 (qq.com)&lt;/code&gt; 请求令牌，请求地址如下：&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;ini&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-ini code-block-extension-codeShowNum" lang="ini"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt; https://qq.com/oauth/token?&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;  &lt;span class="hljs-attr"&gt;client_id&lt;/span&gt;=CLIENT_ID&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;  &lt;span class="hljs-attr"&gt;client_secret&lt;/span&gt;=CLIENT_SECRET&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;  &lt;span class="hljs-attr"&gt;grant_type&lt;/span&gt;=authorization_code&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="5"&gt;  &lt;span class="hljs-attr"&gt;code&lt;/span&gt;=AUTHORIZATION_CODE&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="6"&gt;  &lt;span class="hljs-attr"&gt;redirect_uri&lt;/span&gt;=CALLBACK_URL&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;上面 URL 中，&lt;code&gt;client_id&lt;/code&gt; 参数和 &lt;code&gt;client_secret&lt;/code&gt; 参数用来让授权服务器 确认 A 的身份（&lt;code&gt;client_secret&lt;/code&gt; 参数是保密的，因此只能在后端发请求），&lt;code&gt;grant_type&lt;/code&gt;参数的值是&lt;code&gt;AUTHORIZATION_CODE&lt;/code&gt;，表示采用的授权方式是授权码，&lt;code&gt;code&lt;/code&gt; 参数是上一步拿到的授权码，&lt;code&gt;redirect_uri&lt;/code&gt; 参数是令牌颁发后的回调网址。&lt;/p&gt; &lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/23ab90e5a0ad420aa56058969c58aab3~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="前端鉴权 (6).png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;授权服务器：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;收到请求以后，验证通过，就会颁发令牌。具体做法是向 &lt;code&gt;redirect_uri&lt;/code&gt; 指定的网址，发送一段 JSON 数据。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;json&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-json code-block-extension-codeShowNum" lang="json"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt; &lt;span class="hljs-punctuation"&gt;{&lt;/span&gt; &amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;   &lt;span class="hljs-attr"&gt;"access_token"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt;&lt;span class="hljs-string"&gt;"ACCESS_TOKEN"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;   &lt;span class="hljs-attr"&gt;"token_type"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt;&lt;span class="hljs-string"&gt;"bearer"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;   &lt;span class="hljs-attr"&gt;"expires_in"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt;&lt;span class="hljs-number"&gt;2592000&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="5"&gt;   &lt;span class="hljs-attr"&gt;"refresh_token"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt;&lt;span class="hljs-string"&gt;"REFRESH_TOKEN"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="6"&gt;   &lt;span class="hljs-attr"&gt;"scope"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt;&lt;span class="hljs-string"&gt;"read"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="7"&gt;   &lt;span class="hljs-attr"&gt;"uid"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt;&lt;span class="hljs-number"&gt;100101&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="8"&gt;   &lt;span class="hljs-attr"&gt;"info"&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;{&lt;/span&gt;...&lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="9"&gt; &lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;上面 JSON 数据中，&lt;code&gt;access_token&lt;/code&gt; 字段就是令牌，A 网站在后端拿到了，然后返回给客户端即可。&lt;/p&gt; &lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1ee1c85036846fc8715aec2487f43ec~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="前端鉴权 (7).png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;h2 data-id="heading-40"&gt;6.3 隐藏式模式（Implicit Grant）&lt;/h2&gt; &lt;p&gt;有些 Web 应用是纯前端应用，没有后端。这时就不能用上面的方式了，必须将令牌储存在前端。&lt;strong&gt;OAuth2.0 就规定了第二种方式，允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤，所以称为（授权码）"隐藏式"（implicit）。&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;一句话概括：&lt;code&gt;客户端让用户登录授权服务器换token，客户端使用token访问资源&lt;/code&gt;。&lt;/p&gt; &lt;h3 data-id="heading-41"&gt;隐藏式模式的步骤详解&lt;/h3&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;客户端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;打开网站 A，A 网站提供一个链接，要求用户跳转到 &lt;code&gt;授权服务器&lt;/code&gt;，授权用户数据给 A 网站使用。如下链接：&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;ini&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-ini code-block-extension-codeShowNum" lang="ini"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt; https://qq.com/oauth/authorize?&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;   &lt;span class="hljs-attr"&gt;response_type&lt;/span&gt;=token&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;   &lt;span class="hljs-attr"&gt;client_id&lt;/span&gt;=CLIENT_ID&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;   &lt;span class="hljs-attr"&gt;redirect_uri&lt;/span&gt;=CALLBACK_URL&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="5"&gt;   &lt;span class="hljs-attr"&gt;scope&lt;/span&gt;=read&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;上面 URL 中，&lt;code&gt;response_type&lt;/code&gt;参数为&lt;code&gt;token&lt;/code&gt;，表示要求直接返回令牌。&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;授权服务器：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;用户跳转到授权服务器，登录后同意给予 A 网站授权。这时，授权服务器就会跳回&lt;code&gt;redirect_uri&lt;/code&gt; 参数指定的跳转网址，并且把令牌作为 URL 参数，传给 A 网站。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;bash&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-bash code-block-extension-codeShowNum" lang="bash"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt; https://a.com/callback&lt;span class="hljs-comment"&gt;#token=ACCESS_TOKEN&lt;/span&gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;上面 URL 中，&lt;code&gt;token&lt;/code&gt;参数就是令牌，A 网站因此直接在前端拿到令牌。&lt;/p&gt; &lt;p&gt;&lt;img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/46c8358d1b224378ac423bccbda62546~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="前端鉴权 (8).png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;blockquote&gt; &lt;p&gt;注意：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;令牌的位置是 URL 锚点（fragment），而不是查询字符串（querystring），这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议，因此存在"中间人攻击"的风险，而浏览器跳转时，锚点不会发到服务器，就减少了泄漏令牌的风险。&lt;/li&gt; &lt;li&gt;这种方式把令牌直接传给前端，是很不安全的。因此，只能用于一些安全要求不高的场景，并且令牌的有效期必须非常短，通常就是会话期间（session）有效，浏览器关掉，令牌就失效了。&lt;/li&gt; &lt;/ol&gt; &lt;/blockquote&gt; &lt;h2 data-id="heading-42"&gt;6.4 用户名密码式模式（Password Credentials Grant）&lt;/h2&gt; &lt;p&gt;如果你高度信任某个应用，OAuth 2.0 也允许用户把用户名和密码，直接告诉该应用。该应用就使用你的密码，申请令牌，这种方式称为"密码式"（password）。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;一句话概括：用户在客户端提交账号密码换token，客户端使用token访问资源。&lt;/strong&gt;&lt;/p&gt; &lt;h3 data-id="heading-43"&gt;密码式模式的步骤详解&lt;/h3&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;客户端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;A 网站要求用户提供 &lt;code&gt;授权服务器(qq.com)&lt;/code&gt; 的用户名和密码。拿到以后，A 就直接向 &lt;code&gt;授权服务器&lt;/code&gt; 请求令牌。&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;ini&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-ini code-block-extension-codeShowNum" lang="ini"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;https://oauth.b.com/token?&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;grant_type&lt;/span&gt;=password&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;username&lt;/span&gt;=USERNAME&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;password&lt;/span&gt;=PASSWORD&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="5"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;client_id&lt;/span&gt;=CLIENT_ID&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;上面 URL 中，&lt;code&gt;grant_type&lt;/code&gt;参数是授权方式，这里的&lt;code&gt;password&lt;/code&gt;表示"密码式"，&lt;code&gt;username&lt;/code&gt;和&lt;code&gt;password&lt;/code&gt;是 &lt;code&gt;授权服务器&lt;/code&gt; 的用户名和密码。&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;授权服务器：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;授权服务器&lt;/code&gt; 验证身份通过后，直接给出令牌。&lt;/p&gt; &lt;p&gt;注意，这时不需要跳转，而是把令牌放在 JSON 数据里面，作为 HTTP 回应，A 网站因此拿到令牌。&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;blockquote&gt; &lt;p&gt;这种方式需要用户给出自己的用户名/密码，显然风险很大，因此只适用于其他授权方式都无法采用的情况，而且必须是用户高度信任的应用。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2 data-id="heading-44"&gt;6.5 客户端模式（Client Credentials Grant）&lt;/h2&gt; &lt;p&gt;客户端模式指客户端以自己的名义，而不是以用户的名义，向&lt;code&gt;授权服务器&lt;/code&gt; 进行认证。&lt;/p&gt; &lt;p&gt;主要适用于没有前端的命令行应用。&lt;/p&gt; &lt;p&gt;一句话概括：&lt;code&gt;客户端使用自己的标识换token，客户端使用token访问资源&lt;/code&gt;。&lt;/p&gt; &lt;h3 data-id="heading-45"&gt;客户端模式的步骤详解&lt;/h3&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;客户端：&lt;/p&gt; &lt;p&gt;客户端向&lt;code&gt;授权服务器&lt;/code&gt; 进行身份认证，并要求一个访问令牌。请求链接地址：&lt;/p&gt; &lt;pre&gt;&lt;div class="code-block-extension-header" style="background-color: rgb(248, 248, 248);"&gt;&lt;div class="code-block-extension-headerLeft"&gt;&lt;div class="code-block-extension-foldBtn"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M16.924 9.617A1 1 0 0 0 16 9H8a1 1 0 0 0-.707 1.707l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 .217-1.09z" data-name="Down"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="code-block-extension-headerRight"&gt;&lt;span class="code-block-extension-lang"&gt;ini&lt;/span&gt;&lt;div class="code-block-extension-copyCodeBtn"&gt;复制代码&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;code class="hljs language-ini code-block-extension-codeShowNum" lang="ini"&gt;&lt;span class="code-block-extension-codeLine" data-line-num="1"&gt;&amp;nbsp;https://oauth.b.com/token?&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="2"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;grant_type&lt;/span&gt;=client_credentials&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="3"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;client_id&lt;/span&gt;=CLIENT_ID&amp;amp;&lt;/span&gt; &lt;span class="code-block-extension-codeLine" data-line-num="4"&gt;&amp;nbsp; &amp;nbsp;&lt;span class="hljs-attr"&gt;client_secret&lt;/span&gt;=CLIENT_SECRET&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;上面 URL 中，&lt;code&gt;grant_type&lt;/code&gt;参数等于&lt;code&gt;client_credentials&lt;/code&gt;表示采用凭证式，&lt;code&gt;client_id&lt;/code&gt;和&lt;code&gt;client_secret&lt;/code&gt;用来让&lt;code&gt;授权服务器&lt;/code&gt; 确认 A 的身份。&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;授权服务器：&lt;/p&gt; &lt;p&gt;&lt;code&gt;授权服务器&lt;/code&gt; 验证通过以后，直接返回令牌。&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;blockquote&gt; &lt;p&gt;注意：这种方式给出的令牌，是针对第三方应用的，而不是针对用户的，即有可能多个用户共享同一个令牌。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2 data-id="heading-46"&gt;6.5 &lt;strong&gt;授权模式选型&lt;/strong&gt;&lt;/h2&gt; &lt;h3 data-id="heading-47"&gt;按授权需要的多端情况：&lt;/h3&gt; &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;模式&lt;/th&gt;&lt;th&gt;需要前端&lt;/th&gt;&lt;th&gt;需要后端&lt;/th&gt;&lt;th&gt;需要用户响应&lt;/th&gt;&lt;th&gt;需要客户端密钥&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;授权码模式 Authorization Code&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;隐式授权模式 Implicit Grant&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;密码授权模式 Password Grant&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;客户端授权模式 Client Credentials&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;h3 data-id="heading-48"&gt;按照客户端类型与访问令牌所有者分类：&lt;/h3&gt; &lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ff7cb097558442d7861e67caa3bcf5d0~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="authentication-oauth2-mode-selection.jpeg" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;上述主要比较浅显的讲解了 OAuth2.0 的基本逻辑，如若想详细深入的了解，可查看官方文档 &lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FOAuth" target="_blank" title="https://en.wikipedia.org/wiki/OAuth" ref="nofollow noopener noreferrer"&gt;OAuth&lt;/a&gt; 或 &lt;a href="https://link.juejin.cn?target=http%3A%2F%2Fwww.rfcreader.com%2F%23rfc6749" target="_blank" title="http://www.rfcreader.com/#rfc6749" ref="nofollow noopener noreferrer"&gt;RFC 6749&lt;/a&gt;； 亦可查看 &lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fwww.cnblogs.com%2Fhellxz%2Fp%2Foauth2_process.html" target="_blank" title="https://www.cnblogs.com/hellxz/p/oauth2_process.html" ref="nofollow noopener noreferrer"&gt;OAuth 2.0 概念及授权流程梳理&lt;/a&gt; 做对比&lt;/p&gt; &lt;/blockquote&gt; &lt;h1 data-id="heading-49"&gt;7. 联合登录和信任登录&lt;/h1&gt; &lt;h2 data-id="heading-50"&gt;7.1 什么是联合登陆&lt;/h2&gt; &lt;p&gt;&lt;code&gt;联合登录&lt;/code&gt; 指同时包含多种凭证校验的登录服务，同时，也可以理解为使用第三方凭证进行校验的登录服务。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;通俗点讲：&lt;/strong&gt; 对于两个网站 A 和 B，在登录 A 网站的时候用 B 网站的帐号密码，就是联合登录，或者登录 B 网站的时候使用 A 网站的帐号密码，也是联合登录。&lt;/p&gt; &lt;p&gt;这样的概念其实与上面所讲的 OAuth2.0 的 &lt;code&gt;用户名密码式模式&lt;/code&gt; 认证方式类似。&lt;/p&gt; &lt;p&gt;最经典的莫过于 APP 内嵌 H5 的使用场景，当用户从 APP 进入内嵌的 H5 时，我们希望 APP 内已登录的用户能够访问到 H5 内受限的资源，而未登录的用户则需要登录后访问。&lt;/p&gt; &lt;p&gt;这里思路主要有两种，一种是原生跳转内嵌 H5 页面时，将登录态 Token 附加在 URL 参数上，另一种则是内嵌 H5 主动通过与原生客户端制定的协议获取应用内的登录状态。&lt;/p&gt; &lt;h2 data-id="heading-51"&gt;7.2 什么是信任登录&lt;/h2&gt; &lt;p&gt;&lt;code&gt;信任登录&lt;/code&gt; 是指所有不需要用户主动参与的登录，例如建立在私有设备与用户之间的绑定关系，凭证就是私有设备的信息，此时不需要用户再提供额外的凭证。信任登录又指用第三方比较成熟的用户库来校验凭证，并登录当前访问的网站。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;通俗点讲：&lt;/strong&gt; 在 A 网站有登录状态的时候，可以直接跳转到 B 网站而不用登录，就是 &lt;code&gt;信任登录&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;目前比较常见的第三方信任登录帐号如：QQ 号淘宝帐号、支付宝帐号、微博帐号等。&lt;/p&gt; &lt;p&gt;我们不难发现 OAtuth 2.0 其实就是信任登录的缩影，因为正是有了 OAuth，我们的信任登录才得以实现。&lt;/p&gt; &lt;h1 data-id="heading-52"&gt;8. 唯一登录&lt;/h1&gt; &lt;p&gt;— 假设现在产品经理提一个需求：&lt;strong&gt;我想要实现用户只能在一个设备上登录，禁止用户重复登录；&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;— 身为优秀的程序员的我们当然是满足他啦 ！！&lt;/p&gt; &lt;h2 data-id="heading-53"&gt;8.1 什么是唯一登录&lt;/h2&gt; &lt;p&gt;唯一登录，指的是&lt;strong&gt;禁止多人同时登录同一账号，后者的登录行为，会导致前者掉线。&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;通俗点讲就是&lt;/strong&gt;：A 账号在 A 电脑上登录后，A 账号此时又用 B 电脑再次登录，则 A 电脑请求页面时，提示“重新登录”的信息，并跳转到登录页面&lt;/p&gt; &lt;h2 data-id="heading-54"&gt;8.2 唯一登录流程图&lt;/h2&gt; &lt;p&gt;&lt;img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/86761e0bdda343a7a6cbc05e9f98d4ca~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="8.唯一登录流程图的副本.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;h2 data-id="heading-55"&gt;8.3 唯一登录步骤详解&lt;/h2&gt; &lt;p&gt;&lt;strong&gt;用户在客户端 A 操作：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;输入账号请求登录接口；&lt;/li&gt; &lt;li&gt;后端生成对应 Token 并且返回给客户端 A，并且在服务端保存一个登录状态；&lt;/li&gt; &lt;li&gt;客户端A 保存 Token，并且每次请求都在 header 头中携带对应的 Token；&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;strong&gt;用户在客户端 B 操作：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;突然用户在客户端 B 上开始登录操作，我们会发现，步骤和在客户端A上面的操作几乎是一致的；&lt;/p&gt; &lt;p&gt;只是后端在生成新的 Token 时，要先验证登录状态，然后再生成对应新的 Token；&lt;/p&gt; &lt;h1 data-id="heading-56"&gt;9. 扫码登录&lt;/h1&gt; &lt;h2 data-id="heading-57"&gt;9.1 什么是扫码登录&lt;/h2&gt; &lt;p&gt;扫码登录通常见于移动端 APP 中，很多 PC 端的网站都提供了扫码登录的功能，无需在网页上输入任何账号和密码，只需要让移动端 APP (如微信、淘宝、QQ等等) 中已登录用户主动扫描 &lt;code&gt;二维码&lt;/code&gt; ，再确认登录，以使 PC 端的同款应用得以快速登录的方式就是 &lt;code&gt;扫码登录&lt;/code&gt; 。&lt;/p&gt; &lt;h2 data-id="heading-58"&gt;9.2 什么是二维码&lt;/h2&gt; &lt;p&gt;&lt;code&gt;二维码&lt;/code&gt; 又称二维条码，常见的二维码为 QR Code，QR 全称 Quick Response，是一个近几年来移动设备上超流行的一种编码方式，它比传统的Bar Code条形码能存更多的信息，也能表示更多的数据类型。&lt;/p&gt; &lt;p&gt;通过上面所述，我们不难发现，扫码登录需要三端 (&lt;code&gt;PC端&lt;/code&gt;、&lt;code&gt;手机端&lt;/code&gt;、&lt;code&gt;服务端&lt;/code&gt;) 来进行配合才能达到登录成功的效果；&lt;/p&gt; &lt;h2 data-id="heading-59"&gt;9.3 扫码登录的认证流程图&lt;/h2&gt; &lt;p&gt;&lt;img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2980c555405f42b68801d7525c0e0d63~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="9.扫码登录的认证流程图的副本.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;h2 data-id="heading-60"&gt;9.4 扫码登录的步骤详解 (待扫码阶段、待确认阶段、已确认阶段)&lt;/h2&gt; &lt;p&gt;&lt;strong&gt;待扫码阶段：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;PC端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;打开某个网站 (如taobao.com) 或者某个 APP (如微信) 的扫码登录入口；就会携带 PC 端的设备信息向服务端发送一个获取二维码的请求；&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;服务端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;服务器收到请求后，随机生成一个 UUID 作为二维码 ID，并将 UUID 与&amp;nbsp;&lt;code&gt;PC 端的设备信息&lt;/code&gt;&amp;nbsp;关联起来存储在 Redis 服务器中，然后返回给 PC 端；同时设置一个过期时间，在过期后，用户登录二维码需要进行刷新重新获取。&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;PC 端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;收到二维码 ID 之后，将二维码 ID 以&amp;nbsp;&lt;code&gt;二维码的形式&lt;/code&gt;&amp;nbsp;展示，等待移动端扫码。并且此时的 PC 端开始轮询查询二维码状态，直到登录成功。&lt;/p&gt; &lt;p&gt;如果移动端未扫描，那么一段时间后二维码会自动失效。&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;strong&gt;已扫码待确认阶段：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;手机端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;打开手机端对应&lt;strong&gt;已登录&lt;/strong&gt;的 APP (微信或淘宝等)，开始扫描识别 PC 端展示的二维码；&lt;/p&gt; &lt;p&gt;移动端扫描二维码后，会自动获取到二维码 ID，并将移动端登录的信息凭证（Token）和二维码 ID 作为参数发送给服务端，此时手机必须是已登录（使用扫描登录的前提是移动端的应用为已登录状态，这样才可以共享登录态）。&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;服务端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;收到手机端发来的请求后，会将&amp;nbsp;&lt;code&gt;Token 与二维码 ID&lt;/code&gt;&amp;nbsp;关联，为什么需要关联呢？因为，当我们在使用微信时，移动端退出时，PC 端也应该随之退出登录，这个关联就起到这个作用。然后会生成一个临时 Token，这个 Token 会返回给移动端，一次性 Token 用作确认时的凭证。&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;strong&gt;已确认阶段：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;手机端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;收到确认信息后，点击确认按钮，移动端携带上一步中获取的&amp;nbsp;&lt;code&gt;临时 Token&lt;/code&gt;&amp;nbsp;发送给服务端校验；&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;服务端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;服务端校验完成后，会更新二维码状态，并且给 PC 端生成一个&amp;nbsp;&lt;code&gt;正式的 Token&lt;/code&gt;，后续 PC 端就是持有这个 Token 访问服务端。&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;PC端：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;轮询到二维码状态为已登录状态，并且会获取到了生成的 Token，完成登录，后续访问都基于 Token 完成。&lt;/p&gt; &lt;/li&gt; &lt;/ol&gt; &lt;h1 data-id="heading-61"&gt;10. 一键登录（适用于原生APP）&lt;/h1&gt; &lt;h2 data-id="heading-62"&gt;10.1 账号密码登录&lt;/h2&gt; &lt;p&gt;大家都知道，最传统的登录方式就是使用&lt;strong&gt;账号加密码登录&lt;/strong&gt;，简单粗暴，一般也不会出现什么问题；&lt;/p&gt; &lt;p&gt;&lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;但这种方式要求用户要记住自己的账号和密码，也就是有一个记忆成本。用户为了降低记忆成本，很可能会在不同平台使用同一套账号密码。从安全角度考虑，一旦某个平台的账号密码泄露了，会连累到该用户使用的其他平台。&lt;/li&gt; &lt;li&gt;另外，由于账号和个人身份无关，意味着同一个用户可以注册多个不同的账号，也就是可能会有恶意注册的情况发生。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;strong&gt;直到手机卡的强制实名制才得以解决！&lt;/strong&gt;&lt;/p&gt; &lt;h2 data-id="heading-63"&gt;10.2 手机号验证码登录&lt;/h2&gt; &lt;p&gt;随着无线互联的发展以及手机卡实名制的推广，手机号俨然已成为特别的身份证明，与账号密码相比，手机号可以更好地验证用户的身份，防止恶意注册。&lt;/p&gt; &lt;p&gt;但是手机号注册还是需要一系列繁琐的操作：输入手机号、等待短信验证码、输入验证码、点击登录。整个流程少说二十秒，而且如果收不到短信，也就登录补了，这类问题有可能导致潜在的用户流失。&lt;/p&gt; &lt;p&gt;从安全角度考虑，还存在验证码泄漏的风险。如果有人知道了你的手机号，并且窃取到了验证码，那他也能登录你的账号了。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;所以就有了一键登录操作！&lt;/strong&gt;&lt;/p&gt; &lt;h2 data-id="heading-64"&gt;10.3 什么是一键登录&lt;/h2&gt; &lt;p&gt;我们想一下，为什么我们需要验证码？验证码的作用就是确定这个手机号是你的，那除了使用短信，是否还有别的方式对手机号进行认证？&lt;/p&gt; &lt;p&gt;于是，就有了咱们的主角一键登录。&lt;/p&gt; &lt;p&gt;短信验证码的作用就是证明当前操作页面的用户与输入手机号的用户为相同的人，那么实际上只要我们能够获取到当前手机使用的手机卡号，直接使用这个号码进行登录，不需要额外的操作，这就是&lt;strong&gt;一键登录&lt;/strong&gt;。&lt;/p&gt; &lt;p&gt;一键登录能不能做，取决于运营商是否开放相关服务；随着运营商开放了相关的服务，我们现在已经能够接入运营商提供的 SDK 并付费使用相关的服务。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;一键登录流程图：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c09b580d15ae46c1add78f0a754acd0e~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?" alt="authentication-one-click-login-workflow.png" loading="lazy" class="medium-zoom-image"&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;一键登录步骤详解：&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;SDK 初始化：&lt;/strong&gt; 调用 SDK 方法，传入平台配置的 AppKey 和 AppSecret&lt;/li&gt; &lt;li&gt;&lt;strong&gt;唤起授权页：&lt;/strong&gt; 调用 SDK 唤起授权接口，SDK 会先向运营商发起获取手机号掩码的请求，请求成功后跳到授权页。授权页会显示手机号掩码以及运营商协议给用户确认。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;同意授权并登录：&lt;/strong&gt; 用户同意相关协议，点击授权页面的登录按钮，SDK 会请求本次取号的 Token，请求成功后将 Token 返回给客户端&lt;/li&gt; &lt;li&gt;&lt;strong&gt;取号：&lt;/strong&gt; 将获取到的 Token 发送到自己的服务器，由服务端携带 Token 调用运营商一键登录的接口，调用成功就返回手机号码。服务端用手机号进行登录或注册操作，返回操作结果给客户端，完成一键登录。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;strong&gt;三大运营商开放平台：&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;p&gt;&lt;a href="https://link.juejin.cn?target=http%3A%2F%2Fdev.10086.cn%2F" target="_blank" title="http://dev.10086.cn/" ref="nofollow noopener noreferrer"&gt;移动 - 互联网能力开放平台&lt;/a&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fid.189.cn%2F" target="_blank" title="https://id.189.cn/" ref="nofollow noopener noreferrer"&gt;电信 - 天翼账号开放平台&lt;/a&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;&lt;a href="https://link.juejin.cn?target=http%3A%2F%2Fopen.wo.com.cn%2F" target="_blank" title="http://open.wo.com.cn/" ref="nofollow noopener noreferrer"&gt;联通 - WO+ 开放平台&lt;/a&gt;&lt;/p&gt; &lt;p&gt;由于国内三大运营商各自有独立的 SDK，所以会导致兼容方面的工作会特别繁琐。如果要采用一键登录的方案，不妨采用第三方提供了号码认证服务，下列几家供应商都拥有手机号码认证能力：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fhelp.aliyun.com%2Fproduct%2F75010.html" target="_blank" title="https://help.aliyun.com/product/75010.html" ref="nofollow noopener noreferrer"&gt;阿里 - 号码认证服务&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://link.juejin.cn?target=http%3A%2F%2Fshanyan.253.com%2F" target="_blank" title="http://shanyan.253.com/" ref="nofollow noopener noreferrer"&gt;创蓝 - 闪验&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fwww.jiguang.cn%2Fidentify" target="_blank" title="https://www.jiguang.cn/identify" ref="nofollow noopener noreferrer"&gt;极光 - 极光认证&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://link.juejin.cn?target=https%3A%2F%2Fwww.mob.com%2FmobService%2Fsecverify" target="_blank" title="https://www.mob.com/mobService/secverify" ref="nofollow noopener noreferrer"&gt;mob - 秒验&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;strong&gt;注意：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在认证过程中，需要用户打开蜂窝网络，如果手机设备没有插入 SIM 卡、或者关闭蜂窝网络的情况下，是无法完成认证的。所以就算接入一键登录，还是要兼容传统的登录方式，允许用户在失败的情况下，仍能正常完成登录流程。&lt;/p&gt; &lt;h1 data-id="heading-65"&gt;总结&lt;/h1&gt; &lt;p&gt;在学习了解上面的 10 种鉴权方法后，我们简单概括一下&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;HTTP 基本认证&lt;/code&gt;适用于内部网络，或者对安全要求不是很高的网络；&lt;/li&gt; &lt;li&gt;&lt;code&gt;Session-Cookie&lt;/code&gt; 适用于一般中大型的网站（移动端 APP 除外）；&lt;/li&gt; &lt;li&gt;&lt;code&gt;Token&lt;/code&gt; 和 &lt;code&gt;JWT&lt;/code&gt; 都适用于市面上大部分的企业型网站，JWT 效能会优于 Token；&lt;/li&gt; &lt;li&gt;&lt;code&gt;单点登录&lt;/code&gt; 适用于子系统较多的大型企业网站；&lt;/li&gt; &lt;li&gt;&lt;code&gt;OAuth 2.0&lt;/code&gt;适用于需要快速注册用户型的网站；&lt;/li&gt; &lt;li&gt;&lt;code&gt;扫码登录&lt;/code&gt; 适用于已完成部署了三端的企业；&lt;/li&gt; &lt;li&gt;&lt;code&gt;一键登录&lt;/code&gt; 适用于原生 APP；&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br&gt;&lt;div&gt;作者：易师傅&lt;br&gt;链接：https://juejin.cn/post/7129298214959710244&lt;br&gt;来源：稀土掘金&lt;br&gt;著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。&lt;/div&gt;&lt;/div&gt;</content:encoded>
      <pubDate>Wed, 13 Sep 2023 06:05:00 GMT</pubDate>
    </item>
    <item>
      <title>MySQL从库搭建方案</title>
      <link>https://cliveyuan.cn/article/82</link>
      <content:encoded>&lt;h1&gt;master开启bin-log,设置数据库&lt;/h1&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;# master server # vim /etc/my.cnf [mysqld] log-bin=mysql-bin   #[必须]启用二进制日志 server-id=222       #[必须]服务器唯一ID，默认是1，一般取IP最后一段  # 设置需要写binlog的数据库 binlog-do-db=db1 binlog-do-db=db2  gtid-mode=on enforce-gtid-consistency=true  &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;重启MySQL数据库&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;systemctl restart mysqld  &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;创建slave账号&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;-- # master server mysql GRANT REPLICATION SLAVE ON *.* to 'slave1'@'主库host' identified by 'slave_pwd'; &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;停服,记录bin-log-index, position, 关掉自动重启job!!!&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;-- # master server mysql show master status; &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;备份数据&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;# master server mkdir /tmp/db_backup mysqldump -uroot -p*** --databases db | gzip &amp;gt; /tmp/db_backup/db-20220607.sql.gz &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;还原数据&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;# slave server   192.168.0.1 is master server ip mkdir -p /home/db_data scp root@192.168.0.1:/tmp/db_backup/db-20220607.sql.gz /home/db_data # create db CREATE DATABASE `database0` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # import gunzip -f &amp;lt;/home/db_data/db-20220607.sql.gz| mysql -u root -p****  &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;配置slave,设置数据库&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;# slave server # vim /etc/my.cnf [mysqld] server-id=129 gtid-mode=on enforce-gtid-consistency=true master_info_repository=TABLE relay_log_info_repository=TABLE #replicate-rewrite-db = database0 -&amp;gt; slave_database0 #replicate-rewrite-db = database1 -&amp;gt; slave_database1 # 重启MySQL数据库!!!  # master_log_file 和 master_log_pos 改为上文记录的值 change master to master_host='192.168..0.1',master_user='slave1',master_password='slave_pwd',master_log_file='mysql-bin.000001',master_log_pos=0 for channel '2'; start slave; show slave status; &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;测试同步&lt;/h1&gt; &lt;p&gt;在master数据表中添加记录, 查看slave对应的数据表中是否同步&lt;/p&gt; &lt;h1&gt;启动服务&lt;/h1&gt; &lt;p&gt;测试通过则同步启动应用服务器&lt;/p&gt; &lt;h1&gt;验证数据&lt;/h1&gt; &lt;p&gt;观察新增数据是否同步&lt;/p&gt; &lt;h1&gt;其他&lt;/h1&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Error_code: 1032&lt;/strong&gt; 如果出现主键重复或者更新数据不存在导致的主从不同步时,可执行&lt;code&gt;set global slave_exec_mode='IDEMPOTENT'&lt;/code&gt; 来修改模式为幂等&lt;/li&gt; &lt;/ul&gt;</content:encoded>
      <pubDate>Thu, 07 Sep 2023 15:41:00 GMT</pubDate>
    </item>
    <item>
      <title>Java下载网络文件</title>
      <link>https://cliveyuan.cn/article/81</link>
      <content:encoded>&lt;pre&gt;&lt;code class="language-java"&gt;@SneakyThrows     private void doDown(String url, String path) {         BufferedInputStream in = new BufferedInputStream(new URL(url).openStream());         File file = new File(path);         FileOutputStream out = new FileOutputStream(file);         IOUtils.copy(in, out);         in.close();         out.close();     } &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Fri, 30 Dec 2022 07:44:00 GMT</pubDate>
    </item>
    <item>
      <title>Linux 搭建Redis</title>
      <link>https://cliveyuan.cn/article/80</link>
      <content:encoded>&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;前言&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;之前在本地都是使用windows安装，直接下载运行就好。现在想在linux下安装，但是网上版本太多了，自己记录一个有效的安装步骤。环境：&lt;/span&gt;&lt;/p&gt;&lt;ul style="margin-right: 0px; margin-bottom: 0px; margin-left: 30px; padding: 0px; word-break: break-all; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;li style="margin: 1em 0px; padding: 0px; list-style: disc;"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;&amp;nbsp;redis版本：5.0.7&lt;/span&gt;&lt;/li&gt;&lt;li style="margin: 1em 0px; padding: 0px; list-style: disc;"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;&amp;nbsp;linux服务器：CentOS 7.6&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;安装&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;1、redis是C开发的，所以安装 redis 需要C语言的编译环境，即安装gcc&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;yum install gcc&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;2、切到&amp;nbsp;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;/usr/local 目录下，下载 redis-5.0.7.tar.gz&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;wget http:&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(0, 128, 0);"&gt;//&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(0, 128, 0);"&gt;download.redis.io/releases/redis-5.0.7.tar.gz&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;3、解压并修改文件名&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;tar xzf redis-&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(128, 0, 128);"&gt;5.0&lt;/span&gt;.&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(128, 0, 128);"&gt;7&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(0, 0, 0);"&gt;.tar.gz mv redis&lt;/span&gt;-&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(128, 0, 128);"&gt;5.0&lt;/span&gt;.&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(128, 0, 128);"&gt;7&lt;/span&gt; redis&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;4、进入redis目录，然后进行编译&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(0, 0, 0);"&gt;make&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;5、安装（这个PREFIX是编译时用于指定程序存放的路径）&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;make PREFIX=/usr/local/redis install&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;6、修改redis.conf文件里的daemonize为yes，表示后台启动&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;vim /etc/redis.conf&lt;/pre&gt;&lt;p style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;&lt;br&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;# 设置访问密码&amp;nbsp;requirepass xxx&lt;/p&gt;&lt;p style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;# 设置端口号 port 6379&lt;/p&gt;&lt;p style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;# 设置外网访问&amp;nbsp;protected-mode no&lt;/p&gt;&lt;p style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;&lt;br&gt;&lt;/p&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;7、启动redis&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;service redis start&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;&lt;img src="https://img2020.cnblogs.com/blog/647585/202102/647585-20210201134340002-1120431139.png" alt="" loading="lazy" class="medium-zoom-image" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 100%; height: auto; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) 0s !important;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;8、进入redis客户端。出现如下命令行表示安装成功&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;/usr/local/redis/bin/redis-cli&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&amp;nbsp;&lt;img src="https://img2020.cnblogs.com/blog/647585/202102/647585-20210201134418986-738400823.png" alt="" loading="lazy" class="medium-zoom-image" style="margin: 0px; padding: 0px; max-width: 100%; height: auto; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) 0s !important;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;其它&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;查看 redis 进程&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;ps -ef | grep redis&lt;/pre&gt;&lt;p style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;service redis status&lt;/p&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&lt;span style="margin: 0px; padding: 0px; font-size: 15px;"&gt;关闭 redis 服务(杀掉进程)&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding-top, padding-bottom, margin-top, margin-bottom, color, opacity; font-family: &amp;quot;Courier New&amp;quot;, serif; font-size: 12px;"&gt;kill -&lt;span style="margin: 0px; padding: 0px; font-size: inherit; line-height: 1.5; color: rgb(128, 0, 128);"&gt;9&lt;/span&gt; pid&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(57, 57, 57); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; background-color: rgb(250, 247, 239);"&gt;&amp;nbsp;&lt;/p&gt;</content:encoded>
      <pubDate>Fri, 04 Nov 2022 09:21:00 GMT</pubDate>
    </item>
    <item>
      <title>微信支付接口v3的坑</title>
      <link>https://cliveyuan.cn/article/79</link>
      <content:encoded>&lt;h1&gt;微信支付所需资料：&lt;/h1&gt; &lt;ul&gt; &lt;li&gt;商户号&lt;/li&gt; &lt;li&gt;商户证书序列号&lt;/li&gt; &lt;li&gt;接口密钥(APIV3)&lt;/li&gt; &lt;li&gt;证书（apiclient_key.pem，apiclient_cert.p12，apiclient_cert.pem）&lt;/li&gt; &lt;/ul&gt; &lt;h2&gt;商户证书序列号&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;商户证书序列号是指&lt;code&gt;apiclient_cert.pem&lt;/code&gt;这个证书的序列号&lt;/li&gt; &lt;li&gt;可以通过这个网站查看&lt;a href="https://myssl.com/cert_decode.html" target="_blank"&gt;https://myssl.com/cert_decode.html&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;code&gt;apiclient_cert.pem&lt;/code&gt; 这个证书在项目中其实是用不到的&lt;/li&gt; &lt;/ul&gt; &lt;h2&gt;微信公钥证书 wxPublicKey&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;这个是需要导出的&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/EliasZzz/CertificateDownloader/releases" target="_blank"&gt;CertificateDownloader jar包下载&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code&gt;java -jar CertificateDownloader-1.1.jar -f 商户私钥文件路径 -k 证书解密的密钥(APIV3) -m 商户号 -o 证书保存路径 -s 商户证书序列号 &lt;/code&gt;&lt;/pre&gt; &lt;ul&gt; &lt;li&gt;证书内容作为 wxPublicKey&lt;/li&gt; &lt;/ul&gt;</content:encoded>
      <pubDate>Fri, 01 Jul 2022 05:43:00 GMT</pubDate>
    </item>
    <item>
      <title>ItelliJ IDEA Mac Osx 10.5+ 快捷键</title>
      <link>https://cliveyuan.cn/article/78</link>
      <content:encoded>&lt;h2&gt;# Mac键盘符号和修饰键说明：&lt;/h2&gt;&lt;p&gt;⌘ Command&lt;/p&gt;&lt;p&gt;⇧ Shift&lt;/p&gt;&lt;p&gt;⌥ Option&lt;/p&gt;&lt;p&gt;⌃ Control&lt;/p&gt;&lt;p&gt;↩︎ Return/Enter&lt;/p&gt;&lt;p&gt;⌫ Delete&lt;/p&gt;&lt;p&gt;⌦ 向前删除键（Fn+Delete）&lt;/p&gt;&lt;p&gt;↑ 上箭头&lt;/p&gt;&lt;p&gt;↓ 下箭头&lt;/p&gt;&lt;p&gt;← 左箭头&lt;/p&gt;&lt;p&gt;→ 右箭头&lt;/p&gt;&lt;p&gt;⇞ Page Up（Fn+↑）&lt;/p&gt;&lt;p&gt;⇟ Page Down（Fn+↓）&lt;/p&gt;&lt;p&gt;Home Fn + ←&lt;/p&gt;&lt;p&gt;End Fn + →&lt;/p&gt;&lt;p&gt;⇥ 右制表符（Tab键）&lt;/p&gt;&lt;p&gt;⇤ 左制表符（Shift+Tab）&lt;/p&gt;&lt;p&gt;⎋ Escape (Esc)&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;&amp;nbsp;# editing (编辑)&lt;/h2&gt;&lt;p&gt;⌘N, ⌃↩ 生成代码/创建文件&lt;/p&gt;&lt;p&gt;⌘⌥L 格式化代码&lt;/p&gt;&lt;p&gt;⌃⇧Space 智能代码补全&lt;/p&gt;&lt;p&gt;⌘D 复制当前行或选定的块&lt;/p&gt;&lt;p&gt;⌘⌫ 删除当前行或选定的块的行&lt;/p&gt;&lt;p&gt;⌘⌥T 包围代码&lt;/p&gt;&lt;p&gt;⌘/ 注释/取消注释与行注释&lt;/p&gt;&lt;p&gt;⌘⌥/ 注释/取消注释与块注释&lt;/p&gt;&lt;p&gt;⌥↑ 连续选中代码块、⌥↓ 减少当前选中的代码块&lt;/p&gt;&lt;p&gt;⌥↩ 显示意向动作和快速修复代码&lt;/p&gt;&lt;p&gt;⌃⌥O 优化import (移除无用的导入)&lt;/p&gt;&lt;p&gt;⌘⇧V 从最近的缓冲区粘贴&lt;/p&gt;&lt;p&gt;⌃⇧J 智能的将代码拼接成一行&lt;/p&gt;&lt;p&gt;⌘⇧U 大小写切换&lt;/p&gt;&lt;p&gt;⌘⇧8 列模式&lt;/p&gt;&lt;p&gt;⌘⌃G 选择所有出现&lt;/p&gt;&lt;p&gt;⌘F12 查看文件结构&lt;/p&gt;&lt;p&gt;⌘⌥] / ⌘⌥[&amp;nbsp; &amp;nbsp;快速定位到代码块结束/开始&lt;/p&gt;&lt;p&gt;⌘⇧+/- 展开/折叠所以代码块&lt;/p&gt;&lt;p&gt;⌘P 显示方法的参数信息&lt;/p&gt;&lt;p&gt;⌃O 覆盖方法（重写父类方法）&lt;/p&gt;&lt;p&gt;⌃I 实现方法（实现接口中的方法）&lt;/p&gt;&lt;p&gt;⌃⇧Q 显示上下文信息&lt;/p&gt;&lt;p&gt;⌃⌥I 自动缩进线&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;# Search/Replace（查询/替换）&lt;/h2&gt;&lt;p&gt;Double ⇧ 查询任何东西&lt;/p&gt;&lt;p&gt;⌘F 当前文件查找、⌘⇧F全局查找&lt;/p&gt;&lt;p&gt;⌘R 当前文件替换、⌘⇧F全局替换&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;# Usage Search（使用查询）&lt;/h2&gt;&lt;p&gt;⌥F7 / ⌘F7 在文件中查找用法 / 在类中查找用法&lt;/p&gt;&lt;p&gt;⌘⌥F7 显示用法&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;# Compile and Run（编译和运行）&lt;/h2&gt;&lt;p&gt;⌘F9 编译Project&lt;/p&gt;&lt;p&gt;⌘⇧F9 编译选择的文件、包或模块&lt;/p&gt;&lt;p&gt;⌃⌥R 弹出 Run 的可选择菜单&lt;/p&gt;&lt;p&gt;⌃⌥D 弹出 Debug 的可选择菜单&lt;/p&gt;&lt;p&gt;⌃R 运行&lt;/p&gt;&lt;p&gt;⌃D 调试&lt;/p&gt;&lt;p&gt;⌃⇧R, ⌃⇧D 从编辑器运行上下文环境配置&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;# Debugging（调试）&lt;/h2&gt;&lt;p&gt;F8 跳到下一步，如果当前行断点是一个方法，则不进入当前方法体内&lt;/p&gt;&lt;p&gt;F7 进入下一步，如果当前行断点是一个方法，则进入当前方法体内，如果该方法体还有方法，则不会进入该内嵌的方法中&lt;/p&gt;&lt;p&gt;⇧F7 智能步入，断点所在行上有多个方法调用，会弹出进入哪个方法&lt;/p&gt;&lt;p&gt;⇧F8 跳出&lt;/p&gt;&lt;p&gt;F9 恢复程序&lt;/p&gt;&lt;p&gt;⌥F8 计算表达式（可以更改变量值使其生效）&lt;/p&gt;&lt;p&gt;⌘R&amp;nbsp; 重新执行&lt;/p&gt;&lt;p&gt;⌘F8 切换断点（若光标当前行有断点则取消断点，没有则加上断点）&lt;/p&gt;&lt;p&gt;⌘⇧F8 查看断点信息&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;# Navigation（导航）&lt;/h2&gt;&lt;p&gt;⌘O 搜索类、 ⌘⇧O 搜索文件&lt;/p&gt;&lt;p&gt;⌘⌥O 前往指定的变量 / 方法&lt;/p&gt;&lt;p&gt;⌘⇧] / ⌘⇧[&amp;nbsp; 切换标签&lt;/p&gt;&lt;p&gt;⌘W 关闭活动的编辑器选项卡&lt;/p&gt;&lt;p&gt;⌘L 在当前文件跳转到某一行的指定处&lt;/p&gt;&lt;p&gt;⌘E 显示最近打开的文件记录列表，⌘⇧E 显示最近修改的文件&lt;/p&gt;&lt;p&gt;⌘⌥← / ⌘⌥→ 退回 / 前进到上一个操作的地方&lt;/p&gt;&lt;p&gt;⌘⇧⌫ 跳转到最后一个编辑的地方&lt;/p&gt;&lt;p&gt;⌥F1 显示当前文件选择目标弹出层，弹出层中有很多目标可以进行选择(如在代码编辑窗口可以选择显示该文件的Finder)&lt;/p&gt;&lt;p&gt;⌘B / ⌘ 鼠标点击 进入光标所在的方法/变量的接口或是定义处&lt;/p&gt;&lt;p&gt;⌘⌥B 跳转到实现处，在某个调用的方法名上使用会跳到具体的实现处，可以跳过接口&lt;/p&gt;&lt;p&gt;⌘U 前往当前光标所在方法的父类的方法 / 接口定义&lt;/p&gt;&lt;p&gt;⌃J / F1 查看javadoc&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;# Refactoring（重构）&lt;/h2&gt;&lt;p&gt;F5 复制文件到指定目录&lt;/p&gt;&lt;p&gt;F6 移动文件到指定目录&lt;/p&gt;&lt;p&gt;⌘⌫ 在文件上为安全删除文件，弹出确认框&lt;/p&gt;&lt;p&gt;⇧F6 重命名文件&lt;/p&gt;&lt;p&gt;⌘F6 更改签名&lt;/p&gt;&lt;p&gt;⌘⌥M 将选中的代码提取为方法&lt;/p&gt;&lt;p&gt;⌘⌥V 提取变量&lt;/p&gt;&lt;p&gt;⌘⌥F 提取字段&lt;/p&gt;&lt;p&gt;⌘⌥C 提取常量&lt;/p&gt;&lt;p&gt;⌘⌥P 提取参数&lt;/p&gt;</content:encoded>
      <pubDate>Mon, 13 Jun 2022 05:51:00 GMT</pubDate>
    </item>
    <item>
      <title>阿里云云服务器ECS磁盘扩容</title>
      <link>https://cliveyuan.cn/article/77</link>
      <content:encoded>&lt;p&gt;&lt;a href="https://help.aliyun.com/document_detail/111738.htm?spm=a2c4g.11186623.0.0.a6fa2580mHuy0v#concept-ocb-htw-dhb" target="_blank"&gt;官方教程&lt;/a&gt;&lt;/p&gt; &lt;h1&gt;磁盘扩容&lt;/h1&gt; &lt;p&gt;&lt;img src="https://cliveyuan.cn/upload/2023/05/32qdkv556mhsfp9d08v53qbkej.png" alt="alt" title="alt" /&gt; &lt;img src="https://cliveyuan.cn/upload/2023/05/v2ob8usd9ihe1rne71ke4qtre1.png" alt="alt" title="alt" /&gt;&lt;/p&gt; &lt;h1&gt;查看系统磁盘占用情况&lt;/h1&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;df -h &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;实际步骤&lt;/h3&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;yum install gdisk -y yum install cloud-utils-growpart xfsprogs -y growpart /dev/vda 1 resize2fs /dev/vda1 &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Thu, 09 Jun 2022 01:07:00 GMT</pubDate>
    </item>
    <item>
      <title>常用快捷键整理</title>
      <link>https://cliveyuan.cn/article/shortcut-key</link>
      <content:encoded>&lt;h2&gt;&lt;center&gt;#列编辑&lt;/center&gt;&lt;/h2&gt; &lt;h3&gt;sublime Text&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;windows: &lt;code&gt;Ctrl+Shift+L&lt;/code&gt;&lt;/li&gt; &lt;li&gt;mac: &lt;code&gt;⌘+Shift+L&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;IDEA&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;windows: &lt;code&gt;Alt+shift+Insert&lt;/code&gt;&lt;/li&gt; &lt;li&gt;mac: &lt;code&gt;⌘+Shift+8&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;hr /&gt; &lt;h2&gt;&lt;center&gt;选择相同项&lt;/center&gt;&lt;/h2&gt; &lt;h3&gt;sublime Text&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;windows: &lt;code&gt;Alt+F3&lt;/code&gt;&lt;/li&gt; &lt;li&gt;mac: &lt;code&gt;Ctrl+⌘+G&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;IDEA&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;windows: &lt;code&gt;Ctrl+Alt+shift+J&lt;/code&gt;&lt;/li&gt; &lt;li&gt;mac: &lt;code&gt;Ctrl+⌘+G&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;hr /&gt; &lt;h2&gt;统一设置快捷键&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;选中列编辑(Add Cursors to Line Ends): &lt;code&gt;cmd+shift+L&lt;/code&gt; &lt;code&gt;alt+shift+L&lt;/code&gt;&lt;/li&gt; &lt;li&gt;选中相同项(Select All Occurrences of Find Match): &lt;code&gt;cmd+ctrl+G&lt;/code&gt;  &lt;code&gt;ctrl+alt+G&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt;</content:encoded>
      <pubDate>Fri, 14 Jan 2022 09:19:00 GMT</pubDate>
    </item>
    <item>
      <title>jar 命令的使用</title>
      <link>https://cliveyuan.cn/article/jar</link>
      <content:encoded>&lt;h1&gt;jar 命令&lt;/h1&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;Usage: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ... Options:     -c  create new archive     -t  list table of contents for archive     -x  extract named (or all) files from archive     -u  update existing archive     -v  generate verbose output on standard output     -f  specify archive file name     -m  include manifest information from specified manifest file     -n  perform Pack200 normalization after creating a new archive     -e  specify application entry point for stand-alone application          bundled into an executable jar file     -0  store only; use no ZIP compression     -P  preserve leading '/' (absolute path) and &amp;quot;..&amp;quot; (parent directory) components from file names     -M  do not create a manifest file for the entries     -i  generate index information for the specified jar files     -C  change to the specified directory and include the following file If any file is a directory then it is processed recursively. The manifest file name, the archive file name and the entry point name are specified in the same order as the 'm', 'f' and 'e' flags.  Example 1: to archive two class files into an archive called classes.jar:         jar cvf classes.jar Foo.class Bar.class  Example 2: use an existing manifest file 'mymanifest' and archive all the            files in the foo/ directory into 'classes.jar':         jar cvfm classes.jar mymanifest -C foo/ . &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;解压jar包&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;jar xvf app.jar &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;打包jar包&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;jar cvf0M app.jar BOOT-INF META-INF org &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Mon, 25 Oct 2021 10:08:00 GMT</pubDate>
    </item>
    <item>
      <title>MySQL多库数据备份</title>
      <link>https://cliveyuan.cn/article/70</link>
      <content:encoded>&lt;pre&gt;&lt;code&gt;mysqldump -uroot -p*** --databases prod_sl prod_yq prod_xw prod_hy prod_jl prod_zj prod_ww prod_hn | gzip &amp;gt; /home/backup/mysql/prod.sql.gz  &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Fri, 22 Oct 2021 06:17:00 GMT</pubDate>
    </item>
    <item>
      <title>Nginx 常用配置</title>
      <link>https://cliveyuan.cn/article/nginx</link>
      <content:encoded>&lt;h2&gt;通道断开问题 Broken pipe&lt;/h2&gt; &lt;h3&gt;Nginx 配置&lt;/h3&gt; &lt;pre&gt;&lt;code&gt;    location / {       proxy_pass http://localhost:8004/api/;       client_max_body_size 100m;       proxy_set_header X-Real-IP $remote_addr;       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;       # 这是关键       proxy_ignore_client_abort   on;     } &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如果没解决？&lt;/p&gt; &lt;h3&gt;Exceptionhandler&lt;/h3&gt; &lt;pre&gt;&lt;code class="language-java"&gt;if (&amp;quot;org.apache.catalina.connector.ClientAbortException&amp;quot;.equals(ex.getClass().getName())) {             return null; } &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Thu, 07 Oct 2021 15:11:00 GMT</pubDate>
    </item>
    <item>
      <title>IntelliJ IDEA 技巧</title>
      <link>https://cliveyuan.cn/article/intellij-idea</link>
      <content:encoded>&lt;h2&gt;常用插件&lt;/h2&gt; &lt;h3&gt;IDEA背景图片: &lt;code&gt;Background Image Plus&lt;/code&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;给IDEA设置背景图片&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;MyBatis插件: &lt;code&gt;Free Mybatis plugin&lt;/code&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;生成mapper xml文件&lt;/li&gt; &lt;li&gt;快速从代码跳转到mapper及从mapper返回代码&lt;/li&gt; &lt;li&gt;mybatis自动补全及语法错误提示&lt;/li&gt; &lt;li&gt;集成mybatis generator gui界面&lt;/li&gt; &lt;li&gt;根据数据库注解，生成swagger model注解&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;Setter生成器: &lt;code&gt;GenerateAllSetter&lt;/code&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;一键调用一个对象的所有的set方法&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;IDE无限试用: &lt;code&gt;IDE eval Reset&lt;/code&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;https://zhile.io/2020/11/18/jetbrains-eval-reset-da33a93d.html&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;力扣算法题: &lt;code&gt;LeetCode Editor&lt;/code&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;支持leetcode.com和leetcode-cn.com,可测试与提交问题&lt;/li&gt; &lt;li&gt;更多的插件使用教程： &lt;a href="https://github.com/shuzijun/leetcode-editor" target="_blank"&gt;插件使用介绍&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;Maven Helper&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;easy way for analyzing and excluding conflicting dependencies&lt;/li&gt; &lt;li&gt;actions to run/debug maven goals for a module that contains the current file or on the root module&lt;/li&gt; &lt;li&gt;action to open terminal at the current maven module path&lt;/li&gt; &lt;li&gt;actions to run/debug the current test file.&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;Vue.js&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Open your Vue.js project.&lt;/li&gt; &lt;li&gt;Make sure you have Vue.js listed in your project dependencies in package.json and it is installed.&lt;/li&gt; &lt;li&gt;Now, you will get Vue-specific code completion, navigation, and many other features in .vue files.&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;CamelCase&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;驼峰格式转换&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;Translation&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;翻译&lt;/li&gt; &lt;/ul&gt; &lt;hr /&gt; &lt;h2&gt;初始配置&lt;/h2&gt; &lt;h3&gt;&lt;code&gt;Setting&amp;gt;Editor&amp;gt;General&lt;/code&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;Code Completion&lt;/code&gt; 代码提示非首字母&lt;/li&gt; &lt;li&gt;&lt;code&gt;Auto Import&lt;/code&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;Add Unambiguous imports on the fly&lt;/code&gt;: IntelliJ IDEA 将在我们书写代码的时候自动帮我们导入需要用到的包。但是对于那些同名的包，还是需要手动 Alt + Enter 进行导入的，IntelliJ IDEA 目前还无法智能到替我们做判断&lt;/li&gt; &lt;li&gt;&lt;code&gt;Optimize imports on the fly&lt;/code&gt;: IntelliJ IDEA 将在我们书写代码的时候自动帮我们优化导入的包，比如自动去掉一些没有用到的包&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;code&gt;Appearance&lt;/code&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;Show line numbers&lt;/code&gt; 显示行数&lt;/li&gt; &lt;li&gt;&lt;code&gt;Show method separators&lt;/code&gt; 显示方法线&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;&lt;code&gt;Setting&amp;gt;Editor&amp;gt;CopyRight&lt;/code&gt; 添加版权&lt;/h3&gt; &lt;h2&gt;实现方法体添加TODO&lt;/h2&gt; &lt;p&gt;路径：&lt;code&gt;Settings-&amp;gt;Editor-&amp;gt;File and Code Templates-&amp;gt;Code&lt;/code&gt; 修改：&lt;code&gt;Implemented Method Body&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code&gt;// TODO: Implements me &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Sat, 25 Sep 2021 07:26:00 GMT</pubDate>
    </item>
    <item>
      <title>MySQL查询~ 存在一个表而不在另一个表中的数据</title>
      <link>https://cliveyuan.cn/article/65</link>
      <content:encoded>&lt;div id="cnblogs_post_body" class="blogpost-body blogpost-body-html" style="margin-bottom: 20px; word-break: break-word; color: rgb(75, 75, 75); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; font-size: 13px;"&gt;&lt;p style="line-height: 1.5; margin: 10px auto;"&gt;A、B两表，找出ID字段中，存在A表，但是不存在B表的数据。A表总共13w数据，去重后大约3W条数据，B表有2W条数据，且B表的ID字段有索引。&lt;/p&gt;&lt;h2 style="font-size: 21px; font-weight: bold; line-height: 1.5;"&gt;&lt;a name="t0"&gt;&lt;/a&gt;方法一&lt;/h2&gt;&lt;p style="line-height: 1.5; margin: 10px auto;"&gt;　　使用 not in ,容易理解,效率低&amp;nbsp; ~执行时间为：1.395秒~&lt;/p&gt;&lt;div class="cnblogs_code" style="background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;1 select distinct A.ID from  A where A.ID not in (select ID from B)&lt;/pre&gt;&lt;/div&gt;&lt;h2 style="font-size: 21px; font-weight: bold; line-height: 1.5;"&gt;&lt;a name="t1"&gt;&lt;/a&gt;方法二&lt;/h2&gt;&lt;p style="line-height: 1.5; margin: 10px auto;"&gt;　　使用 left join...on... , "B.ID&amp;nbsp;&lt;span class="kwrd" style="line-height: 1.5;"&gt;isnull" 表示左连接之后在B.ID 字段为 null的记录&amp;nbsp; ~执行时间：0.739秒~&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;1 select A.ID from A left join B on A.ID=B.ID where B.ID is null&lt;/pre&gt;&lt;/div&gt;&lt;p style="line-height: 1.5; margin: 10px auto;"&gt;　　图解&lt;br&gt;&lt;/p&gt;&lt;p style="line-height: 1.5; margin: 10px auto;"&gt;&lt;img src="https://cliveyuan.cn/upload/2021/08/7aipp5h968heerf3oe20afb1tr.png" style="width: 873px;"&gt;&lt;br&gt;&lt;/p&gt;&lt;h2 style="font-size: 21px; font-weight: bold; line-height: 1.5;"&gt;&lt;a name="t2"&gt;&lt;/a&gt;方法三&lt;/h2&gt;&lt;p style="line-height: 1.5; margin: 10px auto;"&gt;　　逻辑相对复杂,但是速度最快&amp;nbsp; ~执行时间: 0.570秒~&lt;/p&gt;&lt;div class="cnblogs_code" style="background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; color: rgb(0, 0, 0); font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;1  select * from  B  2     where (select count(&lt;strong&gt;1&lt;/strong&gt;) as num from A where A.ID = B.ID) = &lt;strong&gt;0&lt;/strong&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded>
      <pubDate>Mon, 23 Aug 2021 03:16:00 GMT</pubDate>
    </item>
    <item>
      <title>解决Java调用 InetAddress.getLocalHost() 非常慢</title>
      <link>https://cliveyuan.cn/article/64</link>
      <content:encoded>&lt;p&gt;在java中获取本机服务器ip时调用了&lt;/p&gt; &lt;pre&gt;&lt;code class="language-java"&gt;InetAddress.getLocalHost() &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;有的时候会非常耗时，特别是服务器上，这个时候这样配置下就能解决问题&lt;/p&gt; &lt;ol&gt; &lt;li&gt;首先，查看主机名：&lt;/li&gt; &lt;/ol&gt; &lt;pre&gt;&lt;code&gt;hostname &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出的就是主机名，如：&lt;code&gt;centos1&lt;/code&gt; 2. 将这个主机名加入到host文件中&lt;/p&gt; &lt;pre&gt;&lt;code&gt;vim /etc/hosts &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;添加一行&lt;code&gt;127.0.0.1 centos1&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;完成&lt;/strong&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 18 Aug 2021 07:34:00 GMT</pubDate>
    </item>
    <item>
      <title>一文搞懂【密钥库】与【证书】文件格式</title>
      <link>https://cliveyuan.cn/article/63</link>
      <content:encoded>&lt;h1&gt;密钥库文件格式&lt;code&gt;keystore&lt;/code&gt;&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;格式    :   JKS 扩展名  :   .jks/.ks 描述    :   [Java Keystore]密钥库的Java实现版本，provider为SUN 特点    :   密钥库和私钥用不同的密码进行保护   格式    :   JCEKS 扩展名  :   .jce 描述    :   [JCE Keystore]密钥库的JCE实现版本，provider为SUN JCE 特点    :   相对于JKS安全级别更高，保护Keystore私钥时采用TripleDES   格式    :   PKCS12 扩展名  :   .p12/.pfx 描述    :   [PKCS #12]个人信息交换语法标准 特点    :   1、包含私钥、公钥及其证书    2、密钥库和私钥用相同密码进行保护   格式    :   BKS 扩展名  :  .bks 描述    :  Bouncycastle Keystore]密钥库的BC实现版本，provider为BC 特点    :   基于JCE实现   格式    :  UBER 扩展名  :  .ubr 描述    :  [Bouncycastle UBER Keystore]密钥库的BC更安全实现版本，provider为BC &lt;/code&gt;&lt;/pre&gt; &lt;hr /&gt; &lt;h1&gt;证书文件格式&lt;code&gt;certificate&lt;/code&gt;&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;格式    :   DER 扩展名  :   .cer/.crt/.rsa 描述    :  [ASN .1 DER]用于存放证书 特点    :   不含私钥、二进制     格式    :   PKCS7 扩展名  :  .p7b/.p7r 描述    :  [PKCS #7]加密信息语法标准 特点    :  1、p7b以树状展示证书链，不含私钥    2、p7r为CA对证书请求签名的回复，只能用于导入     格式    :   CMS 扩展名  :   .p7c/.p7m/.p7s 描述    :  [Cryptographic Message Syntax] 特点    :  1、p7c只保存证书    2、p7m：signature with enveloped data    3、p7s：时间戳签名文件   格式    :   PEM 扩展名  :  .pem 描述    :  [Printable Encoded Message] 特点    :  1、该编码格式在RFC1421中定义，其实PEM是[Privacy-Enhanced Mail]的简写，但他也同样广泛运用于密钥管理    2、ASCII文件    3、一般基于base 64编码     格式    :   PKCS10 扩展名  :  .p10/.csr 描述    :  [PKCS #10]公钥加密标准[Certificate Signing Request] 特点    :   1、证书签名请求文件    2、ASCII文件    3、CA签名后以p7r文件回复     格式    :   SPC 扩展名  :  .pvk/.spc 描述    :  [Software Publishing Certificate] 特点    :   微软公司特有的双证书文件格式，经常用于代码签名，其中    1、pvk用于保存私钥    2、spc用于保存公钥  &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;crt格式证书转为RSA公钥&lt;/h1&gt; &lt;pre&gt;&lt;code class="language-java"&gt;        Security.addProvider(new BouncyCastleProvider());         String path = &amp;quot;/Users/cliveyuan/data/keys/xxx.crt&amp;quot;;         CertificateFactory cf = CertificateFactory.getInstance(&amp;quot;X.509&amp;quot;, &amp;quot;BC&amp;quot;);         X509Certificate cert = (X509Certificate) cf.generateCertificate(new FileInputStream(path));         PublicKey publicKey = cert.getPublicKey();         String publicKeyString = Base64.encodeBase64String(publicKey.getEncoded());         System.out.println(publicKeyString); &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Tue, 10 Aug 2021 09:05:00 GMT</pubDate>
    </item>
    <item>
      <title>搭建email服务器</title>
      <link>https://cliveyuan.cn/article/62</link>
      <content:encoded>&lt;p&gt;&lt;a href="https://docs.iredmail.org/install.iredmail.on.rhel-zh_CN.html" target="_blank"&gt;https://docs.iredmail.org/install.iredmail.on.rhel-zh_CN.html&lt;/a&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Tue, 10 Aug 2021 03:34:00 GMT</pubDate>
    </item>
    <item>
      <title>前端框架vant整合mockJs踩坑之旅</title>
      <link>https://cliveyuan.cn/article/61</link>
      <content:encoded>&lt;blockquote&gt; &lt;p&gt;背景: 最近看上一个前端框架vant,它是移动端UI框架,整合一些常用的功能来做一个开源的移动端UI脚手架&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;项目地址: &lt;a href="https://gitee.com/opensource4clive/vant-demo" target="_blank"&gt;vant-demo&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;一切都很顺利的时候, 启动mock时报错,各种调试,各种改依赖包版本号, 辗转了解了babel的作用,最后还是没能解决,几经放弃. 后来搜索资料发现一个配置搞掉了...&lt;/p&gt; &lt;pre&gt;&lt;code&gt;VUE_CLI_BABEL_TRANSPILE_MODULES = true &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;还是这篇文章启发了我, 表示非常感谢,不然今晚可能无眠了! &lt;a href="https://wangxiaoting.blog.csdn.net/article/details/111952731" target="_blank"&gt;vue运行报错：SyntaxError: Cannot use import statement outside a module&lt;/a&gt;&lt;/p&gt; &lt;p&gt;结语: &lt;strong&gt;千里之堤溃于蚁穴&lt;/strong&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Fri, 06 Aug 2021 17:39:00 GMT</pubDate>
    </item>
    <item>
      <title>MySQL中的悲观锁与常见的死锁场景</title>
      <link>https://cliveyuan.cn/article/mysql-deadlock</link>
      <content:encoded>&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;在MySQL中， 锁机制是并发条件下保护数据一致性与稳定性的一个非常重要的机制， 并且事务的实现也依赖于于锁机制。 其锁定的数据不单包括数据行记录， 同时也包括缓冲池中的LRU列表数据、日志数据等。 悲观锁(FOR UPDATE)则是日常开发中使用最多的一种锁， 但是， 由于事务隔离级别的多样性导致了悲观锁在使用时常常会有不同的表现， 死锁在程序员稍不注意时就会发生。&lt;/p&gt;&lt;h4 id="1-悲观锁概述" style="font-feature-settings: &amp;quot;dlig&amp;quot;, &amp;quot;liga&amp;quot;, &amp;quot;lnum&amp;quot;, &amp;quot;kern&amp;quot;; color: rgb(46, 46, 46); line-height: 1.15em; margin-top: 0px; margin-bottom: 0.4em; font-family: &amp;quot;Open Sans&amp;quot;, sans-serif; text-rendering: geometricprecision; font-size: 2.5rem; letter-spacing: 0.1px;"&gt;1. 悲观锁概述&lt;/h4&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;在通用的程序设计语言中， 锁通常是基于某一个对象， 或者是一组对象而言。 在Python、Java和Golang中， 分别提供了&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;threading.Lock&lt;/code&gt;、&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;synchronized&lt;/code&gt;以及&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;sync.Mutex&lt;/code&gt;互斥所机制。 而数据库要更为特殊一些， 其原因就在于我们所管理的不是一个个的对象， 而是一行行的数据。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;InnoDB存储引擎支持的最小锁粒度为行锁， 可以通过在事务中执行&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;SELECT .. FOR UPDATE&lt;/code&gt;为某一行或者是多行数据添加互斥锁。 锁的生命周期完全由InnoDB管理， 当事务成功提交或者是失败回滚时， 互斥锁则自动释放。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;需要注意的一点是， 互斥锁必须在事务中执行才会生效。 当&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;autocommit&lt;/code&gt;为&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;ON&lt;/code&gt;时， 需要显示的使用&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;BEGIN&lt;/code&gt;开启事务， 而后对数据添加互斥锁。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;在程序设计语言中， 锁的目的是串行化修改、删除操作， InnoDB中的互斥锁有着同样的目的。 但是， 由于事务隔离级别的分类， 使得互斥锁的行为变得复杂许多。 其中最让人感到迷惑的就是为了解决幻读问题所添加的&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;GAP Lock&lt;/code&gt;。&lt;/p&gt;&lt;h4 id="2-事务隔离级别概述" style="font-feature-settings: &amp;quot;dlig&amp;quot;, &amp;quot;liga&amp;quot;, &amp;quot;lnum&amp;quot;, &amp;quot;kern&amp;quot;; color: rgb(46, 46, 46); line-height: 1.15em; margin-top: 0px; margin-bottom: 0.4em; font-family: &amp;quot;Open Sans&amp;quot;, sans-serif; text-rendering: geometricprecision; font-size: 2.5rem; letter-spacing: 0.1px;"&gt;2. 事务隔离级别概述&lt;/h4&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;不同的事务隔离级别， 悲观锁会产生不同的行为。 所以， 理解事务隔离级别是理解悲观锁的第一步。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;InnoDB事务隔离级别从低到高依次为未提交读(READ UNCOMMITED)， 提交读(READ COMMITED)， 可重复读(READ REPEATABLE)以及串行化(SERIALIZABLE)。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;未提交读指的是事务B可以读取到事务A未提交的数据， 此时若事务A回滚， 那么事务B读到的就是错误数据， 也称为脏数据。 该读取行为有时也会被称为脏读， 因为未提交读会导致脏读的问题， 从而导致数据混乱， 所以该事务隔离级别基本不会被使用。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;img src="https://smartkeyerror.oss-cn-shenzhen.aliyuncs.com/jojo/system-design/mysql/lock/read-uncommitted-with-dirty-data.png" alt="" style="display: block; max-width: 100%; height: auto; padding: 0.6em 0px; position: relative; left: 600px; transform: translateX(-50%);"&gt;&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;提交读是指在执行事务B时， 可以读取到事务A提交到的数据， 未提交的数据不可读取。 提交读解决了脏读的问题， 读取到的数据一定是已经持久化至磁盘的数据， 但是会出现同一条SQL语句在执行时出现不一致的情况。 例如事务A、B先后开始执行， 事务A首先读取row-1的内容， 而此时事务B对row-1的内容修改并提交， 此时事务A再次读取row-1数据， 发现其已经发生改变， 而该变化并不是事务A自身进行的。 这种情况又称为不可重复读。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;img src="https://smartkeyerror.oss-cn-shenzhen.aliyuncs.com/jojo/system-design/mysql/lock/Read-Committed.png" alt="" style="display: block; max-width: 100%; height: auto; padding: 0.6em 0px; position: relative; left: 600px; transform: translateX(-50%);"&gt;&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;可重复读， 顾名思义， 解决了提交读的不可重复读问题， 使得事务在读取同一行数据时， 结果并不会因为其它事务的执行而发生改变， 数据发生的修改行为在整个事务内是可以自恰的。 但是并没有解决幻读的问题， 幻读是指其余事务在某一个区间内插入数据， 而非修改数据， 此时事务也会读取到这部分插入的数据。 InnoDB借助MVCC(多版本并发控制)以及锁机制来解决幻读问题。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;MVCC即在数据中添加版本号， 数据插入时会有初始版本号， 在修改、删除时更新版本号。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;img src="https://smartkeyerror.oss-cn-shenzhen.aliyuncs.com/jojo/system-design/mysql/lock/Repeatable-Read.png" alt="" style="display: block; max-width: 100%; height: auto; padding: 0.6em 0px; position: relative; left: 600px; transform: translateX(-50%);"&gt;&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;串行化指事务串行化执行， 自然就不会有出现上述出现的脏读、不可重复读以及幻读了。 一个很重要的事实是， 串行化的事务隔离级别执行效率并不会比可重复读事务隔离级别差很多。 同样的， 提交读执行效率也不会比可重复读执行效率高多少， 所以在优化数据库时， 事务隔离级别不应该是效率优化目标， 而是业务优化目标。&lt;/p&gt;&lt;h4 id="3-mysql中的锁" style="font-feature-settings: &amp;quot;dlig&amp;quot;, &amp;quot;liga&amp;quot;, &amp;quot;lnum&amp;quot;, &amp;quot;kern&amp;quot;; color: rgb(46, 46, 46); line-height: 1.15em; margin-top: 0px; margin-bottom: 0.4em; font-family: &amp;quot;Open Sans&amp;quot;, sans-serif; text-rendering: geometricprecision; font-size: 2.5rem; letter-spacing: 0.1px;"&gt;3. MySQL中的锁&lt;/h4&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;使用&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;FOR UPDATE&lt;/code&gt;对某一行或者是多行数据添加的锁， 其实是由MySQL更细粒度的锁组合而成的， 不同的事务隔离级别有不同的组合方式。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;在InnoDB存储引擎中， 存在3种行锁的算法， 其分别为:&lt;/p&gt;&lt;ul style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-right: 0px; margin-bottom: 1.75em; margin-left: 0px; text-rendering: geometricprecision; padding-left: 3rem; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;li style="margin: 0.4em 0px;"&gt;Record Lock: 单个行记录上的锁，聚集索引及辅助索引均会添加锁。&lt;/li&gt;&lt;li style="margin: 0.4em 0px;"&gt;Gap Lock: 间隙锁， 锁定一个范围， 但不包含行记录本身。&lt;/li&gt;&lt;li style="margin: 0.4em 0px;"&gt;Next-Key Lock: Record Lock + Gap Lock，锁定行记录本身并且锁定一个范围。&lt;/li&gt;&lt;/ul&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;下面用一个实际的例子来解释Record Lock以及Gap Lock。 首先表结构定义如下:&lt;/p&gt;&lt;div class="language-sql highlighter-rouge" style="color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;div class="highlight" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;pre class="highlight" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.9em; margin-bottom: 1.75em; border-color: rgb(227, 237, 243); width: 1200px; padding: 10px; background: rgb(39, 40, 34); border-radius: 3px; color: rgb(255, 255, 255);"&gt;&lt;code class="hljs sql" style="font-family: Inconsolata, monospace, sans-serif; font-size: 15px; padding: 0.5em; border: none; background: rgb(35, 36, 31); border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(248, 248, 242); display: block; overflow-x: auto;"&gt;&lt;span class="k" style="color: rgb(249, 38, 114);"&gt;CREATE&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;TABLE&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;lock_test&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;   &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-keyword" style="color: rgb(249, 38, 114);"&gt;id&lt;/span&gt;&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-built_in" style="color: rgb(230, 219, 116);"&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi" style="color: rgb(174, 129, 255);"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;NOT&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;&lt;span class="hljs-literal" style="color: rgb(174, 129, 255);"&gt;NULL&lt;/span&gt;&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;a&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-built_in" style="color: rgb(230, 219, 116);"&gt;varchar&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi" style="color: rgb(174, 129, 255);"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;NOT&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;&lt;span class="hljs-literal" style="color: rgb(174, 129, 255);"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;PRIMARY&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-keyword" style="color: rgb(249, 38, 114);"&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;   &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-keyword" style="color: rgb(249, 38, 114);"&gt;ENGINE&lt;/span&gt;&lt;/span&gt;&lt;span class="o" style="color: rgb(249, 38, 114);"&gt;=&lt;/span&gt;&lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-keyword" style="color: rgb(249, 38, 114);"&gt;InnoDB&lt;/span&gt;&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;DEFAULT&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-keyword" style="color: rgb(249, 38, 114);"&gt;CHARSET&lt;/span&gt;&lt;/span&gt;&lt;span class="o" style="color: rgb(249, 38, 114);"&gt;=&lt;/span&gt;&lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;latin1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;p&gt;&lt;span class="c1" style="color: rgb(117, 113, 94);"&gt;-- 插入部分测试数据&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;insert&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;into&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;lock_test&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-string" style="color: rgb(230, 219, 116);"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;insert&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;into&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;lock_test&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-string" style="color: rgb(230, 219, 116);"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;insert&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;into&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;lock_test&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-string" style="color: rgb(230, 219, 116);"&gt;&amp;quot;5&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;insert&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;into&lt;/span&gt; &lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;lock_test&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k" style="color: rgb(249, 38, 114);"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv" style="color: rgb(255, 255, 255); background-color: rgb(39, 40, 34);"&gt;&lt;span class="hljs-string" style="color: rgb(230, 219, 116);"&gt;&amp;quot;8&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;接着执行下面的语句:&lt;/p&gt;&lt;table style="margin: 1.75em 0px; width: 1200px; max-width: 100%; background-color: rgb(255, 255, 255); color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;时间&lt;/th&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;会话A&lt;/th&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;会话B&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;1&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;BEGIN;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;2&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “5” FOR UPDATE;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;3&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;BEGIN;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;4&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;INSERT INTO lock_test (a) VALUES (“4”);&lt;br&gt;阻塞，等待会话A事务的提交&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;5&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;COMMIT;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;Query OK, 1 row affected (6.87 sec)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;尽管列&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;a&lt;/code&gt;添加了辅助索引， 但是在对该列使用&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;FOR UPDATE&lt;/code&gt;添加悲观锁时， 仍然会出现其它列被锁定的现象。 这是因为&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;a = &amp;quot;5&amp;quot;&lt;/code&gt;该行数据不仅被添加了Record Lock， 并且也添加了Gap Lock， 其目的就是为了解决幻读问题， 前提是当前事务隔离级别为REPEATABLE READ。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;在列&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;a&lt;/code&gt;的辅助索引中， 值”5”之前的值为”3”， 故存在(3, 5)这个间隙， 所以在插入值”4”时， InnoDB为了杜绝幻读现象的发生， 使得只有在会话A事务提交时才允许插入操作的进行。 另外一点需要注意的是， 当查询的索引具有唯一属性时， InnoDB存储引擎会对Next-Key Lock进行优化， 将其降级为Record Lock， 即仅锁住索引本身， 而不锁定一个范围。&lt;/p&gt;&lt;blockquote style="margin-top: 1.75em; margin-bottom: 1.75em; margin-left: -2.2em; padding: 0px 0px 0px 1.75em; border-left-width: 0.4em; border-left-color: rgb(74, 74, 74); color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0.8em; margin-bottom: 0.8em; text-rendering: geometricprecision; font-style: italic;"&gt;For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it.&lt;/p&gt;&lt;/blockquote&gt;&lt;h4 id="4-锁与事务之间的关联" style="font-feature-settings: &amp;quot;dlig&amp;quot;, &amp;quot;liga&amp;quot;, &amp;quot;lnum&amp;quot;, &amp;quot;kern&amp;quot;; color: rgb(46, 46, 46); line-height: 1.15em; margin-top: 0px; margin-bottom: 0.4em; font-family: &amp;quot;Open Sans&amp;quot;, sans-serif; text-rendering: geometricprecision; font-size: 2.5rem; letter-spacing: 0.1px;"&gt;4. 锁与事务之间的关联&lt;/h4&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;前面提到了Gap Lock的存在主要是为了解决幻读问题的发生， 而在READ COMMITTED事务隔离级别中， 只解决了脏读问题， 所以说， 在该事务隔离级别下， &lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;FOR UPDATE&lt;/code&gt;仅会添加Record Lock， 并不会添加Gap Lock。&lt;/p&gt;&lt;blockquote style="margin-top: 1.75em; margin-bottom: 1.75em; margin-left: -2.2em; padding: 0px 0px 0px 1.75em; border-left-width: 0.4em; border-left-color: rgb(74, 74, 74); color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0.8em; margin-bottom: 0.8em; text-rendering: geometricprecision; font-style: italic;"&gt;For locking reads (SELECT with FOR UPDATE or FOR SHARE), UPDATE statements, and DELETE statements, InnoDB locks only index records, not the gaps before them.&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote style="margin-top: 1.75em; margin-bottom: 1.75em; margin-left: -2.2em; padding: 0px 0px 0px 1.75em; border-left-width: 0.4em; border-left-color: rgb(74, 74, 74); color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0.8em; margin-bottom: 0.8em; text-rendering: geometricprecision; font-style: italic;"&gt;Because gap locking is disabled, phantom problems may occur, as other sessions can insert new rows into the gaps&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;此外， 如果用户通过索引查询一个值， 并在其之上添加排它锁， 当查询的值不存在时， READ COMMITTED与REPEATABLE READ两个事务隔离级别所产生的行为同样存在差异， 一个最直观的差异就是REPEATABLE READ在并发条件下会产生死锁， 而READ COMMITTED则不会。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;READ COMMITTED事务隔离级别:&lt;/p&gt;&lt;table style="margin: 1.75em 0px; width: 1200px; max-width: 100%; background-color: rgb(255, 255, 255); color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;时间&lt;/th&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;会话A&lt;/th&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;会话B&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;1&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;BEGIN;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;2&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “100” FOR UPDATE;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;3&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;BEGIN;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;4&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “100” FOR UPDATE;&lt;br&gt;不会被阻塞&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;5&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;INSERT INTO lock_test (a) VALUES (“100”);&lt;br&gt;不会被阻塞&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;6&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;INSERT INTO lock_test (a) VALUES (“100”);&lt;br&gt;不会被阻塞&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;7&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;COMMIT;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;8&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;COMMIT;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;所以说， 当事务隔离级别为READ COMMITTED时， 无法使用Next-Key Lock来帮助我们实现类似于&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;update_or_create&lt;/code&gt;或者是&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;get_or_create&lt;/code&gt;等方法， 因为在并发条件下会造成重复数据创建， 除非表中存在唯一索引。 这也是Django框架官网中所提到的Multiply records问题。 感兴趣的小伙伴可访问官网获取更多详细内容:&lt;/p&gt;&lt;blockquote style="margin-top: 1.75em; margin-bottom: 1.75em; margin-left: -2.2em; padding: 0px 0px 0px 1.75em; border-left-width: 0.4em; border-left-color: rgb(74, 74, 74); color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0.8em; margin-bottom: 0.8em; text-rendering: geometricprecision; font-style: italic;"&gt;https://docs.djangoproject.com/en/2.2/ref/models/querysets/#get-or-create&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;REPEATABLE READ事务隔离级别:&lt;/p&gt;&lt;table style="margin: 1.75em 0px; width: 1200px; max-width: 100%; background-color: rgb(255, 255, 255); color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;时间&lt;/th&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;会话A&lt;/th&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;会话B&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;1&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;BEGIN;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;2&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “200” FOR UPDATE;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;3&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;BEGIN;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;4&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “200” FOR UPDATE;&lt;br&gt;不会被阻塞&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;5&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;INSERT INTO lock_test (a) VALUES (“200”);&lt;br&gt;阻塞, 等待事务B的结束&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;6&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;INSERT INTO lock_test (a) VALUES (“200”);&lt;br&gt;ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction，死锁发生&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;当在REPEATABLE READ事务隔离级别级别下实现&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;get_or_create&lt;/code&gt;方法时，会产生死锁问题， 原因就在于锁定的记录并不存在， 多个事务可同时对其添加悲观锁， 但是插入语句的执行位置是不确定的， 所以就会有死锁问题的出现。解决此类问题的一个方法就是使用指数退避方式的重试。&lt;/p&gt;&lt;h4 id="5-死锁" style="font-feature-settings: &amp;quot;dlig&amp;quot;, &amp;quot;liga&amp;quot;, &amp;quot;lnum&amp;quot;, &amp;quot;kern&amp;quot;; color: rgb(46, 46, 46); line-height: 1.15em; margin-top: 0px; margin-bottom: 0.4em; font-family: &amp;quot;Open Sans&amp;quot;, sans-serif; text-rendering: geometricprecision; font-size: 2.5rem; letter-spacing: 0.1px;"&gt;5. 死锁&lt;/h4&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;通常来讲， 如果我们的SQL执行计划较为简单， 几乎所有的执行均为单条语句执行时， 死锁基本与我们无关。 但是当执行计划稍加复杂， 事务执行的语句较多时， 就会出现死锁问题。 一个最经典的死锁场景即为AB-BA死锁。&lt;/p&gt;&lt;table style="margin: 1.75em 0px; width: 1200px; max-width: 100%; background-color: rgb(255, 255, 255); color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;时间&lt;/th&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;会话A&lt;/th&gt;&lt;th style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 0px; color: rgb(0, 0, 0);"&gt;会话B&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;1&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;BEGIN;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;2&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “200” FOR UPDATE;&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;3&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;BEGIN;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;4&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “400” FOR UPDATE;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;5&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “400” FOR UPDATE&lt;br&gt;阻塞, 等待事务B的结束&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239); background-color: rgb(246, 246, 246);"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;6&lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt; &lt;/td&gt;&lt;td style="padding: 8px; line-height: 20px; vertical-align: top; border-top: 1px solid rgb(239, 239, 239);"&gt;SELECT * FROM lock_test&lt;br&gt;WHERE a = “200” FOR UPDATE;&lt;br&gt;ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction，死锁发生&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;当MySQL检测到死锁时， 会根据其事务权重选择性的回滚其中一个事务。 但是， 权重的判定完全由MySQL决定， 业务系统无法人为的干预， 如果某一个事务在业务系统中非常重要， 但是MySQL却回滚了该事务， 而业务系统仅捕捉了该异常并向外扩散的话， 并不是我们期望的结果。 所以， 在绝大多数场景下， 指数退避的重试策略要更好一些。 或者对于关键性的业务逻辑， 使用Redis等消息队列进行串行化操作。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;另外一个死锁场景则是上一小节中我们所见到的并发执行&lt;code class="highlighter-rouge" style="font-family: Inconsolata, monospace, sans-serif; font-size: 0.85em; padding: 1px 3px; white-space: pre-wrap; border: 1px solid rgb(227, 237, 243); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 2px; font-feature-settings: &amp;quot;liga&amp;quot; 0; color: rgb(221, 75, 57);"&gt;if not exist then create&lt;/code&gt;模式所带来的死锁问题， 该模式在业务场景下其实非常常见。&lt;/p&gt;&lt;p style="font-feature-settings: &amp;quot;liga&amp;quot;, &amp;quot;onum&amp;quot;, &amp;quot;kern&amp;quot;; margin-top: 0px; margin-bottom: 1.75em; text-rendering: geometricprecision; color: rgb(58, 65, 69); font-family: Merriweather, serif; font-size: 18px; letter-spacing: 0.1px;"&gt;&lt;br&gt;&lt;/p&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Fri, 16 Jul 2021 08:20:00 GMT</pubDate>
    </item>
    <item>
      <title>Linux 常用脚本</title>
      <link>https://cliveyuan.cn/article/linux-scripts</link>
      <content:encoded>&lt;h1&gt;查看系统磁盘占用情况&lt;/h1&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;df -h &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;查看文件夹大小&lt;/h1&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;du -h --max-depth=1 . &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;删除7天以前的文件夹&lt;/h1&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;find . -type d -mtime +7 -exec rm -rf {} \; # x为天数 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;查看Linux版本&lt;/h1&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;cat /etc/redhat-release &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Mon, 05 Jul 2021 10:45:00 GMT</pubDate>
    </item>
    <item>
      <title>设计模式</title>
      <link>https://cliveyuan.cn/article/design-pattern</link>
      <content:encoded>&lt;div id="arc-body" style="margin: 10px auto; line-height: 1.6em; color: rgb(68, 68, 68); font-family: &amp;quot;Helvetica Neue&amp;quot;, 微软雅黑, &amp;quot;Microsoft Yahei&amp;quot;, Helvetica, Arial, sans-serif;"&gt;下面总结一下这 23 种设计模式，以方便小伙伴们日后复习和查阅。&lt;br&gt;&lt;br&gt;&lt;table style="margin: auto; max-width: 100%;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th style="padding: 7px 5px; border: 1px solid rgb(204, 204, 204); background-color: rgb(237, 237, 237); color: rgb(68, 68, 68);"&gt;分类&lt;/th&gt;&lt;th style="padding: 7px 5px; border: 1px solid rgb(204, 204, 204); background-color: rgb(237, 237, 237); color: rgb(68, 68, 68);"&gt;设计模式&lt;/th&gt;&lt;th style="padding: 7px 5px; border: 1px solid rgb(204, 204, 204); background-color: rgb(237, 237, 237); color: rgb(68, 68, 68);"&gt;简述&lt;/th&gt;&lt;th style="padding: 7px 5px; border: 1px solid rgb(204, 204, 204); background-color: rgb(237, 237, 237); color: rgb(68, 68, 68);"&gt;一句话归纳&lt;/th&gt;&lt;th style="padding: 7px 5px; border: 1px solid rgb(204, 204, 204); background-color: rgb(237, 237, 237); color: rgb(68, 68, 68);"&gt;目的&lt;/th&gt;&lt;th style="padding: 7px 5px; border: 1px solid rgb(204, 204, 204); background-color: rgb(237, 237, 237); color: rgb(68, 68, 68);"&gt;生活案例&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan="1" rowspan="4" style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;创建型设计模式&lt;br&gt;（简单来说就是用来创建对象的）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;工厂模式（Factory Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;不同条件下创建不同实例&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;产品标准化，生产更高效&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;封装创建细节&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;实体工厂&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;单例模式（Singleton Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;保证一个类仅有一个实例，并且提供一个全局访问点&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;世上只有一个我&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;保证独一无二&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;CEO&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;原型模式（Prototype Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;通过拷贝原型创建新的对象&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;拔一根猴毛，吹出千万个&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;高效创建对象&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;克隆&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;建造者模式（Builder Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;用来创建复杂的复合对象&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;高配中配和低配，想选哪配就哪配&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;开放个性配置步骤&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;选配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan="1" rowspan="7" style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;结构型设计模式&lt;br&gt;（关注类和对象的组合）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;代理模式（Proxy Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;为其他对象提供一种代理以控制对这个对象的访问&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;没有资源没时间，得找别人来帮忙&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;增强职责&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;媒婆&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;外观模式（Facade Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;对外提供一个统一的接口用来访问子系统&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;打开一扇门，通向全世界&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;统一访问入口&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;前台&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;装饰器模式（Decorator Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;为对象添加新功能&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;他大舅他二舅都是他舅&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;灵活扩展、同宗同源&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;煎饼&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;享元模式（Flyweight Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;使用对象池来减少重复对象的创建&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;优化资源配置，减少重复浪费&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;共享资源池&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;全国社保联网&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;组合模式（Composite Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;将整体与局部（树形结构）进行递归组合，让客户端能够以一种的方式对其进行处理&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;人在一起叫团伙，心在一起叫团队&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;统一整体和个体&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;组织架构树&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;适配器模式（Adapter Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;将原来不兼容的两个类融合在一起&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;万能充电器&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;兼容转换&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;电源适配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;桥接模式（Bridge Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;将两个能够独立变化的部分分离开来&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;约定优于配置&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;不允许用继承&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;桥&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan="1" rowspan="11" style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;行为型设计模式&lt;br&gt;（关注对象之间的通信）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;模板模式（Template Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;定义一套流程模板，根据需要实现模板中的操作&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;流程全部标准化，需要微调请覆盖&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;逻辑复用&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;把大象装进冰箱&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;策略模式（Strategy Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;封装不同的算法，算法之间能互相替换&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;条条大道通罗马，具体哪条你来定&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;把选择权交给用户&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;选择支付方式&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;责任链模式（Chain of Responsibility Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;拦截的类都实现统一接口，每个接收者都包含对下一个接收者的引用。将这些对象连接成一条链，并且沿着这条链传递请求，直到有对象处理它为止。&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;各人自扫门前雪，莫管他们瓦上霜&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;解耦处理逻辑&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;踢皮球&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;迭代器模式（Iterator Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;提供一种方法顺序访问一个聚合对象中的各个元素&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;流水线上坐一天，每个包裹扫一遍&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;统一对集合的访问方式&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;逐个检票进站&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;命令模式（Command Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;将请求封装成命令，并记录下来，能够撤销与重做&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;运筹帷幄之中，决胜千里之外&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;解耦请求和处理&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;遥控器&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;状态模式（State Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;根据不同的状态做出不同的行为&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;状态驱动行为，行为决定状态&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;绑定状态和行为&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;订单状态跟踪&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;备忘录模式（Memento Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;保存对象的状态，在需要时进行恢复&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;失足不成千古恨，想重来时就重来&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;备份、后悔机制&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;草稿箱&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;中介者模式（Mediator Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;将对象之间的通信关联关系封装到一个中介类中单独处理，从而使其耦合松散&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;联系方式我给你，怎么搞定我不管&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;统一管理网状资源&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;朋友圈&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;解释器模式（Interpreter Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;给定一个语言，定义它的语法表示，并定义一个解释器，这个解释器使用该标识来解释语言中的句子&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;我想说”方言“，一切解释权都归我&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;实现特定语法解析&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;摩斯密码&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;观察者模式（Observer Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;状态发生改变时通知观察者，一对多的关系&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;到点就通知我&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;解耦观察者与被观察者&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;闹钟&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;访问者模式（Visitor Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;稳定数据结构，定义新的操作行为&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;横看成岭侧成峰，远近高低各不同&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;解耦数据结构和数据操作&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;KPI考核&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;&amp;nbsp;&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;委派模式（Delegate Pattern）&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;允许对象组合实现与继承相同的代码重用，负责任务的调用和分配&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;这个需求很简单，怎么实现我不管&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;只对结果负责&lt;/td&gt;&lt;td style="padding: 5px; border: 1px solid rgb(204, 204, 204);"&gt;授权委托书&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div class="pre-next-page clearfix" style="padding: 8px 0px; color: rgb(68, 68, 68); line-height: 16px; border-bottom: 1px solid rgb(221, 221, 221); border-top: 1px solid rgb(221, 221, 221); font-family: &amp;quot;Helvetica Neue&amp;quot;, 微软雅黑, &amp;quot;Microsoft Yahei&amp;quot;, Helvetica, Arial, sans-serif;"&gt;转载于&lt;a href="http://c.biancheng.net/view/8462.html" target="_blank"&gt;http://c.biancheng.net/view/8462.html&lt;/a&gt;&lt;/div&gt;</content:encoded>
      <pubDate>Tue, 11 May 2021 05:50:00 GMT</pubDate>
    </item>
    <item>
      <title>Linux7 替换yum源</title>
      <link>https://cliveyuan.cn/article/54</link>
      <content:encoded>&lt;p&gt;替换yum源&lt;/p&gt; &lt;pre&gt;&lt;code&gt;vim /etc/yum.repos.d/epel.repo &lt;/code&gt;&lt;/pre&gt; &lt;pre&gt;&lt;code&gt;[epel] name=Extra Packages for Enterprise Linux 7 - $basearch baseurl=http://mirrors.aliyun.com/epel/7/$basearch failovermethod=priority enabled=1 gpgcheck=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7  [epel-debuginfo] name=Extra Packages for Enterprise Linux 7 - $basearch - Debug baseurl=http://mirrors.aliyun.com/epel/7/$basearch/debug failovermethod=priority enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 gpgcheck=0  [epel-source] name=Extra Packages for Enterprise Linux 7 - $basearch - Source baseurl=http://mirrors.aliyun.com/epel/7/SRPMS failovermethod=priority enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 gpgcheck=0 ~             &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Mon, 18 Jan 2021 05:25:00 GMT</pubDate>
    </item>
    <item>
      <title>如何将自己的代码发布到Maven中央仓库？</title>
      <link>https://cliveyuan.cn/article/52</link>
      <content:encoded>&lt;p&gt;转自：&lt;a href="https://www.cnblogs.com/songyz/p/11387978.html"&gt;https://www.cnblogs.com/songyz/p/11387978.html&lt;/a&gt;&lt;a href="https://www.cnblogs.com/songyz/p/11387978.html"&gt;&lt;/a&gt;&lt;/p&gt;&lt;h1 class="postTitle" style="margin-top: 0px; margin-bottom: 20px; padding: 0px; font-size: 28px; line-height: 1.8; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif;"&gt;&lt;a id="cb_post_title_url" class="postTitle2 vertical-middle" href="https://www.cnblogs.com/songyz/p/11387978.html" style="margin: 0px; padding: 0px; color: rgb(51, 51, 51);"&gt;&lt;span style="margin: 0px; padding: 0px; vertical-align: middle;"&gt;如何将自己的代码发布到Maven中央仓库？&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;div class="clear" style="margin: 0px; padding: 0px; clear: both; color: rgb(125, 139, 141); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif;"&gt;&lt;/div&gt;&lt;div class="postBody" style="margin: 0px; padding: 0px; color: rgb(125, 139, 141); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif;"&gt;&lt;div id="cnblogs_post_body" class="blogpost-body" style="margin: 0px 0px 20px; padding: 0px; word-break: break-word; color: rgb(51, 51, 51); line-height: 1.8;"&gt;&lt;blockquote style="margin-bottom: 0px; padding: 5px 10px; background: none; border-top: none; border-right: none; border-bottom: none; border-left-color: rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85);"&gt;&lt;p style="padding: 0px; color: rgb(119, 119, 119);"&gt;去年在公司做工作流相关业务时，当时使用flowable做引擎，中途涉及到一些业务上的需求，自己整理了一些代码，考虑到开源精神，当时就想着将于公司业务无关的代码抽离出来，放到Maven中央仓库中，以供别人学习借鉴，跟着各路大神的帖子折腾了不少时间，一路曲折最终发布到仓库中，地址在此&amp;nbsp;&lt;a title="Flowable-lang" href="https://mvnrepository.com/artifact/com.github.songyz0310/flowable-lang" target="_blank" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline;"&gt;https://mvnrepository.com/artifact/com.github.songyz0310/flowable-lang&lt;/a&gt;&amp;nbsp;需要的可以使用，我会不定期更新。回到本帖主题，本篇不涉及此工具包，主要说下关于Maven发布的步骤和心得。最近心血来潮，希望把这几年的java相关的东西整理下，暂定项目集&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;java-toolkits 。&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h1 style="padding: 0px; font-size: 28px; font-weight: bold; line-height: 1.5;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;第一步，注册GitHub的账户&lt;/strong&gt;&lt;/h1&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;地址：&lt;a title="https://github.com/" href="https://github.com/" target="_blank" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline;"&gt;https://github.com&lt;/a&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;关于GitHub，无需我多说，Java语言本身就是开源的，作为Javaer又怎么离得开GitHub，注册没什么需要提的，这是我个人的&lt;a href="https://github.com/songyz0310" target="_blank" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline;"&gt;GitHub&lt;/a&gt;地址，欢迎评价点星！&lt;/p&gt;&lt;h1 style="padding: 0px; font-size: 28px; font-weight: bold; line-height: 1.5;"&gt;第二步，注册Sonatype的账户&lt;/h1&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;地址：https://issues.sonatype.org/secure/Signup!default.jspa&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;【友情提示】这里的密码校验真的是很太苛刻了，基本上是我见过的最严格的的。注册过后一定要记在小本本上，否则，我敢说大部分人一小时之后就记不得了，&lt;/strong&gt;&lt;/p&gt;&lt;h1 style="padding: 0px; font-size: 28px; font-weight: bold; line-height: 1.5;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;第三步，在&lt;/strong&gt;Sonatype上&lt;strong style="margin: 0px; padding: 0px;"&gt;提交关于本项目的发布申请&lt;/strong&gt;&lt;/h1&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;点击页面上方&lt;strong style="margin: 0px; padding: 0px;"&gt;&amp;nbsp;&lt;span style="margin: 0px; padding: 0px; font-size: 14pt;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Create&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;按钮即可创建此项目的&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0); font-size: 16px;"&gt;Issue&lt;/span&gt;。&lt;/strong&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;1&lt;/span&gt; Project: Community Support -&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt; Open Source Project Repository Hosting (OSSRH) &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;2&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;Issue TypeRequired: New Project &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;3&lt;/span&gt;  &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;4&lt;/span&gt; Summary: java-&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;toolkits （自己项目名称） &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;5&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;Group Id：com.github.songyz0310 （maven项目坐标 Group Id） &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;6&lt;/span&gt; Project URL：https:&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;//&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;github.com/songyz0310/java-toolkits (项目地址)&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;7&lt;/span&gt; SCM url：https:&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;//&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;github.com/songyz0310/java-toolkits.git （源代码地址）&lt;br style="margin: 0px; padding: 0px;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&amp;nbsp;其他内容可以按照自己实际情况填写，可以用默认值的地方，可以不用填写。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;当你提交后状态为等待工作人员审核，审核通过后状态会修改为&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; background-color: rgb(51, 153, 102); color: rgb(255, 255, 255);"&gt;RESOLVED&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;关于此步骤审核我有个小疑问，我2018年发布flowable-lang项目时，跟2019年发布java-toolkits项目要求有些稍微的不同，后边这一次多了对于权限的校验，不过在工作人员的详细回复下，问题不大。毫无疑问，这次比上次校验的更严格了。当你看到最后这一条评论时，就证明你可以开始下一步了。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&lt;img src="https://img2018.cnblogs.com/blog/898741/201908/898741-20190821115006150-1646592379.png" alt="" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;h1 style="padding: 0px; font-size: 28px; font-weight: bold; line-height: 1.5;"&gt;第四步，配置Maven&lt;/h1&gt;&lt;h2 style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5;"&gt;4.1，配置 settings.xml 文件&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;在servers节点内部添加如下server配置，这里就会用到第二步的注册信息（~偷笑~）&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 1&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;server&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 2&lt;/span&gt;   &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;sonatype-nexus-snapshots&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 3&lt;/span&gt;   &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;username&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;Sonatype账号&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;username&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 4&lt;/span&gt;   &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;password&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;Sonatype密码&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;password&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 5&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;server&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 6&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;server&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 7&lt;/span&gt;   &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;sonatype-nexus-staging&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 8&lt;/span&gt;   &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;username&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;Sonatype账号&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;username&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 9&lt;/span&gt;   &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;password&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;Sonatype密码&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;password&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;10&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;server&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5;"&gt;4.2，配置项目 pom.xml 文件&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;增加开源许可协议，SCM信息，开发者信息等待根据自己信息填写即可&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 1&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;licenses&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 2&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;license&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 3&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;name&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;The Apache Software License, Version 2.0&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;name&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 4&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;url&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;http://www.apache.org/licenses/LICENSE-2.0.txt&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;url&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 5&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;license&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 6&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;licenses&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 7&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;scm&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 8&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;connection&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;scm:git:https://github.com/songyz0310/java-toolkits.git&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;connection&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 9&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;developerConnection&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;scm:git:https://github.com/songyz0310/java-toolkits.git&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;developerConnection&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;10&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;url&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;git:https://github.com/songyz0310/java-toolkits.git&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;url&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;11&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;scm&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;12&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;developers&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;13&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;developer&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;14&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;name&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;songyz&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;name&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;15&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;email&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;songyinzeng@gmail.com&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;email&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;16&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;organization&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;i1stcs&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;organization&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;17&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;developer&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;18&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;developers&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;如果发布Release版本，需要添加Release的相关profile配置，distributionManagement节和maven-compiler-plugin节的配置信息根据自己的实际情况做修改。&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; color: rgb(0, 0, 0); font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 1&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;profile&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 2&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;release&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 3&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;build&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 4&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;resources&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 5&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;resource&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 6&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;directory&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;src/main/java&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;directory&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 7&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;includes&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 8&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;include&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;**/*.properties&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;include&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt; 9&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;includes&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;10&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;resource&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;11&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;resources&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;12&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugins&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;13&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt; Source &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;--&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;14&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;15&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;16&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;maven-source-plugin&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;17&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;2.2.1&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;18&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;executions&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;19&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;execution&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;20&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;phase&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;package&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;phase&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;21&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goals&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;22&lt;/span&gt;                             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goal&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;jar-no-fork&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goal&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;23&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goals&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;24&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;execution&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;25&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;executions&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;26&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;27&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt; Javadoc &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;--&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;28&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;29&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;30&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;maven-javadoc-plugin&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;31&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;2.9.1&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;32&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;configuration&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;33&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;show&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;private&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;show&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;34&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;nohelp&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;nohelp&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;35&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;charset&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;UTF-8&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;charset&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;36&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;encoding&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;UTF-8&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;encoding&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;37&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;docencoding&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;UTF-8&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;docencoding&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;38&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;additionalparam&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;-Xdoclint:none&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;additionalparam&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;39&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt; TODO 临时解决不规范的javadoc生成报错,后面要规范化后把这行去掉 &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;--&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;40&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;configuration&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;41&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;executions&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;42&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;execution&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;43&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;phase&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;package&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;phase&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;44&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goals&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;45&lt;/span&gt;                             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goal&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;jar&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goal&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;46&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goals&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;47&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;execution&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;48&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;executions&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;49&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;50&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt; GPG &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;--&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;51&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;52&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;53&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;maven-gpg-plugin&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;54&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;1.5&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;55&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;executions&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;56&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;execution&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;57&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;phase&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;verify&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;phase&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;58&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goals&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;59&lt;/span&gt;                             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goal&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;sign&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goal&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;60&lt;/span&gt;                         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;goals&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;61&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;execution&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;62&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;executions&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;63&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;64&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;Compiler &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;--&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;65&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;66&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;67&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;maven-compiler-plugin&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;68&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;3.0&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;69&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;configuration&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;70&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;source&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;1.8&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;source&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;71&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;target&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;1.8&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;target&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;72&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;fork&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;fork&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;73&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;verbose&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;verbose&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;74&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;encoding&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;UTF-8&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;encoding&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;75&lt;/span&gt;                     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;showWarnings&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;showWarnings&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;76&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;configuration&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;77&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;78&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;Release &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;--&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;79&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;80&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;groupId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;81&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;maven-release-plugin&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;artifactId&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;82&lt;/span&gt;                 &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;2.5.1&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;version&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;83&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugin&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;84&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;plugins&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;85&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;build&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;86&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;distributionManagement&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;87&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;snapshotRepository&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;88&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;sonatype-nexus-snapshots&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;89&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;name&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;Sonatype Nexus Snapshots&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;name&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;90&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;url&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;https://oss.sonatype.org/content/repositories/snapshots/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;url&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;91&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;snapshotRepository&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;92&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;repository&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;93&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;sonatype-nexus-staging&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;id&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;94&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;name&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;Nexus Release Repository&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;name&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;95&lt;/span&gt;             &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;url&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;https://oss.sonatype.org/service/local/staging/deploy/maven2/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;url&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;96&lt;/span&gt;         &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;repository&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;97&lt;/span&gt;     &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;distributionManagement&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 128); line-height: 1.5 !important;"&gt;98&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;profile&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;h1 style="padding: 0px; font-size: 28px; font-weight: bold; line-height: 1.5;"&gt;第五步，配置PGP的公钥信息&lt;/h1&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;由于我使用的是Windows，Mac和Linux用户请自行查找本步骤解决方案&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;Windows下使用gpg4win来进行配置。下载地址&amp;nbsp;&lt;a target="_blank" style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;https://www.gpg4win.org/get-gpg4win.html&lt;/span&gt;&lt;/a&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;安装好之后，打开cmd控制台，使用&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;gpg --list-keys&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;命令来查询自己配置的key&lt;br style="margin: 0px; padding: 0px;"&gt;如果提示gpg不是可执行程序或命令，请配置Path路径到&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;GnuPG&lt;/span&gt;&amp;nbsp;&lt;/strong&gt;的bin目录&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;生成密钥的命令&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;gpg --gen-key&lt;/span&gt;&lt;/strong&gt;，过程中需要使用到姓名、邮箱等信息，这里的配置最好和&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Sonatype&lt;/span&gt;&lt;/strong&gt;注册信息、pom文件配置信息保持一致，以免不必要的麻烦。&lt;br style="margin: 0px; padding: 0px;"&gt;生成的过程中，会有个弹框要求输入&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Passphase&lt;/span&gt;&lt;/strong&gt;信息，这个是密钥的密码，同样需要记牢。发布签名的过程中会用得到。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;使用&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;gpg --list-keys&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;命令查询配置好的公私钥信息，使用&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys &amp;lt;公钥key&amp;gt;&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;将公钥信息发送到ubuntu.com服务器，后续推送maven仓库会做校验。&lt;/p&gt;&lt;h1 style="padding: 0px; font-size: 28px; font-weight: bold; line-height: 1.5;"&gt;第六步，打包Deploy&lt;/h1&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;使用&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;&amp;nbsp;&lt;code style="margin: 0px; padding: 0px;"&gt;mvn clean deploy -P &amp;lt;profile-id&amp;gt;&lt;/code&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;命令，一键打包。&lt;br style="margin: 0px; padding: 0px;"&gt;打包过程中会要求输入gpg密钥的&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;&lt;code style="margin: 0px; padding: 0px;"&gt;Passphase&lt;/code&gt;&lt;/span&gt;&lt;/strong&gt;信息，输入即可。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;【友情提示】如果打包过程中出现了&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;401&lt;/span&gt;类的错误，可能是因为&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Maven&lt;/span&gt;的配置文件中&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Server&lt;/span&gt;节点配置的用户名和密码不正确，或者&amp;nbsp;&lt;span style="margin: 0px; padding: 0px; font-size: 16px; color: rgb(255, 0, 0);"&gt;Issue&amp;nbsp;&lt;/span&gt;还未审核通过。&lt;/strong&gt;&lt;/p&gt;&lt;h1 style="padding: 0px; font-size: 28px; font-weight: bold; line-height: 1.5;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;第七步，发布Release&lt;/strong&gt;&lt;/h1&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;进入&amp;nbsp;&lt;a href="https://oss.sonatype.org/#stagingRepositories" target="_blank" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline;"&gt;https://oss.sonatype.org/#stagingRepositories&lt;/a&gt;&amp;nbsp;查看发布好的构件，点击左侧的Staging Repositories，可以使用Group Id或其他信息搜索自己的项目，&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;此时的构件状态为&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Open&lt;/span&gt;&lt;/strong&gt;，选中构件，并点击上方的&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Close–&amp;gt;Confirm&lt;/span&gt;&amp;nbsp;&lt;/strong&gt;在下边的Activity选项卡中查看状态。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;当状态变成&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;closed&lt;/span&gt;&lt;/strong&gt;后，执行&amp;nbsp;&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Release–&amp;gt;Confirm&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;并在下边的Activity选项卡中查看状态。&lt;br style="margin: 0px; padding: 0px;"&gt;成功后构件自动删除，一小段时间（约1-2个小时）后即可同步到maven的中央仓库。届时会有邮件通知。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&lt;em id="__mceDel" style="margin: 0px; padding: 0px;"&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;&lt;/em&gt;至此，发布到Maven中央仓库完成。&lt;em id="__mceDel" style="margin: 0px; padding: 0px;"&gt;&lt;em id="__mceDel" style="margin: 0px; padding: 0px;"&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;&lt;h1 style="padding: 0px; font-size: 28px; font-weight: bold; line-height: 1.5;"&gt;第八步，收尾工作&lt;/h1&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;对自己提交的&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Issue&lt;/span&gt;&lt;/strong&gt;增加&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Comment&lt;/span&gt;&lt;/strong&gt;，留言致谢并表示发布已经完成，请工作人员关闭&lt;strong style="margin: 0px; padding: 0px;"&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Issue&lt;/span&gt;&lt;/strong&gt;。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;有始有终吧。☺☺☺收工~~~&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded>
      <pubDate>Wed, 23 Dec 2020 08:24:00 GMT</pubDate>
    </item>
    <item>
      <title>java8函数式编程</title>
      <link>https://cliveyuan.cn/article/51</link>
      <content:encoded>&lt;p&gt;转自&lt;a href="https://zhuanlan.zhihu.com/p/63107670"&gt;https://zhuanlan.zhihu.com/p/63107670&lt;/a&gt;&lt;/p&gt; &lt;header class="Post-Header" style="overflow: hidden; width: 690px; margin: 0px auto; color: rgb(18, 18, 18); font-family: -apple-system, system-ui, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans SC&amp;quot;, &amp;quot;Noto Sans CJK SC&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; font-size: medium;"&gt;&lt;h1 class="Post-Title" style="margin-top: 24px; margin-bottom: 24px; font-style: inherit; font-variant: inherit; font-weight: 600; font-stretch: inherit; font-size: 24px; line-height: 1.22; font-family: inherit; overflow-wrap: break-word;"&gt;Java8里面函数式编程&lt;/h1&gt;&lt;div class="Post-Author" style="display: flex; -webkit-box-align: center; align-items: center;"&gt;&lt;div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person" style="display: flex; -webkit-box-align: center; align-items: center; -webkit-box-flex: 1; flex: 1 1 0%; white-space: nowrap; overflow: hidden;"&gt;&lt;span class="UserLink AuthorInfo-avatarWrapper"&gt;&lt;div class="Popover" style="position: relative; display: inline-block;"&gt;&lt;div id="Popover5-toggle" aria-haspopup="true" aria-expanded="false" aria-owns="Popover5-content"&gt;&lt;a class="UserLink-link" data-za-detail-view-element_name="User" target="_blank" href="https://www.zhihu.com/people/di-jing-ping-fang" style="color: inherit;"&gt;&lt;img class="Avatar Avatar--round AuthorInfo-avatar" width="38" height="38" src="https://pic4.zhimg.com/70d8d6ca151553c96d4c20ae7b3fae09_xs.jpg" srcset="https://pic4.zhimg.com/70d8d6ca151553c96d4c20ae7b3fae09_l.jpg 2x" alt="地精平方" style="background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-radius: 50%; vertical-align: top;"&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="AuthorInfo-content" style="-webkit-box-flex: 1; flex: 1 1 0%; margin-left: 14px; overflow: hidden;"&gt;&lt;div class="AuthorInfo-head" style="display: flex; -webkit-box-align: center; align-items: center; font-size: 15px; line-height: 1.1; flex-shrink: 0;"&gt;&lt;span class="UserLink AuthorInfo-name" style="font-weight: 600; color: rgb(68, 68, 68);"&gt;&lt;div class="Popover" style="position: relative; display: inline-block;"&gt;&lt;div id="Popover6-toggle" aria-haspopup="true" aria-expanded="false" aria-owns="Popover6-content"&gt;&lt;a class="UserLink-link" data-za-detail-view-element_name="User" target="_blank" href="https://www.zhihu.com/people/di-jing-ping-fang" style="color: inherit;"&gt;地精平方&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="AuthorInfo-detail" style="overflow: hidden; color: rgb(100, 100, 100);"&gt;&lt;div class="AuthorInfo-badge" style="display: flex; -webkit-box-align: center; align-items: center; margin-top: 2px; font-size: 14px;"&gt;&lt;div class="ztext AuthorInfo-badgeText" style="word-break: break-word; line-height: 1.6; overflow: hidden; text-overflow: ellipsis;"&gt;程序员&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Voters" style="color: rgb(133, 144, 166); display: block; margin-top: 14px; font-size: 14px;"&gt;&lt;button type="button" class="Button Button--plain" style="padding: 0px; font-size: 14px; color: rgb(133, 144, 166); background-image: none; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-width: initial; border-style: none; border-color: initial; appearance: none; border-radius: 0px; height: auto;"&gt;1 人赞同了该文章&lt;/button&gt;&lt;/span&gt;&lt;/div&gt;&lt;/header&gt;&lt;div class="Post-RichTextContainer" style="position: relative; overflow: visible; width: 690px; margin: 0px auto; color: rgb(18, 18, 18); font-family: -apple-system, system-ui, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans SC&amp;quot;, &amp;quot;Noto Sans CJK SC&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; font-size: medium;"&gt;&lt;div class="RichText ztext Post-RichText" style="word-break: break-word; line-height: 1.6; margin-top: 20px;"&gt;&lt;p style="margin-bottom: 1.4em;"&gt;Java8里面引入了新的一个包java.util.function。里面定义了下面几个核心接口：&lt;/p&gt;&lt;ul style="padding: 0px; margin: 1.4em 0px; display: table;"&gt;&lt;li style="list-style: none; display: table-row;"&gt;Function&amp;lt;T,R&amp;gt;：接收一个参数，返回一个结果。&lt;/li&gt;&lt;li style="list-style: none; display: table-row;"&gt;Consumer&amp;lt;T&amp;gt;：接收一个参数，无返回。&lt;/li&gt;&lt;li style="list-style: none; display: table-row;"&gt;Predicate&amp;lt;T&amp;gt;：接收一个参数，返回一个boolean的结果。&lt;/li&gt;&lt;li style="list-style: none; display: table-row;"&gt;Supplier&amp;lt;R&amp;gt;：无参数，返回一个结果。&lt;/li&gt;&lt;li style="list-style: none; display: table-row;"&gt;BiFunction&amp;lt;T,V,R&amp;gt;：接收两个参数，返回一个结果。&lt;/li&gt;&lt;li style="list-style: none; display: table-row;"&gt;BiConsumer&amp;lt;T,V&amp;gt;：接收两个参数，无返回值。&lt;/li&gt;&lt;li style="list-style: none; display: table-row;"&gt;BiPredicate&amp;lt;T,V&amp;gt;：接收两个参数，返回boolean值。&lt;/li&gt;&lt;/ul&gt;&lt;p style="margin-top: 1.4em; margin-bottom: 1.4em;"&gt;&lt;span style="font-weight: 600;"&gt;Function接口&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;div class="highlight" style="margin: 1em 0px;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0.88889em; font-size: 0.9em; word-break: normal; overflow-wrap: normal; background: rgb(246, 246, 246);"&gt;&lt;code class="language-java" style="margin: 0px; font-family: Menlo, Monaco, Consolas, &amp;quot;Andale Mono&amp;quot;, &amp;quot;lucida console&amp;quot;, &amp;quot;Courier New&amp;quot;, monospace;"&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//function表示具有返回值的，具有一个参数的方法 &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;function1&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;::&lt;/span&gt;&lt;span class="n"&gt;valueOf&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt; &lt;span class="n"&gt;function2&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;::&lt;/span&gt;&lt;span class="n"&gt;valueOf&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt; &lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//可以用lambda表达式 &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;function3&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;)-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;.&lt;/span&gt;&lt;span class="na" style="color: rgb(0, 132, 255);"&gt;toString&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;();&lt;/span&gt; &lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//报错，因为无返回值 &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//Function out=System.out::println; &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//返回值是Boolean的function &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="s" style="color: rgb(241, 64, 60);"&gt;"123"&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;function4&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;::&lt;/span&gt;&lt;span class="n"&gt;equals&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt; &lt;span class="kt" style="font-weight: 600; color: rgb(23, 81, 153);"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;equals&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="n"&gt;function4&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;.&lt;/span&gt;&lt;span class="na" style="color: rgb(0, 132, 255);"&gt;apply&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;(&lt;/span&gt;&lt;span class="s" style="color: rgb(241, 64, 60);"&gt;"123"&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin-top: 1.4em; margin-bottom: 1.4em;"&gt;&lt;span style="font-weight: 600;"&gt;Consumer接口&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;div class="highlight" style="margin: 1em 0px;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0.88889em; font-size: 0.9em; word-break: normal; overflow-wrap: normal; background: rgb(246, 246, 246);"&gt;&lt;code class="language-java" style="margin: 0px; font-family: Menlo, Monaco, Consolas, &amp;quot;Andale Mono&amp;quot;, &amp;quot;lucida console&amp;quot;, &amp;quot;Courier New&amp;quot;, monospace;"&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//Consumer可以用来表示只有一个参数，无返回值的方法 &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;&lt;/span&gt;&lt;span class="n"&gt;Consumer&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;.&lt;/span&gt;&lt;span class="na" style="color: rgb(0, 132, 255);"&gt;out&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;::&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;.&lt;/span&gt;&lt;span class="na" style="color: rgb(0, 132, 255);"&gt;accept&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;(&lt;/span&gt;&lt;span class="s" style="color: rgb(241, 64, 60);"&gt;"123"&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;);&lt;/span&gt; &lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//可以用lambda表达式 &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;&lt;/span&gt;&lt;span class="n"&gt;Consumer&lt;/span&gt; &lt;span class="n"&gt;consumer2&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;)-&amp;gt;{};&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin-top: 1.4em; margin-bottom: 1.4em;"&gt;&lt;span style="font-weight: 600;"&gt;Predicate接口&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;div class="highlight" style="margin: 1em 0px;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0.88889em; font-size: 0.9em; word-break: normal; overflow-wrap: normal; background: rgb(246, 246, 246);"&gt;&lt;code class="language-java" style="margin: 0px; font-family: Menlo, Monaco, Consolas, &amp;quot;Andale Mono&amp;quot;, &amp;quot;lucida console&amp;quot;, &amp;quot;Courier New&amp;quot;, monospace;"&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//用Predicate来表示 &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;&lt;/span&gt;&lt;span class="n"&gt;Predicate&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;predicate&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;::&lt;/span&gt;&lt;span class="n"&gt;equals&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin-top: 1.4em; margin-bottom: 1.4em;"&gt;&lt;span style="font-weight: 600;"&gt;Supplier接口&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;div class="highlight" style="margin: 1em 0px;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0.88889em; font-size: 0.9em; word-break: normal; overflow-wrap: normal; background: rgb(246, 246, 246);"&gt;&lt;code class="language-java" style="margin: 0px; font-family: Menlo, Monaco, Consolas, &amp;quot;Andale Mono&amp;quot;, &amp;quot;lucida console&amp;quot;, &amp;quot;Courier New&amp;quot;, monospace;"&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//无参数有返回 &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;&lt;/span&gt;&lt;span class="n"&gt;Supplier&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;supplier&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hashCode&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt; &lt;span class="n"&gt;IntSupplier&lt;/span&gt; &lt;span class="n"&gt;intSupplier&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hashCode&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt; &lt;span class="n"&gt;Supplier&lt;/span&gt; &lt;span class="n"&gt;supplier2&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=()-&amp;gt;&lt;/span&gt; &lt;span class="s" style="color: rgb(241, 64, 60);"&gt;"test"&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin-top: 1.4em; margin-bottom: 1.4em;"&gt;&lt;span style="font-weight: 600;"&gt;二元参数相关&lt;/span&gt;&lt;/p&gt;&lt;div class="highlight" style="margin: 1em 0px;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0.88889em; font-size: 0.9em; word-break: normal; overflow-wrap: normal; background: rgb(246, 246, 246);"&gt;&lt;code class="language-java" style="margin: 0px; font-family: Menlo, Monaco, Consolas, &amp;quot;Andale Mono&amp;quot;, &amp;quot;lucida console&amp;quot;, &amp;quot;Courier New&amp;quot;, monospace;"&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;//二个参数的函数 &lt;/span&gt;&lt;span class="c1" style="font-style: italic; color: rgb(153, 153, 153);"&gt;&lt;/span&gt;&lt;span class="n"&gt;BiFunction&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=&lt;/span&gt; &lt;span class="o" style="font-weight: 600;"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;str2&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;)-&amp;gt;&lt;/span&gt;&lt;span class="kc" style="font-weight: 600;"&gt;true&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt; &lt;span class="n"&gt;BiConsumer&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;test2&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;str2&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;)-&amp;gt;{};&lt;/span&gt; &lt;span class="n"&gt;BiPredicate&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;test3&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;=(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;,&lt;/span&gt;&lt;span class="n"&gt;str2&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;)-&amp;gt;&lt;/span&gt;&lt;span class="kc" style="font-weight: 600;"&gt;true&lt;/span&gt;&lt;span class="o" style="font-weight: 600;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin-top: 1.4em;"&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="ContentItem-time" style="margin: 0px auto; color: rgb(133, 144, 166); padding: 16px 0px; overflow: hidden; width: 690px; font-family: -apple-system, system-ui, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans SC&amp;quot;, &amp;quot;Noto Sans CJK SC&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif;"&gt;发布于 2019-04-20&lt;/div&gt;</content:encoded>
      <pubDate>Fri, 27 Nov 2020 07:32:00 GMT</pubDate>
    </item>
    <item>
      <title>IOS抓包软件 Thor</title>
      <link>https://cliveyuan.cn/article/50</link>
      <content:encoded>&lt;p&gt;&lt;a href="https://www.jianshu.com/p/bb8231f48a07" target="_blank"&gt;https://www.jianshu.com/p/bb8231f48a07&lt;/a&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Mon, 16 Nov 2020 02:55:00 GMT</pubDate>
    </item>
    <item>
      <title>git 常用脚本</title>
      <link>https://cliveyuan.cn/article/49</link>
      <content:encoded>&lt;h2&gt;一键清理本地分支：删除除master之外的本地分支，同步远程分支&lt;/h2&gt; &lt;blockquote&gt; &lt;p&gt;执行前一定要提交当前分支的更改哦&lt;/p&gt; &lt;/blockquote&gt; &lt;pre&gt;&lt;code class="language-shell"&gt;git checkout master;git branch | xargs git branch \-d;git remote prune origin; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;合并Commits&lt;/h2&gt; &lt;blockquote&gt; &lt;p&gt;将多个提交记录进行合并&lt;/p&gt; &lt;/blockquote&gt; &lt;pre&gt;&lt;code&gt;git rebase -i ${commitId} &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;commitId是最近一条不需要合并的commit的id&lt;/p&gt; &lt;pre&gt;&lt;code&gt;pick 2dfbc7e1 commit1 pick 2dfbc7e2 commit2 pick 2dfbc7e3 commit3 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;修改为&lt;/p&gt; &lt;pre&gt;&lt;code&gt;pick 2dfbc7e1 commit1 s 2dfbc7e2 commit2 s 2dfbc7e3 commit3 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;s 表示要合并的commit&lt;/p&gt; &lt;pre&gt;&lt;code&gt;#the first commit commit1 #the second commit commit2 #the third commit commit3 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;改为&lt;/p&gt; &lt;pre&gt;&lt;code&gt;#the first commit merge commits - commit1 - commit2 - commit3 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;最重要的一步：&lt;strong&gt;强制提交&lt;/strong&gt;&lt;/p&gt; &lt;pre&gt;&lt;code&gt;git push --force &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;完成&lt;/p&gt; &lt;h1&gt;生成&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;#全局配置 git config --global user.name &amp;quot;Clive Yuan&amp;quot; git config --global user.email &amp;quot;xxxx@foxmail.com&amp;quot; cd ~/.ssh     mkdir ~/.ssh ssh-keygen -t rsa -C &amp;quot;clive@xxx.com&amp;quot; cat ~/.ssh/id_rsa.pub ssh -T git@gitee.com &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;别名&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;up = pull --rebase --autostash acp = &amp;quot;!f() { git add -A &amp;amp;&amp;amp; git commit -m \&amp;quot;$@\&amp;quot; &amp;amp;&amp;amp; git push; }; f&amp;quot; ac = &amp;quot;!f() { git add -A &amp;amp;&amp;amp; git commit -m \&amp;quot;$@\&amp;quot;; }; f&amp;quot; cleanbranch = &amp;quot;checkout master;branch | xargs branch \\-d;remote prune origin;&amp;quot;  # 忽略换行符  git config core.autocrlf false &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Fri, 06 Nov 2020 02:15:00 GMT</pubDate>
    </item>
    <item>
      <title>Spring学习笔记</title>
      <link>https://cliveyuan.cn/article/spring-learn</link>
      <content:encoded>&lt;h1&gt;Spring&lt;/h1&gt; &lt;h2&gt;特点&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;轻量级&lt;/li&gt; &lt;li&gt;松耦合&lt;/li&gt; &lt;li&gt;万能胶&lt;/li&gt; &lt;li&gt;设计模式&lt;/li&gt; &lt;li&gt;面向Bean&lt;/li&gt; &lt;/ul&gt; &lt;h2&gt;关键策略&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;基于POJO的轻量级和最小侵入性编程&lt;/li&gt; &lt;li&gt;通过依赖注入和面向接口松耦合&lt;/li&gt; &lt;li&gt;基于切面和惯性进行声明式编程&lt;/li&gt; &lt;li&gt;通过切面和模板减少样板式代码&lt;/li&gt; &lt;/ul&gt; &lt;h2&gt;IoC 控制反转&lt;/h2&gt; &lt;p&gt;将实例化bean的控制权交给spring框架&lt;/p&gt; &lt;h2&gt;AOP 面向切面编程&lt;/h2&gt; &lt;p&gt;将那些影响多个类的行为通过切面方式封装到一个可重用的模块中&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 03 Jun 2020 14:20:00 GMT</pubDate>
    </item>
    <item>
      <title>idea license</title>
      <link>https://cliveyuan.cn/article/46</link>
      <content:encoded>&lt;p&gt;https://zhile.io/custom/license&lt;/p&gt; &lt;p&gt;code: https://gitee.com/clive_private/codes/bwsak1ljteufpdrxgn9v356&lt;/p&gt;</content:encoded>
      <pubDate>Mon, 01 Jun 2020 03:33:00 GMT</pubDate>
    </item>
    <item>
      <title>crontab 启动springboot项目失败</title>
      <link>https://cliveyuan.cn/article/45</link>
      <content:encoded>&lt;blockquote&gt; &lt;p&gt;记一次踩坑经历&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;起因&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在Linux中使用用全路径shell启动springBoot项目&lt;/p&gt; &lt;pre&gt;&lt;code&gt;sh /home/code/app.sh &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;code&gt;app.sh&lt;/code&gt;脚本中启动springBoot的命令是&lt;code&gt;java -jar app.jar&lt;/code&gt;&lt;/p&gt; &lt;p&gt;问题就在这里，如果进入到命令的当前目录即&lt;code&gt;/home/code/&lt;/code&gt;去执行&lt;code&gt;app.sh&lt;/code&gt;是没问题的，全路径执行就不行&lt;/p&gt; &lt;p&gt;在使用&lt;code&gt;crontab&lt;/code&gt;时，就算脚本是进入到对应目录去执行&lt;code&gt;app.sh&lt;/code&gt;也是不行的&lt;/p&gt; &lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;启动springBoot命令这里使用&lt;code&gt;java&lt;/code&gt;的全路径&lt;code&gt;/usr/java/jdk1.8.xxx/java -jar app.jar&lt;/code&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Mon, 11 May 2020 09:34:00 GMT</pubDate>
    </item>
    <item>
      <title>使用acme.sh免费申请Let's Encrypt泛域名证书SSL</title>
      <link>https://cliveyuan.cn/article/44</link>
      <content:encoded>&lt;p&gt;&lt;a href="https://zhuanlan.zhihu.com/p/112300451" target="_blank"&gt;https://zhuanlan.zhihu.com/p/112300451&lt;/a&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 29 Apr 2020 04:01:00 GMT</pubDate>
    </item>
    <item>
      <title>CentOS8下安装mysql5.7</title>
      <link>https://cliveyuan.cn/article/43</link>
      <content:encoded>&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-weight: 700; margin: 0px; padding: 0px;"&gt;1、安装YUM Repo&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;由于CentOS 的yum源中没有mysql，需要到mysql的官网下载yum repo配置文件。&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;wget https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;然后进行repo的安装：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;rpm -ivh mysql57-community-release-el7-9.noarch.rpm&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;执行完成后会在&lt;code style="font-size: 12.6px; padding: 0px; margin: 0px;"&gt;/etc/yum.repos.d/&lt;/code&gt;目录下生成两个repo文件&lt;code style="font-size: 12.6px; padding: 0px; margin: 0px;"&gt;mysql-community.repo&lt;/code&gt;&amp;nbsp;&lt;code style="font-size: 12.6px; padding: 0px; margin: 0px;"&gt;mysql-community-source.repo&lt;/code&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-weight: 700; margin: 0px; padding: 0px;"&gt;2、安装MySQL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;使用yum命令即可完成安装&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857;"&gt;&lt;font face="Courier New"&gt;&lt;span style="font-size: 12px; white-space: pre-wrap;"&gt;yum install mysql-community-server&lt;/span&gt;&lt;span style="font-size: 12px !important; white-space: pre-wrap;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important; padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap;"&gt;&lt;span style="color: rgb(204, 204, 204); font-family: &amp;quot;Source Code Pro&amp;quot;, &amp;quot;DejaVu Sans Mono&amp;quot;, &amp;quot;Ubuntu Mono&amp;quot;, &amp;quot;Anonymous Pro&amp;quot;, &amp;quot;Droid Sans Mono&amp;quot;, Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, sans-serif; font-size: 14px; font-variant-ligatures: common-ligatures; white-space: pre; background-color: rgb(45, 45, 45);"&gt; &lt;/span&gt;&lt;span class="token comment" style="outline-style: initial; outline-width: 0px; margin: 0px; padding: 0px; font-size: 14px; overflow-wrap: break-word; color: rgb(153, 153, 153); white-space: pre; font-family: &amp;quot;Source Code Pro&amp;quot;, &amp;quot;DejaVu Sans Mono&amp;quot;, &amp;quot;Ubuntu Mono&amp;quot;, &amp;quot;Anonymous Pro&amp;quot;, &amp;quot;Droid Sans Mono&amp;quot;, Menlo, Monaco, Consolas, Inconsolata, Courier, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, sans-serif !important; font-style: italic !important; font-variant-numeric: normal !important; font-variant-east-asian: normal !important; font-stretch: normal !important; line-height: normal !important;"&gt;# 如果报错： No match for argument: mysql-community-server ，执行如下命令 之后再执行上述命令&lt;/span&gt;&lt;/pre&gt;&lt;pre style="font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important; padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap;"&gt;&lt;span class="token comment" style="outline-style: initial; outline-width: 0px; margin: 0px; padding: 0px; font-size: 14px; overflow-wrap: break-word; color: rgb(153, 153, 153); white-space: pre; font-family: &amp;quot;Source Code Pro&amp;quot;, &amp;quot;DejaVu Sans Mono&amp;quot;, &amp;quot;Ubuntu Mono&amp;quot;, &amp;quot;Anonymous Pro&amp;quot;, &amp;quot;Droid Sans Mono&amp;quot;, Menlo, Monaco, Consolas, Inconsolata, Courier, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, sans-serif !important; font-style: italic !important; font-variant-numeric: normal !important; font-variant-east-asian: normal !important; font-stretch: normal !important; line-height: normal !important;"&gt;yum module disable mysql&lt;br&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-weight: 700; margin: 0px; padding: 0px;"&gt;启动msyql：&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;systemctl start mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;启动MySQL&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-weight: 700; margin: 0px; padding: 0px;"&gt;配置MySQL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;获取安装时的临时密码：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;grep &lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;'&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;temporary password&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;'&lt;/span&gt; /var/log/mysqld.log&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;倘若没有：&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;1.删除原来安装过的mysql残留的数据&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;rm -rf /var/lib/mysql&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;2.再启动mysql&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;systemctl start mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;启动MySQL&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-weight: 700; margin: 0px; padding: 0px;"&gt;登录：&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;mysql -u root -p&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;登录成功后修改密码：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;set password=password(&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;yourpassword&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&amp;nbsp;设置安全选项：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;mysql_secure_installation&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;其他设置：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;systemctl stop mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;关闭MySQL&lt;/span&gt; systemctl restart mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;重启MySQL&lt;/span&gt; systemctl status mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;查看MySQL运行状态&lt;/span&gt; systemctl enable mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;设置开机启动&lt;/span&gt; systemctl disable mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;关闭开机启动&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 style="font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-size: 16px; padding: 0px;"&gt;&amp;nbsp;3、其他配置&lt;/h3&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-weight: 700; margin: 0px; padding: 0px;"&gt;开启远程控制&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;MySQL默认是没有开启远程控制的，必须添加远程访问的用户&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="color: rgb(0, 0, 0); text-decoration-line: underline; margin: 0px; padding: 0px; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;grant all privileges on 数据库名.表名 to 创建的用户名(root)@&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;%&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt; identified by &lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;密码&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt; 数据库名.表名 如果写成*.*代表授权所有的数据库 &lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt; flush privileges; &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;刷新刚才的内容&lt;br style="margin: 0px; padding: 0px;"&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;#如：&lt;br style="margin: 0px; padding: 0px;"&gt;grant all privileges on *.* to root@"113.64.243.1" identified by "123456789";&lt;br style="margin: 0px; padding: 0px;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="color: rgb(0, 0, 0); text-decoration-line: underline; margin: 0px; padding: 0px; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;@ 后面是访问mysql的客户端IP地址（或是 主机名） % 代表任意的客户端，如果填写 localhost 为本地访问（那此用户就不能远程访问该mysql数据库了）。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;同时也可以为现有的用户设置是否具有远程访问权限。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-weight: 700; margin: 0px; padding: 0px;"&gt;配置默认编码为utf8：&lt;/span&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;vi /etc/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;my.cnf &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;添加&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;[mysqld] character_set_server&lt;/span&gt;=&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;utf8 init_connect&lt;/span&gt;=&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;'&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;SET NAMES utf8&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;'&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-weight: 700; margin: 0px; padding: 0px;"&gt;其他默认配置文件路径：&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="padding: 0px; margin-bottom: 0px; line-height: 1.42857; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;配置文件：/etc/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;my.cnf  日志文件：&lt;/span&gt;/var/log//var/log/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;mysqld.log  服务启动脚本：&lt;/span&gt;/usr/lib/systemd/system/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;mysqld.service  socket文件：&lt;/span&gt;/var/run/mysqld/mysqld.pid&lt;/pre&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded>
      <pubDate>Tue, 28 Apr 2020 08:45:00 GMT</pubDate>
    </item>
    <item>
      <title>git init project</title>
      <link>https://cliveyuan.cn/article/42</link>
      <content:encoded>&lt;h1&gt;Command line instructions&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;Git global setup git config --global user.name &amp;quot;cliveyuan&amp;quot; git config --global user.email &amp;quot;clive@cliveyuan.com&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;Create a new repository&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;git clone git@gitee.com:opensource4clive/java-tools.git cd java-tools touch README.md git add README.md git commit -m &amp;quot;add README&amp;quot; git push -u origin master &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;Existing folder or Git repository&lt;/h1&gt; &lt;h1&gt;must create project in gitee before&lt;/h1&gt; &lt;pre&gt;&lt;code&gt;cd existing_folder git init git remote add origin git@gitee.com:opensource4clive/java-tools.git git add -A git commit -am 'init' git push -u origin master &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Thu, 09 Apr 2020 01:54:00 GMT</pubDate>
    </item>
    <item>
      <title>Git中撤销提交</title>
      <link>https://cliveyuan.cn/article/41</link>
      <content:encoded>&lt;h1&gt;Git中撤销提交&lt;/h1&gt; &lt;h2&gt;Git的几种状态&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;未修改             工作区 已修改    ↓             工作区 已暂存    ↓             暂存区 已提交    ↓             本地仓库 已推送    ↓             远程仓库 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;已修改 未暂存&lt;/h2&gt; &lt;p&gt;已经修改了文件，还未进行&lt;code&gt;git add&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;恢复方法&lt;/h3&gt; &lt;p&gt;使用一下任意命令&lt;/p&gt; &lt;pre&gt;&lt;code&gt;git checkout . git reset --hard &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;已暂存 未提交&lt;/h2&gt; &lt;p&gt;已经进行了&lt;code&gt;git add&lt;/code&gt;，还未进行&lt;code&gt;git commit&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;恢复方法&lt;/h3&gt; &lt;p&gt;使用一下任意命令&lt;/p&gt; &lt;pre&gt;&lt;code&gt;git reset git checkout . git reset --hard &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;已提交 未推送&lt;/h2&gt; &lt;p&gt;已经进行了&lt;code&gt;git ommit&lt;/code&gt;，还未进行&lt;code&gt;git push&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;恢复方法&lt;/h3&gt; &lt;p&gt;使用远程仓库覆盖本地仓库&lt;/p&gt; &lt;pre&gt;&lt;code&gt;git reset --hard origin/master &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;已推送&lt;/h2&gt; &lt;p&gt;已经进行了&lt;code&gt;git push&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;恢复方法&lt;/h3&gt; &lt;p&gt;回滚本地仓库，强制推送覆盖远程仓库&lt;/p&gt; &lt;pre&gt;&lt;code&gt;git reset --hard HEAD^ git push -f &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Mon, 30 Mar 2020 07:20:00 GMT</pubDate>
    </item>
    <item>
      <title>漫谈SQL优化</title>
      <link>https://cliveyuan.cn/article/40</link>
      <content:encoded>&lt;h2&gt;1. 前言&lt;/h2&gt; &lt;p&gt;随着业务量的增长，用户数越来越多，随之产生的数据也呈几何级增长，从而慢查询越来越多。SQL优化一方面是找出系统的瓶颈，提高数据库服务器的整体性能，而另一方面需要合理的结构设计和参数调整，以提数据访问的速度，同时还要尽可能的节约系统资源，以便让系统性能最大化。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;本文内容主要针对的是关系型数据库，以MySQL为例子&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;2. 需要准备的知识点&lt;/h2&gt; &lt;h3&gt;2.1 数据逻辑架构&lt;/h3&gt; &lt;p&gt;&lt;img src="https://cliveyuan.cn/upload/2020/03/se21nub40mih5qc2npp0080c4d.png" alt="架构图" title="架构图" /&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一层：客户端通过连接服务，将要执行的SQL指令传输过来&lt;/li&gt; &lt;li&gt;第二层：服务器解析并优化SQL，生成最终的执行计划并执行&lt;/li&gt; &lt;li&gt;第三层：存储引擎，负责数据的储存和提取&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;2.2 锁&lt;/h3&gt; &lt;p&gt;数据库通过锁机制来解决并发场景-共享锁（读锁）和排他锁（写锁）。读锁是不阻塞的，多个客户端可以在同一时刻读取同一个资源。写锁是排他的，并且会阻塞其他的读锁和写锁。简单提下乐观锁和悲观锁。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;乐观锁&lt;/strong&gt;：通常用于数据竞争不激烈的场景，多读少写，通过版本号和时间戳实现。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;悲观锁&lt;/strong&gt;：通常用于数据竞争激烈的场景，每次操作都会锁定数据，要锁定数据需要一定的锁策略来配合。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;表锁&lt;/strong&gt;：锁定整张表，开销最小，但是会加剧锁竞争。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;行锁&lt;/strong&gt;：锁定行级别，开销最大，但是可以最大程度的支持并发。&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;但是MySQL的存储引擎的真实实现不是简单的行级锁，一般都是实现了多版本并发控制（MVCC）。MVCC是行级锁的变种，多数情况下避免了加锁操作，开销更低。MVCC是通过保存数据的某个时间点快照实现的。&lt;/p&gt; &lt;h3&gt;2.3 事务&lt;/h3&gt; &lt;p&gt;事务保证一组原子性的操作，要么全部成功，要么全部失败。一旦失败，回滚之前的所有操作。&lt;/p&gt; &lt;p&gt;隔离级别控制了一个事务中的修改，哪些在事务内和事务间是可见的。四种常见的隔离级别：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;未提交读&lt;/strong&gt;（Read UnCommitted），事务中的修改，即使没提交对其他事务也是可见的。事务可能读取未提交的数据，造成脏读。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;提交读&lt;/strong&gt;（Read Committed），一个事务开始时，只能看见已提交的事务所做的修改。事务未提交之前，所做的修改对其他事务是不可见的。也叫不可重复读，同一个事务多次读取同样记录可能不同。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;可重复读&lt;/strong&gt;（RepeatTable Read），同一个事务中多次读取同样的记录结果时结果相同。&lt;/li&gt; &lt;li&gt;&lt;strong&gt;可串行化&lt;/strong&gt;（Serializable），最高隔离级别，强制事务串行执行。&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;2.4 常用存储引擎&lt;/h3&gt; &lt;ul&gt; &lt;li&gt; &lt;p&gt;&lt;strong&gt;InnoDB引擎：&lt;/strong&gt; 支持事务、行级锁，被用来设计处理大量短期事务，具有高性能和自动崩溃恢复的特性&lt;/p&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;**MyISAM引擎：**不支持事务和行级锁，查询性能强，崩溃后无法安全恢复&lt;/p&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h2&gt;3. 优化&lt;/h2&gt; &lt;h3&gt;3.1 优化方法&lt;/h3&gt; &lt;p&gt;&lt;img src="https://cliveyuan.cn/upload/2020/03/upmhafb32ahm4o5vv30upb0p47.png" alt="优化方法" title="优化方法" /&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;软优化：操作数据库&lt;/li&gt; &lt;li&gt;硬优化：是操作服务器硬件及参数设置&lt;/li&gt; &lt;/ul&gt; &lt;h3&gt;3.2 软优化&lt;/h3&gt; &lt;h4&gt;3.2.1 查询语句优化&lt;/h4&gt; &lt;p&gt;用&lt;code&gt;EXPLAIN&lt;/code&gt;命令分析一条查询语句的执行信息&lt;/p&gt; &lt;pre&gt;&lt;code class="language-sql"&gt;EXPLAIN SELECT * FROM `user` &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;img src="https://cliveyuan.cn/upload/2020/03/2r3begjti8jd7p6pn5k0cvnras.png" alt="" title="" /&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;select_type&lt;/strong&gt;，有几种值：simple（表示简单的select，没有union和子查询），primary（有子查询，最外面的select查询就是primary），union（union中的第二个或随后的select查询，不依赖外部查询结果），dependent union（union中的第二个或随后的select查询，依赖外部查询结果）&lt;/li&gt; &lt;li&gt;&lt;strong&gt;type&lt;/strong&gt;，有几种值：system（表仅有一行（=系统表），这是const连接类型的一个特例），const（常量查询）, ref(非唯一索引访问，只有普通索引)，eq_ref（使用唯一索引或组件查询），all（全表查询），index（根据索引查询全表），range（范围查询）&lt;/li&gt; &lt;li&gt;&lt;strong&gt;possible_keys&lt;/strong&gt;: 表中可能帮助查询的索引&lt;/li&gt; &lt;li&gt;&lt;strong&gt;key&lt;/strong&gt;，选择使用的索引&lt;/li&gt; &lt;li&gt;&lt;strong&gt;key_len&lt;/strong&gt;，使用的索引长度&lt;/li&gt; &lt;li&gt;&lt;strong&gt;rows&lt;/strong&gt;，扫描的行数，越大越不好&lt;/li&gt; &lt;li&gt;&lt;strong&gt;extra&lt;/strong&gt;，有几种值：Only index（信息从索引中检索出，比扫描表快），where used（使用where限制），Using filesort （可能在内存或磁盘排序），Using temporary（对查询结果排序时使用临时表）&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.2.2 优化子查询&lt;/h4&gt; &lt;p&gt;在MySQL中，尽量使用&lt;code&gt;JOIN&lt;/code&gt;来代替子查询。因为子查询需要嵌套查询，嵌套查询时会建立一张临时表，临时表的建立和删除都会有较大的系统开销，而连接查询不会创建临时表，因此效率比嵌套子查询高。&lt;/p&gt; &lt;h4&gt;3.2.3 使用索引&lt;/h4&gt; &lt;blockquote&gt; &lt;p&gt;使用索引可以显著地提高数据库查询速度，但是未恰当使用索引往往适得其反&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;如何创建索引:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;尽量选择区分度高的列创建索引&lt;/li&gt; &lt;li&gt;对于查询频率高的列创建索引&lt;/li&gt; &lt;li&gt;尽量使用长度短的列作为索引&lt;/li&gt; &lt;li&gt;对于长VARCHAR/TEXT/BLOB使用前缀索引&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;strong&gt;索引未命中:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;条件中包含&lt;code&gt;OR&lt;/code&gt; / &lt;code&gt;NOT IN&lt;/code&gt; / &lt;code&gt;NOT EXIST&lt;/code&gt; / &lt;code&gt;不等于&lt;/code&gt;&lt;/li&gt; &lt;li&gt;模糊匹配字段以&lt;code&gt;%&lt;/code&gt;开头&lt;/li&gt; &lt;li&gt;未使用联合索引中的第一个字段&lt;/li&gt; &lt;li&gt;数值的字符串列未使用单引号&lt;/li&gt; &lt;li&gt;在索引列上使用函数&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.2.4 分解表&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;对于字段较多的表，如果某些字段使用频率较低，此时应当，将其分离出来从而形成新的表&lt;/li&gt; &lt;li&gt;对应存储长文本如&lt;code&gt;LONGTEXT&lt;/code&gt;，应当放到单独的表中进行存储&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.2.5 中间表&lt;/h4&gt; &lt;blockquote&gt; &lt;p&gt;对于将大量连接查询的表可以创建中间表，从而减少在查询时造成的连接耗时&lt;/p&gt; &lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;中间表复制源表部分数据，并且与源表相“隔离”，在中间表上做统计查询不 会对在线应用产生负面影响&lt;/li&gt; &lt;li&gt;中间表上可以灵活的添加索引或增加临时用的新字段，从而达到提高统计查询 效率和辅助统计查询作用&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.2.6 增加冗余字段&lt;/h4&gt; &lt;blockquote&gt; &lt;p&gt;在设计数据库时，我们往往依照数据库的范式降低数据间的冗余度，但是冗余字段就像是把双刃剑，在业务需求上,有效的增加数据的冗余度，还可以提高数据的访问效率&lt;/p&gt; &lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;空间换时间&lt;/li&gt; &lt;li&gt;业务快照&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.2.7 分析表&lt;/h4&gt; &lt;p&gt;分析表主要是分析表中关键字的分布,检查表主要是检查表中是否存在错误,优化表主要是消除删除或更新造成的表空间浪费&lt;/p&gt; &lt;pre&gt;&lt;code class="language-sql"&gt;ANALYZE TABLE user; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;img src="https://cliveyuan.cn/upload/2020/03/ofid5d41hagbno1ufpgue2sbjc.png" alt="分析表" title="分析表" /&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Op: 表示执行的操作&lt;/li&gt; &lt;li&gt;Msg_type: 信息类型,有status,info,note,warning,error&lt;/li&gt; &lt;li&gt;Msg_text: 显示信息&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.2.8 检查表&lt;/h4&gt; &lt;blockquote&gt; &lt;p&gt;使用 CHECK关键字, 如CHECK TABLE &lt;code&gt;user&lt;/code&gt; [option]&lt;/p&gt; &lt;/blockquote&gt; &lt;pre&gt;&lt;code class="language-mysql"&gt;CHECK TABLE `user` FAST; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;img src="https://cliveyuan.cn/upload/2020/03/ssqgii0ldki0bps2s9sdm37hjn.png" alt="检查表" title="检查表" /&gt; option 只对MyISAM有效, 共五个参数值:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;QUICK: 不扫描行,不检查错误的连接&lt;/li&gt; &lt;li&gt;FAST: 只检查没有正确关闭的表&lt;/li&gt; &lt;li&gt;CHANGED: 只检查上次检查后被更改的表和没被正确关闭的表&lt;/li&gt; &lt;li&gt;MEDIUM: 扫描行,以验证被删除的连接是有效的,也可以计算各行关键字校验和&lt;/li&gt; &lt;li&gt;EXTENDED: 最全面的的检查,对每行关键字全面查找&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.2.9 优化表&lt;/h4&gt; &lt;blockquote&gt; &lt;p&gt;使用OPTIMIZE关键字,如OPTIMIZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE &lt;code&gt;user&lt;/code&gt;;&lt;/p&gt; &lt;/blockquote&gt; &lt;pre&gt;&lt;code class="language-sql"&gt;OPTIMIZE LOCAL TABLE `user`; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;img src="https://cliveyuan.cn/upload/2020/03/15vf4cuqfsgtoruh7lj0mv40h5.png" alt="优化表" title="优化表" /&gt; LOCAL | NO_WRITE_TO_BINLOG都是表示不写入日志，优化表只对VARCHAR, BLOB和TEXT有效, 通过OPTIMIZE TABLE语句可以消除文件碎片, 在执行过程中会加上只读锁&lt;/p&gt; &lt;h3&gt;3.3 硬优化&lt;/h3&gt; &lt;h4&gt;3.3.1 硬件配置&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;配置多核心和频率高的cpu,多核心可以执行多个线程&lt;/li&gt; &lt;li&gt;配置大内存,提高内存,即可提高缓存区容量,因此能减少磁盘I/O时间,从而提高响应速度&lt;/li&gt; &lt;li&gt;配置高速磁盘或合理分布磁盘:高速磁盘提高I/O,分布磁盘能提高并行操作的能力&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.3.2 优化数据库参数&lt;/h4&gt; &lt;p&gt;优化数据库参数可以提高资源利用率,从而提高MySQL服务器性能.MySQL服务的配置参数都在my.cnf或my.ini,下面列出性能影响较大的几个参数.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;key_buffer_size: 索引缓冲区大小&lt;/li&gt; &lt;li&gt;table_cache: 能同时打开表的个数&lt;/li&gt; &lt;li&gt;query_cache_size和query_cache_type:前者是查询缓冲区大小,后者是前面参数的开关,0表示不使用缓冲区,1表示使用缓冲区,但可以在查询中使用SQL_NO_CACHE表示不要使用缓冲区,2表示在查询中明确指出使用缓冲区才用缓冲区,即SQL_CACHE.&lt;/li&gt; &lt;li&gt;sort_buffer_size:排序缓冲区&lt;/li&gt; &lt;/ul&gt; &lt;h4&gt;3.3.3 分库分表 + 读写分离&lt;/h4&gt; &lt;p&gt;当数据量达到一定的数量之后，限制数据库存储性能的就不再是数据库层面的优化就能够解决的；这个时候往往采用的是读写分离与分库分表同时也会结合缓存一起使用，而这个时候数据库层面的优化只是基础。读写分离适用于较小一些的数据量；分表适用于中等数据量；而分库与分表一般是结合着用，这就适用于大数据量的存储了。分库分表 + 读写分离，也就是把一个库拆分为多个库，部署在多个数据库服务上，这时作为主库承载写入请求。然后每个主库都挂载至少一个从库，由从库来承载读请求，从而减轻服务器压力&lt;/p&gt; &lt;h4&gt;3.3.4 缓存集群&lt;/h4&gt; &lt;p&gt;缓存系统的设计就是为了承载高并发而生。所以单机承载的并发量都在每秒几万，甚至每秒数十万，对高并发的承载能力比数据库系统要高出一到两个数量级。就是在写数据库的时候同时写一份数据到缓存集群里，然后用缓存集群来承载大部分的读请求。这样的话，通过缓存集群，就可以用更少的机器资源承载更高的并发。&lt;/p&gt; &lt;h2&gt;4. 结语&lt;/h2&gt; &lt;p&gt;要快速定位和解决慢SQL问题需要对数据库结构和运行机制有足够的了解，在设计数据库时就要考虑到数据量级，创建合适的字段类型和索引，设计合理的表结构可以避免慢SQL&lt;/p&gt;</content:encoded>
      <pubDate>Fri, 20 Mar 2020 05:44:00 GMT</pubDate>
    </item>
    <item>
      <title>mysql授权ip远程访问</title>
      <link>https://cliveyuan.cn/article/39</link>
      <content:encoded>&lt;pre&gt;&lt;code&gt;/*授与所有权限给127.0.0.1这个ip 访问，如果不限制ip则填% */ GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1'  IDENTIFIED BY 'password' WITH GRANT OPTION;  /*添加权限:赋予username所有的db_name的数据库权限*/ GRANT ALL PRIVILEGES ON db_name.* TO 'username'@'%' WITH GRANT OPTION; &lt;/code&gt;&lt;/pre&gt; &lt;pre&gt;&lt;code&gt;/*刷新权限*/ flush privileges; &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Thu, 12 Mar 2020 01:21:00 GMT</pubDate>
    </item>
    <item>
      <title>mysql配置</title>
      <link>https://cliveyuan.cn/article/38</link>
      <content:encoded>&lt;h2&gt;解决Linux中mysql中文问号乱码&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;#[mysqld] character-set-server=utf8 init_connect='SET NAMES utf8'  [mysql] default-character-set=utf8  service mysqld restart;  show variables like 'character_set%'; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;解决mysql默认8小时断开&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;在mysql的my.ini最后加上  # this is myown dinifition for mysql connection timeout wait_timeout=31536000 interactive_timeout=31536000 &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Mon, 24 Feb 2020 09:15:00 GMT</pubDate>
    </item>
    <item>
      <title>Linux 安装 maven</title>
      <link>https://cliveyuan.cn/article/37</link>
      <content:encoded>&lt;h2&gt;下载maven包&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;cd ~  wget https://file.xlz168.cn/download/apache-maven-3.6.3.tar.gz  wget http://mirrors.hust.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz  &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;解压 &amp;amp; 移动&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;mkdir /home/software tar -zxvf apache-maven-3.6.3-bin.tar.gz mv apache-maven-3.6.3 /home/software &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;配置环境变量&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;vim /etc/profile  #mvn export MVN_HOME=/home/software/apache-maven-3.6.3 export PATH=$MVN_HOME/bin:$PATH  source /etc/profile  &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;验证&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;mvn -version &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;以上&lt;/p&gt;</content:encoded>
      <pubDate>Fri, 21 Feb 2020 02:30:00 GMT</pubDate>
    </item>
    <item>
      <title>CentOS 7 安装 Jenkins</title>
      <link>https://cliveyuan.cn/article/36</link>
      <content:encoded>&lt;h2 id="blogTitle0" style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;原文：&lt;a href="https://www.cnblogs.com/fangts/p/11095316.html" style="font-family: &amp;quot;Noto Sans&amp;quot;, sans-serif; font-size: 14px;"&gt;https://www.cnblogs.com/fangts/p/11095316.html&lt;/a&gt;&lt;/h2&gt;&lt;h2 id="blogTitle0" style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;准备工作&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;首选需要安装JAVA环境&amp;nbsp;&lt;a class="uri" href="https://www.cnblogs.com/stulzq/p/9286878.html" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline;"&gt;https://www.cnblogs.com/stulzq/p/9286878.html&lt;/a&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;如果你的系统没有自带git，那么也需要安装一个&lt;/p&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;yum install git&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="blogTitle1" style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;1.安装&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;第一种方法&lt;/p&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key &lt;p&gt;yum install jenkins&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;第二种方法&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;直接下载 rpm 安装&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;各个版本地址 &lt;a class="uri" href="https://pkg.jenkins.io/" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline;"&gt;https://pkg.jenkins.io/&lt;/a&gt;&lt;/p&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;wget https://pkg.jenkins.io/redhat/jenkins-2.156-1.1.noarch.rpm rpm -ivh jenkins-2.156-1.1.noarch.rpm&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="blogTitle2" style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;2.配置&lt;/h2&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;vim /etc/sysconfig/jenkins &lt;span class="hljs-meta" style="margin: 0px; padding: 0px; color: rgb(43, 145, 175);"&gt;&lt;span class="hljs-meta" style="margin: 0px; padding: 0px;"&gt; #&lt;/span&gt;&lt;span class="bash" style="margin: 0px; padding: 0px;"&gt;&lt;span class="bash" style="margin: 0px; padding: 0px;"&gt;监听端口&lt;/span&gt; JENKINS_PORT=&amp;quot;8080&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="blogTitle3" style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;3.配置权限&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;为了不因为权限出现各种问题，这里直接使用root&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;修改用户为root&lt;/p&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;vim /etc/sysconfig/jenkins &lt;span class="hljs-meta" style="margin: 0px; padding: 0px; color: rgb(43, 145, 175);"&gt;&lt;span class="hljs-meta" style="margin: 0px; padding: 0px;"&gt; #&lt;/span&gt;&lt;span class="bash" style="margin: 0px; padding: 0px;"&gt;&lt;span class="bash" style="margin: 0px; padding: 0px;"&gt;修改配置&lt;/span&gt; &lt;span class="hljs-meta" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-meta" style="margin: 0px; padding: 0px;"&gt;$&lt;/span&gt;&lt;span class="bash" style="margin: 0px; padding: 0px;"&gt;&lt;span class="bash" style="margin: 0px; padding: 0px;"&gt;JENKINS_USER=&lt;/span&gt;&lt;span class="hljs-string" style="margin: 0px; padding: 0px; color: rgb(163, 21, 21);"&gt;&lt;span class="bash" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-string" style="margin: 0px; padding: 0px;"&gt;&amp;quot;root&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;修改目录权限&lt;/p&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;chown -R root:root /var/lib/jenkins chown -R root:root /var/cache/jenkins chown -R root:root /var/log/jenkins&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;重启&lt;/p&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;service jenkins restart ps -ef | grep jenkins&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="blogTitle4" style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;4.启动&lt;/h2&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;systemctl start jenkins&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;我这里启动失败了：&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/668104/201807/668104-20180710201227396-1299962709.png" alt="1531198978143" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;错误信息为&lt;code style="margin: 0px; padding: 0px;"&gt;Starting Jenkins bash: /usr/bin/java: No such file or directory&lt;/code&gt;是java环境配置的问题。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;找到你的jdk目录，我是在 &lt;code style="margin: 0px; padding: 0px;"&gt;usr/local/java/jdk1.8.0_171/&lt;/code&gt;下，创建软链接即可：&lt;/p&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;ln -s /usr/local/java/jdk1.8.0_171/bin/java /usr/bin/java&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;然后重新启动&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/668104/201807/668104-20180710201226959-451256225.png" alt="1531199078302" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;h2 id="blogTitle5" style="margin-top: 20px; margin-bottom: 20px; padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;5.安装&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;访问jenkins地址 http:&amp;lt;ip或者域名&amp;gt;:8080&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/668104/201807/668104-20180710201226584-1112601029.png" alt="1531204667345" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;执行命令查看密码：&lt;/p&gt;&lt;pre class="shell" style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-size: 14px; background-color: rgb(255, 255, 255);"&gt;&lt;code class="hljs" style="margin: 0px;"&gt;cat /var/lib/jenkins/secrets/initialAdminPassword&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;插件安装选择推荐插件&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/668104/201807/668104-20180710201226138-1190837537.png" alt="1531204844660" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;安装进行中&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/668104/201807/668104-20180710201225629-148350366.png" alt="1531204864191" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;插件安装完成以后将会创建管理员账户&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/668104/201807/668104-20180710201225150-820617266.png" alt="1531205120250" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;安装完成：&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/668104/201807/668104-20180710201224689-1468094918.png" alt="1531205170165" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;设置Jenkins，安装插件：Pipeline Maven Integration、Maven Integration、Publish Over SSH、Gitee&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830095043782-995755011.png" alt="" width="352" height="397" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830095143070-374293857.png" alt="" width="750" height="250" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt; &lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;系统设置，配置远程应用服务器&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830094440953-86431378.png" alt="" width="608" height="474" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830115817866-1203719766.png" alt="" width="763" height="417" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830121057248-134756642.png" alt="" width="1490" height="568" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;全局工具配置，分别设置maven、jdk、git&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830121214296-1082763794.png" alt="" width="374" height="343" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt; &lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830171326624-1322101703.png" alt="" width="936" height="236" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830171815651-2034431037.png" alt="" width="685" height="217" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830171724966-1934138060.png" alt="" width="860" height="327" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt; &lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830171840068-818079831.png" alt="" width="749" height="233" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;创建构建任务&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830172434822-1227476137.png" alt="" width="1254" height="475" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;输入一个名字，例如我输入：helloPudding&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;进入配置页面，配置源代码&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830172628354-2030398254.png" alt="" width="1438" height="575" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830175701155-994811922.png" alt="" width="766" height="326" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;分两步操作&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;第一步 清理服务器环境 和 第二步 启动服务&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830182537821-588336501.png" alt="" width="1207" height="834" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;配置maven打包命令，并跳过单元测试。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt; &lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830182254097-1012308669.png" alt="" width="751" height="187" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;执行构建任务&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;img src="https://images2018.cnblogs.com/blog/482189/201808/482189-20180830182357734-1520613075.png" alt="" width="394" height="523" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; max-width: 800px; height: auto;"&gt;&lt;/p&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Sun, 16 Feb 2020 03:06:00 GMT</pubDate>
    </item>
    <item>
      <title>发布jar到公共仓库时遇到问题</title>
      <link>https://cliveyuan.cn/article/35</link>
      <content:encoded>&lt;ol&gt; &lt;li&gt;gpg 搜索不到public key&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;failureMessage No public key: Key with id: (1fcda02dd63733fe) was not ableto be located on http://pgp.mit.edu:11371/. Uploadyour public key and try the operation again.&lt;/p&gt; &lt;pre&gt;&lt;code&gt;gpg --keyserver http://pool.sks-keyservers.net:11371 --send-keys A81CC45E gpg --keyserver http://pgp.mit.edu:11371 --send-keys A81CC45E gpg --keyserver http://keyserver.ubuntu.com:11371 --send-keys A81CC45E  # 如果不行就将http换为hkp &lt;/code&gt;&lt;/pre&gt; &lt;ol start="2"&gt; &lt;li&gt;java doc 去掉docLint校验&lt;/li&gt; &lt;/ol&gt; &lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;plugin&amp;gt;                 &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;                 &amp;lt;artifactId&amp;gt;maven-javadoc-plugin&amp;lt;/artifactId&amp;gt;                 &amp;lt;version&amp;gt;2.9.1&amp;lt;/version&amp;gt;                 &amp;lt;executions&amp;gt;                     &amp;lt;execution&amp;gt;                         &amp;lt;id&amp;gt;attach-javadocs&amp;lt;/id&amp;gt;                         &amp;lt;goals&amp;gt;                             &amp;lt;goal&amp;gt;jar&amp;lt;/goal&amp;gt;                         &amp;lt;/goals&amp;gt;                         &amp;lt;configuration&amp;gt;                             &amp;lt;additionalparam&amp;gt;-Xdoclint:none&amp;lt;/additionalparam&amp;gt;                         &amp;lt;/configuration&amp;gt;                     &amp;lt;/execution&amp;gt;                 &amp;lt;/executions&amp;gt;             &amp;lt;/plugin&amp;gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;参考文章：&lt;a href="https://blog.csdn.net/qqhjqs/article/details/80963875" target="_blank"&gt;https://blog.csdn.net/qqhjqs/article/details/80963875&lt;/a&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 30 Oct 2019 07:42:00 GMT</pubDate>
    </item>
    <item>
      <title>centos7 中文乱码解决方法</title>
      <link>https://cliveyuan.cn/article/34</link>
      <content:encoded>&lt;p&gt;1.查看安装中文包： 查看系统是否安装中文语言包 （列出所有可用的公共语言环境的名称，包含有zh_CN）&lt;/p&gt; &lt;h1&gt;locale -a |grep &amp;quot;zh_CN&amp;quot;&lt;/h1&gt; &lt;p&gt;没有输出，说明没有安装，输入下面的命令安装：&lt;/p&gt; &lt;h1&gt;yum groupinstall &amp;quot;fonts&amp;quot; -y&lt;/h1&gt; &lt;p&gt;安装完成，查看安了哪些中文语言包&lt;/p&gt; &lt;h1&gt;locale -a |grep &amp;quot;zh_CN&amp;quot;&lt;/h1&gt; &lt;p&gt;zh_CN zh_CN.gb18030 zh_CN.gb2312 zh_CN.gbk zh_CN.utf8&lt;/p&gt; &lt;h1&gt;显示问题&lt;/h1&gt; &lt;p&gt;LC_CTYPE：用于字符分类和字符串处理，控制所有字符的处理方式，包括字符编码，字符是单字节还是多字节，如何打印等。是最重要的一个环境变量。&lt;/p&gt; &lt;p&gt;~/.bashrc 中添加 export LC_CTYPE='zh_CN.UTF-8'&lt;/p&gt;</content:encoded>
      <pubDate>Tue, 20 Aug 2019 09:28:00 GMT</pubDate>
    </item>
    <item>
      <title>cron 表达式示例</title>
      <link>https://cliveyuan.cn/article/33</link>
      <content:encoded>&lt;pre&gt;&lt;code&gt; 每隔5秒执行一次：*/5 * * * * ?   每隔1分钟执行一次：0 */1 * * * ?   每天23点执行一次：0 0 23 * * ?   每天凌晨1点执行一次：0 0 1 * * ?   每月1号凌晨1点执行一次：0 0 1 1 * ?   每月最后一天23点执行一次：0 0 23 L * ?   每周星期天凌晨1点实行一次：0 0 1 ? * L   在26分、29分、33分执行一次：0 26,29,33 * * * ?   每天的0点、13点、18点、21点都执行一次：0 0 0,13,18,21 * * ? &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Fri, 16 Aug 2019 12:55:00 GMT</pubDate>
    </item>
    <item>
      <title>Java中InputStream和String之间的转换方法</title>
      <link>https://cliveyuan.cn/article/32</link>
      <content:encoded>&lt;p&gt;详见 &lt;a href="https://blog.csdn.net/lmy86263/article/details/60479350" target="_blank"&gt;https://blog.csdn.net/lmy86263/article/details/60479350&lt;/a&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Mon, 12 Aug 2019 08:54:00 GMT</pubDate>
    </item>
    <item>
      <title>ssh-keygen 生成rsa密钥</title>
      <link>https://cliveyuan.cn/article/31</link>
      <content:encoded>&lt;h2&gt;全局配置&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;git config --global user.name &amp;quot;Clive Yuan&amp;quot; git config --global user.email &amp;quot;xxxx@foxmail.com&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;创建公钥的目的： 使用SSH公钥可以让你在你的电脑和码云通讯的时候使用安全连接（git的remote要使用SSH地址）&lt;/p&gt; &lt;h2&gt;打开终端进入.ssh目录&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;cd ~/.ssh     &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;如果.ssh文件夹不存在，执行指令自动创建&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;mkdir ~/.ssh &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;生成RSA密钥对&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;ssh-keygen -t rsa -C &amp;quot;你的邮箱@xxx.com&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;为了方便全程回车即可（不用输入ras文件名及密码）&lt;/h2&gt; &lt;h2&gt;查看公钥内容&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;cat ~/.ssh/id_rsa.pub &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;将公钥内容复制并粘贴（注意：公钥内容以ssh-rsa开头，你的邮箱结尾）&lt;/h2&gt; &lt;h3&gt;粘贴地址   &lt;a href="http://git.oschina.net/profile/sshkeys" target="_blank"&gt;http://git.oschina.net/profile/sshkeys&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;添加公钥完成后进行测试公钥&lt;/p&gt; &lt;h2&gt;测试SSH链接&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;ssh -T git@git.oschina.net &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;当终端提示welcome to Git@OSC ...  表示链接成功&lt;/h2&gt; &lt;h2&gt;至此以后只要拷贝ssh链接地址，然后利用git指令即可进行相关操作！&lt;/h2&gt; &lt;p&gt;祝你成功！&lt;/p&gt;</content:encoded>
      <pubDate>Sun, 11 Aug 2019 07:23:00 GMT</pubDate>
    </item>
    <item>
      <title>mysql高版本驱动日期时区不正确</title>
      <link>https://cliveyuan.cn/article/30</link>
      <content:encoded>&lt;p&gt;在高版本的mysql驱动中，数据库中的时间为正确的，但是查出来的时间与当前时间不匹配，相差了几个时区&lt;/p&gt; &lt;p&gt;解决方法： 数据库连接中添加 serverTimezone=Asia/Shanghai&lt;/p&gt;</content:encoded>
      <pubDate>Tue, 09 Jul 2019 02:14:00 GMT</pubDate>
    </item>
    <item>
      <title>MBG(MyBatis Generator) 生成字段添加反引号(`)</title>
      <link>https://cliveyuan.cn/article/29</link>
      <content:encoded>&lt;p&gt;数据库字段中有mysql关键字时，采用添加反引号的方法解决； 是引用MBG时，参考如下配置：&lt;/p&gt; &lt;pre&gt;&lt;code class="language-xml"&gt; &amp;lt;context id=&amp;quot;DB2Tables&amp;quot; targetRuntime=&amp;quot;MyBatis3&amp;quot;&amp;gt;         &amp;lt;property name=&amp;quot;javaFileEncoding&amp;quot; value=&amp;quot;UTF-8&amp;quot;/&amp;gt;         &amp;lt;property name=&amp;quot;autoDelimitKeywords&amp;quot; value=&amp;quot;true&amp;quot;/&amp;gt;         &amp;lt;property name=&amp;quot;beginningDelimiter&amp;quot; value=&amp;quot;`&amp;quot;/&amp;gt;         &amp;lt;property name=&amp;quot;endingDelimiter&amp;quot; value=&amp;quot;`&amp;quot;/&amp;gt;         &amp;lt;!-- other code ... --&amp;gt;         &amp;lt;/context&amp;gt; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如果没生效，试下&lt;code&gt;table&lt;/code&gt;标签中添加&lt;code&gt;delimitIdentifiers=&amp;quot;true&amp;quot;&lt;/code&gt; 默认是只有关键字的字段才加反引号，如果需要所有字段都加的话，在table标签中添加&lt;code&gt;delimitAllColumns=&amp;quot;true&amp;quot;&lt;/code&gt;属性&lt;/p&gt; &lt;p&gt;BTW:当时是因为其他子项目没编译通过，临时关闭了运行前编译，所以当时改了一通都没起作用。。。。&lt;/p&gt;</content:encoded>
      <pubDate>Tue, 25 Jun 2019 09:03:00 GMT</pubDate>
    </item>
    <item>
      <title>springboot 上传文件，MultipartFile为null</title>
      <link>https://cliveyuan.cn/article/28</link>
      <content:encoded>&lt;ol&gt; &lt;li&gt;排除&lt;code&gt;MultipartAutoConfiguration&lt;/code&gt;&lt;/li&gt; &lt;/ol&gt; &lt;pre&gt;&lt;code class="language-java"&gt;@SpringBootApplication (exclude = {MultipartAutoConfiguration.class}) &lt;/code&gt;&lt;/pre&gt; &lt;ol start="2"&gt; &lt;li&gt;添加&lt;code&gt;MultipartResolver&lt;/code&gt;&lt;/li&gt; &lt;/ol&gt; &lt;pre&gt;&lt;code class="language-java"&gt;//显示声明CommonsMultipartResolver为mutipartResolver     @Bean(name = &amp;quot;multipartResolver&amp;quot;)     public MultipartResolver multipartResolver() {         CommonsMultipartResolver resolver = new CommonsMultipartResolver();         resolver.setDefaultEncoding(&amp;quot;UTF-8&amp;quot;);         //resolveLazily属性启用是为了推迟文件解析，以在在UploadAction中捕获文件大小异常         resolver.setResolveLazily(true);         resolver.setMaxInMemorySize(40960);         //上传文件大小 5M 5*1024*1024         resolver.setMaxUploadSize(5 * 1024 * 1024);         return resolver;     } &lt;/code&gt;&lt;/pre&gt; &lt;ol start="3"&gt; &lt;li&gt;添加&lt;code&gt;@RequestParam&lt;/code&gt;&lt;/li&gt; &lt;/ol&gt; &lt;pre&gt;&lt;code class="language-java"&gt;@PostMapping(&amp;quot;/upload&amp;quot;)     public ApiResponse upload(@RequestParam(&amp;quot;file&amp;quot;) MultipartFile multipartFile) {      // other code ...     } &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Tue, 25 Jun 2019 08:59:00 GMT</pubDate>
    </item>
    <item>
      <title>centos7安装Nginx</title>
      <link>https://cliveyuan.cn/article/26</link>
      <content:encoded>&lt;h2 id="安装所需环境" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;安装所需环境&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;Nginx 是 C语言 开发，建议在 Linux 上运行，当然，也可以安装 Windows 版本，本篇则使用&amp;nbsp;&lt;a title="CentOS" href="http://www.linuxidc.com/topicnews.aspx?tid=14" target="_blank" style="margin: 0px; padding: 0px; color: black; text-decoration-line: underline;"&gt;CentOS&lt;/a&gt;&amp;nbsp;7 作为安装环境。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;一. gcc 安装&lt;/strong&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;安装 nginx 需要先将官网下载的源码进行编译，编译依赖 gcc 环境，如果没有 gcc 环境，则需要安装：&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs sql" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;yum &lt;span class="hljs-keyword" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px;"&gt;install&lt;/span&gt; gcc-&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px;"&gt;c++&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;二. PCRE pcre-devel 安装&lt;/strong&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;PCRE(Perl Compatible Regular Expressions) 是一个Perl库，包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式，所以需要在 linux 上安装 pcre 库，pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库。命令：&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs cmake" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;yum &lt;span class="hljs-keyword" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px;"&gt;install&lt;/span&gt; -y pcre pcre-devel&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;三. zlib 安装&lt;/strong&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;zlib 库提供了很多种压缩和解压缩的方式， nginx 使用 zlib 对 http 包的内容进行 gzip ，所以需要在 Centos 上安装 zlib 库。&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs cmake" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;yum &lt;span class="hljs-keyword" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px;"&gt;install&lt;/span&gt; -y zlib zlib-devel&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;四. OpenSSL 安装&lt;/strong&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;OpenSSL 是一个强大的安全套接字层密码库，囊括主要的密码算法、常用的密钥和证书封装管理功能及 SSL 协议，并提供丰富的应用程序供测试或其它目的使用。&lt;br style="margin: 0px; padding: 0px;"&gt;nginx 不仅支持 http 协议，还支持 https（即在ssl协议上传输http），所以需要在 Centos 安装 OpenSSL 库。&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs cmake" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;yum &lt;span class="hljs-keyword" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px;"&gt;install&lt;/span&gt; -y openssl openssl-devel&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="官网下载" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;官网下载&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;1.直接下载&lt;code style="margin: 0px; padding: 0px;"&gt;.tar.gz&lt;/code&gt;安装包，地址：&lt;a class="uri" href="https://nginx.org/en/download.html" style="margin: 0px; padding: 0px; color: black; text-decoration-line: underline;"&gt;https://nginx.org/en/download.html&lt;/a&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;img src="http://www.linuxidc.com/upload/2016_09/160905180451092.png" alt="nginx.png" width="706" vspace="5" style="margin: 0px; padding: 0px; max-width: 900px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;2.使用&lt;code style="margin: 0px; padding: 0px;"&gt;wget&lt;/code&gt;命令下载（推荐）。&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs swift" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;wget -&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px;"&gt;c&lt;/span&gt; https:&lt;span class="hljs-comment" style="margin: 0px; padding: 0px; color: rgb(136, 136, 136);"&gt;&lt;span class="hljs-comment" style="margin: 0px; padding: 0px;"&gt;//nginx.org/download/nginx-1.10.1.tar.gz&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;img src="http://www.linuxidc.com/upload/2016_09/160905180451091.png" alt="nginx-wget.png" width="706" vspace="5" style="margin: 0px; padding: 0px; max-width: 900px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;我下载的是1.10.1版本，这个是目前的稳定版。&lt;/p&gt;&lt;h2 id="解压" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;解压&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;依然是直接命令：&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs css" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;&lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;tar&lt;/span&gt; &lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;-zxvf&lt;/span&gt; &lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;nginx-1&lt;/span&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;.10&lt;/span&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;.1&lt;/span&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;.tar&lt;/span&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;.gz&lt;/span&gt; &lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;cd&lt;/span&gt; &lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-tag" style="margin: 0px; padding: 0px;"&gt;nginx-1&lt;/span&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;.10&lt;/span&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-selector-class" style="margin: 0px; padding: 0px;"&gt;.1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="配置" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;配置&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;其实在 nginx-1.10.1 版本中你就不需要去配置相关东西，默认就可以了。当然，如果你要自己配置目录也是可以的。&lt;br style="margin: 0px; padding: 0px;"&gt;1.使用默认配置&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;./configure&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;2.自定义配置（不推荐）&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs ruby" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;./configure \ --prefix=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px; color: rgb(0, 136, 0);"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/usr/local&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx \ --conf-path=/usr&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/local/nginx&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/conf/nginx&lt;/span&gt;.conf \ --pid-path=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/usr/local&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx/conf&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx.pid \ --lock-path=/var&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/lock/nginx&lt;/span&gt;.lock \ --error-log-path=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/var/log&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx/error&lt;/span&gt;.log \ --http-log-path=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/var/log&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx/access&lt;/span&gt;.log \ --with-http_gzip_static_module \ --http-client-body-temp-path=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/var/temp&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx/client&lt;/span&gt; \ --http-proxy-temp-path=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/var/temp&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx/proxy&lt;/span&gt; \ --http-fastcgi-temp-path=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/var/temp&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx/fastcgi&lt;/span&gt; \ --http-uwsgi-temp-path=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/var/temp&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx/uwsgi&lt;/span&gt; \ --http-scgi-temp-path=&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/var/temp&lt;/span&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-regexp" style="margin: 0px; padding: 0px;"&gt;/nginx/scgi&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote style="margin-top: 10px; margin-bottom: 10px; padding: 5px 10px; background: none rgb(238, 238, 238); border-width: 2px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-color: rgb(239, 239, 239); border-image: initial; min-height: 35px; line-height: 1.6em; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px;"&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;注：将临时文件目录指定为/var/temp/nginx，需要在/var下创建temp及nginx目录&lt;/p&gt;&lt;/blockquote&gt;&lt;h2 id="编译安装" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;编译安装&lt;/h2&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs go" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px;"&gt;make&lt;/span&gt; &lt;span class="hljs-built_in" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px;"&gt;make&lt;/span&gt; install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;查找安装路径：&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs nginx" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;&lt;span class="hljs-attribute" style="margin: 0px; padding: 0px; color: rgb(163, 21, 21);"&gt;&lt;span class="hljs-attribute" style="margin: 0px; padding: 0px;"&gt;whereis&lt;/span&gt; nginx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;img src="http://www.linuxidc.com/upload/2016_09/160905180451094.png" alt="nginx-whereis.png" width="706" vspace="5" style="margin: 0px; padding: 0px; max-width: 900px; height: auto;"&gt;&lt;/p&gt;&lt;h2 id="启动停止nginx" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;启动、停止nginx&lt;/h2&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs bash" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px;"&gt;cd&lt;/span&gt; /usr/&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px;"&gt;&lt;span class="hljs-built_in" style="margin: 0px; padding: 0px;"&gt;local&lt;/span&gt;/nginx/sbin/ ./nginx  ./nginx &lt;span class="hljs-_" style="margin: 0px; padding: 0px;"&gt;-s stop ./nginx &lt;span class="hljs-_" style="margin: 0px; padding: 0px;"&gt;-s quit ./nginx &lt;span class="hljs-_" style="margin: 0px; padding: 0px;"&gt;-s reload&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote style="margin-top: 10px; margin-bottom: 10px; padding: 5px 10px; background: none rgb(238, 238, 238); border-width: 2px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-color: rgb(239, 239, 239); border-image: initial; min-height: 35px; line-height: 1.6em; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px;"&gt;&lt;p style="margin: 10px auto; padding: 0px;"&gt;&lt;code style="margin: 0px; padding: 0px;"&gt;./nginx -s quit&lt;/code&gt;:此方式停止步骤是待nginx进程处理任务完毕进行停止。&lt;br style="margin: 0px; padding: 0px;"&gt;&lt;code style="margin: 0px; padding: 0px;"&gt;./nginx -s stop&lt;/code&gt;:此方式相当于先查出nginx进程id再使用kill命令强制杀掉进程。&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;查询nginx进程：&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs perl" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;ps aux|&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px;"&gt;grep&lt;/span&gt; nginx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="重启-nginx" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;重启 nginx&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;1.先停止再启动（推荐）：&lt;br style="margin: 0px; padding: 0px;"&gt;对 nginx 进行重启相当于先停止再启动，即先执行停止命令再执行启动命令。如下：&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs bash" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;./nginx &lt;span class="hljs-_" style="margin: 0px; padding: 0px;"&gt;-s quit ./nginx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;2.重新加载配置文件：&lt;br style="margin: 0px; padding: 0px;"&gt;当 ngin x的配置文件 nginx.conf 修改后，要想让配置生效需要重启 nginx，使用&lt;code style="margin: 0px; padding: 0px;"&gt;-s reload&lt;/code&gt;不用先停止 ngin x再启动 nginx 即可将配置信息在 nginx 中生效，如下：&lt;br style="margin: 0px; padding: 0px;"&gt;./nginx -s reload&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;启动成功后，在浏览器可以看到这样的页面：&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;img src="http://www.linuxidc.com/upload/2016_09/160905180451093.png" alt="nginx-welcome.png" width="706" vspace="5" style="margin: 0px; padding: 0px; max-width: 900px; height: auto;"&gt;&lt;/p&gt;&lt;h2 id="开机自启动" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;设置nginx全局变量&lt;/h2&gt;&lt;p style="padding: 0px; line-height: 1.5; background-color: rgb(238, 238, 238);"&gt;&lt;span style="color: rgb(0, 0, 0); font-family: Menlo, Monaco, Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; white-space: pre-wrap; background-color: rgb(240, 240, 240);"&gt;vi /etc/profile &lt;/span&gt;&lt;/p&gt;&lt;pre&gt;&lt;font face="Verdana, Arial, Helvetica, sans-serif"&gt;&lt;span style="font-size: 21px;"&gt;export NGINX_HOME=/usr/local/nginx export &lt;/span&gt;&lt;/font&gt;&lt;font face="Verdana, Arial, Helvetica, sans-serif"&gt;&lt;span style="font-size: 21px;"&gt;PATH=$NGINX_HOME/sbin:$PATH&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;h2 id="开机自启动" style="padding: 0px; font-size: 21px; font-weight: bold; line-height: 1.5; color: rgb(0, 0, 0); font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;开机自启动&lt;/h2&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;即在&lt;code style="margin: 0px; padding: 0px;"&gt;rc.local&lt;/code&gt;增加启动代码就可以了。&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs lua" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;vi /etc/rc.&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;local&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;增加一行&amp;nbsp;&lt;code style="margin: 0px; padding: 0px;"&gt;/usr/local/nginx/sbin/nginx&lt;/code&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;设置执行权限：&lt;/p&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; color: rgb(0, 0, 0); font-size: 14px; background-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs perl" style="margin: 0px; padding: 0.5em; display: block; overflow-x: auto; background: rgb(240, 240, 240); text-size-adjust: none; color: black;"&gt;&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px;"&gt;chmod&lt;/span&gt; &lt;span class="hljs-number" style="margin: 0px; padding: 0px; color: rgb(0, 136, 0);"&gt;&lt;span class="hljs-number" style="margin: 0px; padding: 0px;"&gt;755&lt;/span&gt; rc.&lt;span class="hljs-keyword" style="margin: 0px; padding: 0px; color: rgb(0, 0, 255);"&gt;local&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&lt;img src="http://www.linuxidc.com/upload/2016_09/160905180451095.png" alt="nginx-rclocal.png" width="706" vspace="5" style="margin: 0px; padding: 0px; max-width: 900px; height: auto;"&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;到这里，nginx就安装完毕了，启动、停止、重启操作也都完成了，当然，你也可以添加为系统服务，我这里就不在演示了。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(238, 238, 238);"&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;</content:encoded>
      <pubDate>Sat, 22 Jun 2019 15:57:00 GMT</pubDate>
    </item>
    <item>
      <title>CentOS7下安装mysql5.7</title>
      <link>https://cliveyuan.cn/article/25</link>
      <content:encoded>&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;1、安装YUM Repo&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;由于CentOS 的yum源中没有mysql，需要到mysql的官网下载yum repo配置文件。&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;wget https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;然后进行repo的安装：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;rpm -ivh mysql57-community-release-el7-9.noarch.rpm&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;执行完成后会在&lt;code style="margin: 0px; padding: 0px;"&gt;/etc/yum.repos.d/&lt;/code&gt;目录下生成两个repo文件&lt;code style="margin: 0px; padding: 0px;"&gt;mysql-community.repo&lt;/code&gt;&amp;nbsp;&lt;code style="margin: 0px; padding: 0px;"&gt;mysql-community-source.repo&lt;/code&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;2、安装MySQL&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;使用yum命令即可完成安装&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;yum install mysql-server&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;启动msyql：&lt;/strong&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;systemctl start mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;启动MySQL&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;配置MySQL&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;获取安装时的临时密码：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;grep &lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;'&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;temporary password&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;'&lt;/span&gt; /var/log/mysqld.log&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;倘若没有：&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;1.删除原来安装过的mysql残留的数据&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;rm -rf /var/lib/mysql&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;2.再启动mysql&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;systemctl start mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;启动MySQL&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;登录：&lt;/strong&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;mysql -u root -p&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;登录成功后修改密码：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;set password=password(&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;yourpassword&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&amp;nbsp;设置安全选项：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;mysql_secure_installation&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;其他设置：&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;systemctl stop mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;关闭MySQL&lt;/span&gt; systemctl restart mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;重启MySQL&lt;/span&gt; systemctl status mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;查看MySQL运行状态&lt;/span&gt; systemctl enable mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;设置开机启动&lt;/span&gt; systemctl disable mysqld &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;关闭开机启动&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 style="padding: 0px; font-size: 16px; font-weight: bold; line-height: 1.5; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&amp;nbsp;3、其他配置&lt;/h3&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;开启远程控制&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;MySQL默认是没有开启远程控制的，必须添加远程访问的用户&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;grant all privileges on 数据库名.表名 to 创建的用户名(root)@&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;%&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt; identified by &lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;密码&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;"&lt;/span&gt;; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt; 数据库名.表名 如果写成*.*代表授权所有的数据库 &lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt; flush privileges; &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;刷新刚才的内容&lt;br style="margin: 0px; padding: 0px;"&gt;&lt;br style="margin: 0px; padding: 0px;"&gt;#如：&lt;br style="margin: 0px; padding: 0px;"&gt;grant all privileges on *.* to root@"113.64.243.1" identified by "123456789";&lt;br style="margin: 0px; padding: 0px;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px;"&gt;&lt;span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"&gt;&lt;a title="复制代码" style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); text-decoration-line: underline; background-color: rgb(245, 245, 245) !important; border: none !important;"&gt;&lt;img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 800px; height: auto; border-width: initial !important; border-style: none !important;"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;@ 后面是访问mysql的客户端IP地址（或是 主机名） % 代表任意的客户端，如果填写 localhost 为本地访问（那此用户就不能远程访问该mysql数据库了）。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;同时也可以为现有的用户设置是否具有远程访问权限。&lt;/p&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;配置默认编码为utf8：&lt;/strong&gt;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;vi /etc/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;my.cnf &lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;#&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 128, 0); line-height: 1.5 !important;"&gt;添加&lt;/span&gt; &lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;[mysqld] character_set_server&lt;/span&gt;=&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;utf8 init_connect&lt;/span&gt;=&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;'&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;SET NAMES utf8&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(128, 0, 0); line-height: 1.5 !important;"&gt;'&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p style="margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;strong style="margin: 0px; padding: 0px;"&gt;其他默认配置文件路径：&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); border: 1px solid rgb(204, 204, 204); overflow: auto; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;&lt;pre style="margin-bottom: 0px; padding: 0px; white-space: pre-wrap; font-family: &amp;quot;Courier New&amp;quot; !important; font-size: 12px !important;"&gt;配置文件：/etc/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;my.cnf  日志文件：&lt;/span&gt;/var/log//var/log/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;mysqld.log  服务启动脚本：&lt;/span&gt;/usr/lib/systemd/system/&lt;span style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); line-height: 1.5 !important;"&gt;mysqld.service  socket文件：&lt;/span&gt;/var/run/mysqld/mysqld.pid&lt;/pre&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded>
      <pubDate>Sat, 22 Jun 2019 15:53:00 GMT</pubDate>
    </item>
    <item>
      <title>PE私钥文件转字符串</title>
      <link>https://cliveyuan.cn/article/24</link>
      <content:encoded>&lt;pre&gt;&lt;code class="language-shell"&gt;openssl pkcs8 -topk8 -inform PEM -in clive.private.pem -outform PEM -nocrypt &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Wed, 19 Jun 2019 03:32:00 GMT</pubDate>
    </item>
    <item>
      <title>maven 使用指南</title>
      <link>https://cliveyuan.cn/article/23</link>
      <content:encoded>&lt;h2&gt;下载源码&lt;/h2&gt; &lt;pre&gt;&lt;code&gt;mvn dependency:resolve -Dclassifier=sources &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Wed, 13 Mar 2019 02:16:00 GMT</pubDate>
    </item>
    <item>
      <title>【MAC】命令行终端切换wifi</title>
      <link>https://cliveyuan.cn/article/22</link>
      <content:encoded>&lt;p&gt;查看wifi对应设备名&lt;/p&gt; &lt;p&gt;networksetup -listallhardwareports&lt;/p&gt; &lt;p&gt;关闭wifi&lt;/p&gt; &lt;p&gt;networksetup -setairportpower en0 off   //en0  设备名&lt;/p&gt; &lt;p&gt;打开wifi&lt;/p&gt; &lt;p&gt;networksetup -setairportpower en0 on&lt;/p&gt; &lt;p&gt;加入wifi&lt;/p&gt; &lt;p&gt;networksetup -setairportnetwork en0  wifi名  wifi密码&lt;/p&gt; &lt;p&gt;tips：企业证书认证的wifi，无法获取密码，不能连接。&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 13 Mar 2019 02:14:00 GMT</pubDate>
    </item>
    <item>
      <title>JDK环境安装与配置（Windows 10）</title>
      <link>https://cliveyuan.cn/article/21</link>
      <content:encoded>&lt;div class="article"&gt;&lt;div data-note-content="" class="show-content"&gt;&lt;div class="show-content-free"&gt;&lt;h1&gt;1.官网下载地址&lt;/h1&gt; &lt;blockquote&gt; &lt;p&gt;&lt;a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html"&gt;http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;/a&gt;&lt;a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;img src="https://upload-images.jianshu.io/upload_images/2662937-1b4617501418cebf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"&gt;&lt;br&gt;&lt;/p&gt; &lt;h1&gt;2.安装&lt;/h1&gt; &lt;blockquote&gt; &lt;p&gt;双击jdk-8u171-windows-x64.exe，选择目标安装目录，一般默认安装。&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;3.配置环境变量&lt;/h1&gt; &lt;blockquote&gt; &lt;p&gt;1.新建系统变量：&lt;br&gt; 变量名（N）：JAVA_HOME&lt;br&gt; 变量值（V）：jdk的安装路径&lt;/p&gt; &lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;2.新建系统变量：&lt;br&gt; 变量名（N）：CLASSPATH&lt;br&gt; 变量值（V）：.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;&lt;/p&gt; &lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;3.添加修改系统变量：&lt;br&gt; 变量名（N）：Path&lt;br&gt; 变量值（V）：;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;4.验证&lt;/h1&gt; &lt;blockquote&gt; &lt;p&gt;运行cmd，输入命令：java -version 和 javac -version&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;显示如下JDK版本信息即可:&lt;br&gt; java version "1.8.0_171"&lt;br&gt; Java(TM) SE Runtime Environment (build 1.8.0_171-b11)&lt;br&gt; Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)&lt;/p&gt; &lt;/blockquote&gt;</content:encoded>
      <pubDate>Mon, 11 Mar 2019 03:32:00 GMT</pubDate>
    </item>
    <item>
      <title>JDK环境安装与配置（Linux CentOS 7）</title>
      <link>https://cliveyuan.cn/article/20</link>
      <content:encoded>&lt;div&gt;&lt;div&gt;&lt;span style="background-color: rgb(255, 255, 0);"&gt;&lt;font color="#ff0000"&gt;&lt;b&gt;本文安装JDK的版本为JDK1.8&lt;/b&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;更新系统软件&lt;/li&gt; &lt;/ol&gt; &lt;pre class="hljs undefined"&gt;&lt;code&gt;yum update &lt;/code&gt;&lt;/pre&gt; &lt;ol start="2"&gt; &lt;li&gt;查找系统已安装的jdk组件&lt;/li&gt; &lt;/ol&gt; &lt;pre class="hljs ruby"&gt;&lt;code class="ruby"&gt;rpm -qa &lt;span class="hljs-params"&gt;| grep -E '^open[jre|&lt;/span&gt;jdk]&lt;span class="hljs-params"&gt;|j[re|&lt;/span&gt;dk]&lt;span class="hljs-string"&gt;' &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; &lt;ol start="3"&gt; &lt;li&gt;查看java版本&lt;/li&gt; &lt;/ol&gt; &lt;pre class="hljs undefined"&gt;&lt;code&gt;java -version &lt;/code&gt;&lt;/pre&gt; &lt;ol start="4"&gt; &lt;li&gt;卸载以前已有的jdk&lt;/li&gt; &lt;/ol&gt; &lt;pre class="hljs css"&gt;&lt;code class="css"&gt;&lt;span class="hljs-selector-tag"&gt;yum&lt;/span&gt; &lt;span class="hljs-selector-tag"&gt;remove&lt;/span&gt; &lt;span class="hljs-selector-tag"&gt;java-1&lt;/span&gt;&lt;span class="hljs-selector-class"&gt;.6&lt;/span&gt;&lt;span class="hljs-selector-class"&gt;.0-openjdk&lt;/span&gt; &lt;span class="hljs-selector-tag"&gt;yum&lt;/span&gt; &lt;span class="hljs-selector-tag"&gt;remove&lt;/span&gt; &lt;span class="hljs-selector-tag"&gt;java-1&lt;/span&gt;&lt;span class="hljs-selector-class"&gt;.7&lt;/span&gt;&lt;span class="hljs-selector-class"&gt;.0-openjdk&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt; &lt;ol start="5"&gt; &lt;li&gt;在/usr目录中先建名为java的文件夹&lt;/li&gt; &lt;/ol&gt; &lt;pre class="hljs undefined"&gt;&lt;code&gt;mkdir /usr/java&lt;/code&gt;&lt;/pre&gt;&lt;ol start="6"&gt;&lt;li&gt;下载jdk-8u111-linux-x64.tar.gz包，并上传至服务器/usr/java文件夹中。&lt;br&gt;&lt;pre class="hljs undefined" style="line-height: 1.42857;"&gt;&lt;span style="white-space: pre-wrap;"&gt;url: &lt;/span&gt;&lt;a href="https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html"&gt;https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;/a&gt; wget xxx.tar.gz &lt;/pre&gt;&lt;pre class="hljs undefined" style="line-height: 1.42857;"&gt;wget &lt;a href="https://file.xlz168.cn/download/jdk-8u241-linux-x64.tar.gz"&gt;https://file.xlz168.cn/download/jdk-8u241-linux-x64.tar.gz&lt;/a&gt;&lt;br&gt;&lt;/pre&gt;&lt;p style="line-height: 1.42857;"&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;解压jdk-8u111-linux-x64.tar.gz包至/usr/java/jdk1.8.0_111文件夹&lt;/li&gt; &lt;/ol&gt; &lt;pre class="hljs css"&gt;&lt;span style="white-space: pre-wrap;"&gt;tar -xvf jdk-8u241-linux-x64.tar.gz&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;pre class="hljs css"&gt;mv jdk1.8.0_241 /usr/java/&lt;br&gt;&lt;/pre&gt; &lt;ol start="8"&gt; &lt;li&gt;添加到环境变量&lt;/li&gt; &lt;/ol&gt; &lt;ul&gt; &lt;li&gt;编辑/etc/profile文件，在&lt;em&gt;export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL&lt;/em&gt;下面添加如下代码：&lt;/li&gt; &lt;/ul&gt; &lt;pre class="hljs bash"&gt;&lt;code class="bash"&gt;&lt;span class="hljs-comment"&gt;#jdk&lt;/span&gt; &lt;span class="hljs-built_in"&gt;export&lt;/span&gt; JAVA_HOME=/usr/&lt;span class="hljs-built_in"&gt;java&lt;/span&gt;/jdk1.8.0_241 &lt;span class="hljs-built_in"&gt;export&lt;/span&gt; PATH=&lt;span class="hljs-variable"&gt;$JAVA_HOME&lt;/span&gt;/bin:&lt;span class="hljs-variable"&gt;$PATH&lt;/span&gt; &lt;span class="hljs-built_in"&gt;export&lt;/span&gt; CLASSPATH=.:&lt;span class="hljs-variable"&gt;$JAVA_HOME&lt;/span&gt;/lib/dt.jar:&lt;span class="hljs-variable"&gt;$JAVA_HOME&lt;/span&gt;/lib/tools.jar &lt;/code&gt;&lt;/pre&gt; &lt;ul&gt; &lt;li&gt;执行命令使配置生效&lt;/li&gt; &lt;/ul&gt; &lt;pre class="hljs bash"&gt;&lt;code class="bash"&gt;&lt;span class="hljs-built_in"&gt;source&lt;/span&gt; /etc/profile &lt;/code&gt;&lt;/pre&gt; &lt;ol start="9"&gt; &lt;li&gt;验证，是否安装成功&lt;/li&gt; &lt;/ol&gt; &lt;pre class="hljs undefined"&gt;&lt;code&gt;java -version&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;</content:encoded>
      <pubDate>Mon, 11 Mar 2019 03:25:00 GMT</pubDate>
    </item>
    <item>
      <title>VirtualBox中安装CentOS7后无法上网的解决方案</title>
      <link>https://cliveyuan.cn/article/18</link>
      <content:encoded>&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-bottom: 16px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; font-size: 16px; color: rgb(79, 79, 79); line-height: 26px; overflow-wrap: break-word; font-variant-ligatures: common-ligatures;"&gt;&lt;br&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; font-size: 16px; color: rgb(79, 79, 79); line-height: 26px; overflow-wrap: break-word; font-variant-ligatures: common-ligatures;"&gt;安装了VirtualBox（CentOS7镜像）后无法上网，在网上找到了相应解决方案，所以分享记录下来&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; font-size: 16px; color: rgb(79, 79, 79); line-height: 26px; overflow-wrap: break-word; font-variant-ligatures: common-ligatures;"&gt;1 配置VirtualBox的虚拟网卡&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; font-size: 16px; color: rgb(79, 79, 79); line-height: 26px; overflow-wrap: break-word; font-variant-ligatures: common-ligatures;"&gt;1）打开网络和共享中心，找到VirtualBox Host-Only Network&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;&lt;img title="" alt="这里写图片描述" src="https://img-blog.csdn.net/2018041520504556?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FpYW5feGlhX2Vy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" style="outline-style: initial; outline-width: 0px; border-style: none; margin: 24px 0px; max-width: 100%; overflow-wrap: break-word; cursor: zoom-in;"&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; font-size: 16px; color: rgb(79, 79, 79); line-height: 26px; overflow-wrap: break-word; font-variant-ligatures: common-ligatures;"&gt;2) 双击该适配器，点击属性，为网卡配置上IPv4的地址以及子网掩码，如下图所示。因为我的主机使用的是无线网络，所以主机的ip地址是192.168.0.102，子网掩码是255.255.255.0， 默认网关、dhcp服务器、dns服务器都是192.168.0.1. 这里VirtualBox虚拟网卡的IP地址设置一个和&lt;a href="https://www.baidu.com/s?wd=%E4%B8%BB%E6%9C%BA%E5%9C%B0%E5%9D%80&amp;amp;tn=24004469_oem_dg&amp;amp;rsv_dl=gh_pl_sl_csd" target="_blank" style="outline-style: initial; outline-width: 0px; color: rgb(103, 149, 181); cursor: pointer; overflow-wrap: break-word;"&gt;主机地址&lt;/a&gt;同一网段的地址（192.168.0.110，这个地址也是将来虚拟机里网卡的默认网关地址），掩码设置和主机一样，其它的都不设置。&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;&lt;img title="" alt="这里写图片描述" src="https://img-blog.csdn.net/20180415205123668?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FpYW5feGlhX2Vy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" style="outline-style: initial; outline-width: 0px; border-style: none; margin: 24px 0px; max-width: 100%; overflow-wrap: break-word; cursor: zoom-in;"&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; font-size: 16px; color: rgb(79, 79, 79); line-height: 26px; overflow-wrap: break-word; font-variant-ligatures: common-ligatures;"&gt;2 配置虚拟机的网卡&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;1）按照下图配置虚拟机的网络&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;&lt;img title="" alt="这里写图片描述" src="https://img-blog.csdn.net/20180415205146792?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FpYW5feGlhX2Vy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" style="outline-style: initial; outline-width: 0px; border-style: none; margin: 24px 0px; max-width: 100%; overflow-wrap: break-word; cursor: zoom-in;"&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; font-size: 16px; color: rgb(79, 79, 79); line-height: 26px; overflow-wrap: break-word; font-variant-ligatures: common-ligatures;"&gt;其中，连接方式选择桥接网卡、界面名称选择你主机上网用的无线网卡、控制芯片选择桌面、混杂模式选择拒绝、勾选接入网络。&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;2）设置完成后，启动虚拟机&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;3 配置CentOS7的网络&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;1）修改网卡对应的配置文件，设置BOOTPROTO为dhcp，ONBOOT为yes&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;$ vi /etc/sysconfig/network-scripts/ifcfg-enp0s3&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;&lt;img title="" alt="这里写图片描述" src="https://img-blog.csdn.net/20180415205230494?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FpYW5feGlhX2Vy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" style="outline-style: initial; outline-width: 0px; border-style: none; margin: 24px 0px; max-width: 100%; overflow-wrap: break-word; cursor: zoom-in;"&gt;&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;2）修改网关，设置NETWORKING为yes，GATEWAY为VirtualBox虚拟网卡的ip地址&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;$ vi /etc/sysconfig/network&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;&lt;img title="" alt="这里写图片描述" src="https://img-blog.csdn.net/20180415205400118?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FpYW5feGlhX2Vy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" style="outline-style: initial; outline-width: 0px; border-style: none; margin: 24px 0px; max-width: 100%; overflow-wrap: break-word; cursor: zoom-in;"&gt;&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;3）修改DNS，设置nameserver为host主机的nameserver&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;$ vi /etc/resolv.cof&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;&lt;img title="" alt="这里写图片描述" src="https://img-blog.csdn.net/20180415205454486?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FpYW5feGlhX2Vy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" style="outline-style: initial; outline-width: 0px; border-style: none; margin: 24px 0px; max-width: 100%; overflow-wrap: break-word; cursor: zoom-in;"&gt;&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;4) 重启网络服务，&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;$ service network restart&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;至此，整个配置就结束了，虚拟机也&lt;a href="https://www.baidu.com/s?wd=%E8%83%BD%E4%B8%8A%E7%BD%91&amp;amp;tn=24004469_oem_dg&amp;amp;rsv_dl=gh_pl_sl_csd" target="_blank" style="outline-style: initial; outline-width: 0px; color: rgb(103, 149, 181); cursor: pointer; overflow-wrap: break-word;"&gt;能上网&lt;/a&gt;了。&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; font-size: 16px; color: rgb(79, 79, 79); line-height: 26px; overflow-wrap: break-word; font-variant-ligatures: common-ligatures;"&gt;如果还不行的话可以先将防火墙关掉&amp;nbsp;&lt;br style="outline-style: initial; outline-width: 0px; overflow-wrap: break-word;"&gt;syetemctl stop firewalld&lt;/p&gt;</content:encoded>
      <pubDate>Fri, 08 Mar 2019 07:57:00 GMT</pubDate>
    </item>
    <item>
      <title>一键搭建shadowsocks</title>
      <link>https://cliveyuan.cn/article/17</link>
      <content:encoded>&lt;blockquote&gt; &lt;p&gt;原文 &lt;a href="https://www.flyzy2005.com/fan-qiang/shadowsocks/bandwagonhost-shadowsocks/" target="_blank"&gt;https://www.flyzy2005.com/fan-qiang/shadowsocks/bandwagonhost-shadowsocks/&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;github源码地址：&lt;/strong&gt; &lt;a href="https://github.com/flyzy2005/ss-fly" target="_blank"&gt;https://github.com/flyzy2005/ss-fly&lt;/a&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 20 Feb 2019 02:27:00 GMT</pubDate>
    </item>
    <item>
      <title>MySQL索引原理及慢查询优化</title>
      <link>https://cliveyuan.cn/article/16</link>
      <content:encoded>&lt;blockquote style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;&lt;p&gt;转自：&lt;a href="https://tech.meituan.com/2014/06/30/mysql-index.html"&gt;https://tech.meituan.com/2014/06/30/mysql-index.html&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h6 style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;背景&lt;br&gt;&lt;/h6&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;MySQL凭借着出色的性能、低廉的成本、丰富的资源，已经成为绝大多数互联网公司的首选关系型数据库。虽然性能出色，但所谓“好马配好鞍”，如何能够更好的使用它，已经成为开发工程师的必修课，我们经常会从职位描述上看到诸如“精通MySQL”、“SQL语句优化”、“了解数据库原理”等要求。我们知道一般的应用系统，读写比例在10:1左右，而且插入操作和一般的更新操作很少出现性能问题，遇到最多的，也是最容易出问题的，还是一些复杂的查询操作，所以查询语句的优化显然是重中之重。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;本人从13年7月份起，一直在美团核心业务系统部做慢查询的优化工作，共计十余个系统，累计解决和积累了上百个慢查询案例。随着业务的复杂性提升，遇到的问题千奇百怪，五花八门，匪夷所思。本文旨在以开发工程师的角度来解释数据库索引的原理和如何优化慢查询。&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt;    &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;count&lt;/span&gt;(*)  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt;    task  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;where&lt;/span&gt;    &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;status&lt;/span&gt;=&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;2&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; operator_id=&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;20839&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; operate_time&amp;gt;&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1371169729&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; operate_time&amp;lt;&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1371174603&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;type&lt;/span&gt;=&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;2&lt;/span&gt;; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;系统使用者反应有一个功能越来越慢，于是工程师找到了上面的SQL。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;并且兴致冲冲的找到了我，“这个SQL需要优化，给我把每个字段都加上索引”。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;我很惊讶，问道：“为什么需要每个字段都加上索引？”&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;“把查询的字段都加上索引会更快”，工程师信心满满。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;“这种情况完全可以建一个联合索引，因为是最左前缀匹配，所以operate_time需要放到最后，而且还需要把其他相关的查询都拿来，需要做一个综合评估。”&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;“联合索引？最左前缀匹配？综合评估？”工程师不禁陷入了沉思。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;多数情况下，我们知道索引能够提高查询效率，但应该如何建立索引？索引的顺序如何？许多人却只知道大概。其实理解这些概念并不难，而且索引的原理远没有想象的那么复杂。&lt;/p&gt;&lt;h2 id="索引目的" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;索引目的&lt;/h2&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;索引的目的在于提高查询效率，可以类比字典，如果要查“mysql”这个单词，我们肯定需要定位到m字母，然后从下往下找到y字母，再找到剩下的sql。如果没有索引，那么你可能需要把所有单词看一遍才能找到你想要的，如果我想找到m开头的单词呢？或者ze开头的单词呢？是不是觉得如果没有索引，这个事情根本无法完成？&lt;/p&gt;&lt;h2 id="索引原理" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;索引原理&lt;/h2&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;除了词典，生活中随处可见索引的例子，如火车站的车次表、图书的目录等。它们的原理都是一样的，通过不断的缩小想要获得数据的范围来筛选出最终想要的结果，同时把随机的事件变成顺序的事件，也就是我们总是通过同一种查找方式来锁定数据。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;数据库也是一样，但显然要复杂许多，因为不仅面临着等值查询，还有范围查询(&amp;gt;、&amp;lt;、between、in)、模糊查询(like)、并集查询(or)等等。数据库应该选择怎么样的方式来应对所有的问题呢？我们回想字典的例子，能不能把数据分成段，然后分段查询呢？最简单的如果1000条数据，1到100分成第一段，101到200分成第二段，201到300分成第三段……这样查第250条数据，只要找第三段就可以了，一下子去除了90%的无效数据。但如果是1千万的记录呢，分成几段比较好？稍有算法基础的同学会想到搜索树，其平均复杂度是lgN，具有不错的查询性能。但这里我们忽略了一个关键的问题，复杂度模型是基于每次相同的操作成本来考虑的，数据库实现比较复杂，数据保存在磁盘上，而为了提高性能，每次又可以把部分数据读入内存来计算，因为我们知道访问磁盘的成本大概是访问内存的十万倍左右，所以简单的搜索树难以满足复杂的应用场景。&lt;/p&gt;&lt;h3 id="磁盘io与预读" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 22px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;磁盘IO与预读&lt;/h3&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;前面提到了访问磁盘，那么这里先简单介绍一下磁盘IO和预读，磁盘读取数据靠的是机械运动，每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分，寻道时间指的是磁臂移动到指定磁道所需要的时间，主流磁盘一般在5ms以下；旋转延迟就是我们经常听说的磁盘转速，比如一个磁盘7200转，表示每分钟能转7200次，也就是说1秒钟能转120次，旋转延迟就是1/120/2 = 4.17ms；传输时间指的是从磁盘读出或将数据写入磁盘的时间，一般在零点几毫秒，相对于前两个时间可以忽略不计。那么访问一次磁盘的时间，即一次磁盘IO的时间约等于5+4.17 = 9ms左右，听起来还挺不错的，但要知道一台500 -MIPS的机器每秒可以执行5亿条指令，因为指令依靠的是电的性质，换句话说执行一次IO的时间可以执行40万条指令，数据库动辄十万百万乃至千万级数据，每次9毫秒的时间，显然是个灾难。下图是计算机硬件延迟的对比图，供大家参考：&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;&lt;img src="https://awps-assets.meituan.net/mit-x/blog-images-bundle-2014/7f46a0a4.png" alt="various-system-software-hardware-latencies" style="display: block; margin: 2rem auto 0.2rem; max-width: 75%; cursor: pointer;"&gt;&lt;/p&gt;&lt;div class="img-figure" style="margin: 0.5rem 0px 1.5rem; text-align: center;"&gt;&lt;span style="padding: 0.4rem 1rem; color: rgb(119, 119, 119); font-size: 1.2rem; font-family: serif;"&gt;various-system-software-hardware-latencies&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;考虑到磁盘IO是非常高昂的操作，计算机操作系统做了一些优化，当一次IO时，不光把当前磁盘地址的数据，而是把相邻的数据也都读取到内存缓冲区内，因为局部预读性原理告诉我们，当计算机访问一个地址的数据的时候，与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关，一般为4k或8k，也就是我们读取一页内的数据时候，实际上才发生了一次IO，这个理论对于索引的数据结构设计非常有帮助。&lt;/p&gt;&lt;h3 id="索引的数据结构" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 22px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;索引的数据结构&lt;/h3&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;前面讲了生活中索引的例子，索引的基本原理，数据库的复杂性，又讲了操作系统的相关知识，目的就是让大家了解，任何一种数据结构都不是凭空产生的，一定会有它的背景和使用场景，我们现在总结一下，我们需要这种数据结构能够做些什么，其实很简单，那就是：每次查找数据时把磁盘IO次数控制在一个很小的数量级，最好是常数数量级。那么我们就想到如果一个高度可控的多路搜索树是否能满足需求呢？就这样，b+树应运而生。&lt;/p&gt;&lt;h3 id="详解b-树" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 22px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;详解b+树&lt;/h3&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;&lt;img src="https://awps-assets.meituan.net/mit-x/blog-images-bundle-2014/7af22798.jpg" alt="b+树" style="display: block; margin: 2rem auto 0.2rem; max-width: 75%; cursor: pointer;"&gt;&lt;/p&gt;&lt;div class="img-figure" style="margin: 0.5rem 0px 1.5rem; text-align: center;"&gt;&lt;span style="padding: 0.4rem 1rem; color: rgb(119, 119, 119); font-size: 1.2rem; font-family: serif;"&gt;b+树&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;如上图，是一颗b+树，关于b+树的定义可以参见&lt;a href="http://zh.wikipedia.org/wiki/B%2B%E6%A0%91" style="text-decoration-line: underline; color: rgb(22, 185, 169); margin: 0px 4px;"&gt;B+树&lt;span class="fa fa-link" aria-hidden="true" style="font-size: 10px; margin: 0px; padding-left: 2px; vertical-align: text-top; font-family: iconfont !important;"&gt;&lt;/span&gt;&lt;/a&gt;，这里只说一些重点，浅蓝色的块我们称之为一个磁盘块，可以看到每个磁盘块包含几个数据项（深蓝色所示）和指针（黄色所示），如磁盘块1包含数据项17和35，包含指针P1、P2、P3，P1表示小于17的磁盘块，P2表示在17和35之间的磁盘块，P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非叶子节点只不存储真实的数据，只存储指引搜索方向的数据项，如17、35并不真实存在于数据表中。&lt;/p&gt;&lt;h3 id="b-树的查找过程" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 22px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;b+树的查找过程&lt;/h3&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;如图所示，如果要查找数据项29，那么首先会把磁盘块1由磁盘加载到内存，此时发生一次IO，在内存中用二分查找确定29在17和35之间，锁定磁盘块1的P2指针，内存时间因为非常短（相比磁盘的IO）可以忽略不计，通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存，发生第二次IO，29在26和30之间，锁定磁盘块3的P2指针，通过指针加载磁盘块8到内存，发生第三次IO，同时内存中做二分查找找到29，结束查询，总计三次IO。真实的情况是，3层的b+树可以表示上百万的数据，如果上百万的数据查找只需要三次IO，性能提高将是巨大的，如果没有索引，每个数据项都要发生一次IO，那么总共需要百万次的IO，显然成本非常非常高。&lt;/p&gt;&lt;h3 id="b-树性质" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 22px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;b+树性质&lt;/h3&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;1.通过上面的分析，我们知道IO次数取决于b+数的高度h，假设当前数据表的数据为N，每个磁盘块的数据项的数量是m，则有h=㏒(m+1)N，当数据量N一定的情况下，m越大，h越小；而m = 磁盘块的大小 / 数据项的大小，磁盘块的大小也就是一个数据页的大小，是固定的，如果数据项占的空间越小，数据项的数量越多，树的高度越低。这就是为什么每个数据项，即索引字段要尽量的小，比如int占4字节，要比bigint8字节少一半。这也是为什么b+树要求把真实的数据放到叶子节点而不是内层节点，一旦放到内层节点，磁盘块的数据项会大幅度下降，导致树增高。当数据项等于1时将会退化成线性表。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;2.当b+树的数据项是复合的数据结构，比如(name,age,sex)的时候，b+数是按照从左到右的顺序来建立搜索树的，比如当(张三,20,F)这样的数据来检索的时候，b+树会优先比较name来确定下一步的所搜方向，如果name相同再依次比较age和sex，最后得到检索的数据；但当(20,F)这样的没有name的数据来的时候，b+树就不知道下一步该查哪个节点，因为建立搜索树的时候name就是第一个比较因子，必须要先根据name来搜索才能知道下一步去哪里查询。比如当(张三,F)这样的数据来检索时，b+树可以用name来指定搜索方向，但下一个字段age的缺失，所以只能把名字等于张三的数据都找到，然后再匹配性别是F的数据了， 这个是非常重要的性质，即索引的最左匹配特性。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;关于MySQL索引原理是比较枯燥的东西，大家只需要有一个感性的认识，并不需要理解得非常透彻和深入。我们回头来看看一开始我们说的慢查询，了解完索引原理之后，大家是不是有什么想法呢？先总结一下索引的几大基本原则：&lt;/p&gt;&lt;h2 id="建索引的几大原则" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;建索引的几大原则&lt;/h2&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;1.最左前缀匹配原则，非常重要的原则，mysql会一直向右匹配直到遇到范围查询(&amp;gt;、&amp;lt;、between、like)就停止匹配，比如a = 1 and b = 2 and c &amp;gt; 3 and d = 4 如果建立(a,b,c,d)顺序的索引，d是用不到索引的，如果建立(a,b,d,c)的索引则都可以用到，a,b,d的顺序可以任意调整。 2.=和in可以乱序，比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序，mysql的查询优化器会帮你优化成索引可以识别的形式。 3.尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*)，表示字段不重复的比例，比例越大我们扫描的记录数越少，唯一键的区分度是1，而一些状态、性别字段可能在大数据面前区分度就是0，那可能有人会问，这个比例有什么经验值吗？使用场景不同，这个值也很难确定，一般需要join的字段我们都要求是0.1以上，即平均1条扫描10条记录。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;4.索引列不能参与计算，保持列“干净”，比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引，原因很简单，b+树中存的都是数据表中的字段值，但进行检索时，需要把所有元素都应用函数才能比较，显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;5.尽量的扩展索引，不要新建索引。比如表中已经有a的索引，现在要加(a,b)的索引，那么只需要修改原来的索引即可。&lt;/p&gt;&lt;h2 id="回到开始的慢查询" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;回到开始的慢查询&lt;/h2&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;根据最左匹配原则，最开始的sql语句的索引应该是status、operator_id、type、operate_time的联合索引；其中status、operator_id、type的顺序可以颠倒，所以我才会说，把这个表的所有相关查询都找到，会综合分析； 比如还有如下查询：&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt; * &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt; task &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;where&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;status&lt;/span&gt; = &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;type&lt;/span&gt; = &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;12&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;limit&lt;/span&gt; &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;10&lt;/span&gt;; &lt;/code&gt;&lt;/pre&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;count&lt;/span&gt;(*) &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt; task &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;where&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;status&lt;/span&gt; = &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0&lt;/span&gt; ; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;那么索引建立成(status,type,operator_id,operate_time)就是非常正确的，因为可以覆盖到所有情况。这个就是利用了索引的最左匹配的原则&lt;/p&gt;&lt;h2 id="查询优化神器-explain命令" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;查询优化神器 - explain命令&lt;/h2&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;关于explain命令相信大家并不陌生，具体用法和字段含义可以参考官网&lt;a href="http://dev.mysql.com/doc/refman/5.5/en/explain-output.html" style="text-decoration-line: underline; color: rgb(22, 185, 169); margin: 0px 4px;"&gt;explain-output&lt;span class="fa fa-link" aria-hidden="true" style="font-size: 10px; margin: 0px; padding-left: 2px; vertical-align: text-top; font-family: iconfont !important;"&gt;&lt;/span&gt;&lt;/a&gt;，这里需要强调rows是核心指标，绝大部分rows小的语句执行一定很快（有例外，下面会讲到）。所以优化语句基本上都是在优化rows。&lt;/p&gt;&lt;h2 id="慢查询优化基本步骤" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;慢查询优化基本步骤&lt;/h2&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;0.先运行看看是否真的很慢，注意设置SQL_NO_CACHE 1.where条件单表查，锁定最小返回记录表。这句话的意思是把查询语句的where都应用到表中返回的记录数最小的表开始查起，单表每个字段分别查询，看哪个字段的区分度最高 2.explain查看执行计划，是否与1预期一致（从锁定记录较少的表开始查询） 3.order by limit 形式的sql语句让排序的表优先查 4.了解业务方使用场景 5.加索引时参照建索引的几大原则 6.观察结果，不符合预期继续从0分析&lt;/p&gt;&lt;h2 id="几个慢查询案例" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 24px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;几个慢查询案例&lt;/h2&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;下面几个例子详细解释了如何分析和优化慢查询。&lt;/p&gt;&lt;h3 id="复杂语句写法" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 22px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;复杂语句写法&lt;/h3&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;很多情况下，我们写SQL只是为了实现功能，这只是第一步，不同的语句书写方式对于效率往往有本质的差别，这要求我们对mysql的执行计划和索引原则有非常清楚的认识，请看下面的语句：&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt;    &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;distinct&lt;/span&gt; cert.emp_id  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt;    cm_log cl  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt;    (       &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt;          emp.id &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;as&lt;/span&gt; emp_id,          emp_cert.id &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;as&lt;/span&gt; cert_id        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt;          employee emp        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;left&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt;          emp_certificate emp_cert              &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt; emp.id = emp_cert.emp_id        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;where&lt;/span&gt;          emp.is_deleted=&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0&lt;/span&gt;    ) cert        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt; (          cl.ref_table=&lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'Employee'&lt;/span&gt;           &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; cl.ref_oid= cert.emp_id       )        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;or&lt;/span&gt; (          cl.ref_table=&lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'EmpCertificate'&lt;/span&gt;           &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; cl.ref_oid= cert.cert_id       )  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;where&lt;/span&gt;    cl.last_upd_date &amp;gt;=&lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'2013-11-07 15:03:00'&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; cl.last_upd_date&amp;lt;=&lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'2013-11-08 16:00:00'&lt;/span&gt;; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;0.先运行一下，53条记录 1.87秒，又没有用聚合语句，比较慢&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;53 rows in &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;set&lt;/span&gt; (&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1.87&lt;/span&gt; sec) &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;1.explain&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;+&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+------------+-------+---------------------------------+-----------------------+---------+-------------------+-------+--------------------------------+&lt;/span&gt; | id | select_type | table      | type  | possible_keys                   | key                   | key_len | ref               | rows  | Extra                          | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+------------+-------+---------------------------------+-----------------------+---------+-------------------+-------+--------------------------------+&lt;/span&gt; |  1 | PRIMARY     | cl         | range | cm_log_cls_id,idx_last_upd_date | idx_last_upd_date     | 8       | NULL              |   379 | Using where; Using temporary   | |  1 | PRIMARY     | &amp;lt;derived2&amp;gt; | ALL   | NULL                            | NULL                  | NULL    | NULL              | 63727 | Using where; Using join buffer | |  2 | DERIVED     | emp        | ALL   | NULL                            | NULL                  | NULL    | NULL              | 13317 | Using where                    | |  2 | DERIVED     | emp_cert   | ref   | emp_certificate_empid           | emp_certificate_empid | 4       | meituanorg.emp.id |     1 | Using index                    | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+------------+-------+---------------------------------+-----------------------+---------+-------------------+-------+--------------------------------+&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;简述一下执行计划，首先mysql根据idx_last_upd_date索引扫描cm_log表获得379条记录；然后查&lt;derived2&gt;表扫描了63727条记录，&lt;derived2&gt;分为两部分，derived表示构造表，也就是不存在的表，可以简单理解成是一个语句形成的结果集，后面的数字表示语句的ID。derived2表示的是ID = 2的查询构造了虚拟表，并且返回了63727条记录。我们再来看看ID = 2的语句究竟做了写什么返回了这么大量的数据，首先全表扫描employee表13317条记录，然后根据索引emp_certificate_empid关联emp_certificate表，rows = 1表示，每个关联都只锁定了一条记录，效率比较高。获得&lt;derived2&gt;后，再和cm_log的379条记录根据规则关联。从执行过程上可以看出&lt;derived2&gt;返回了太多的数据，返回的数据绝大部分cm_log都用不到，因为cm_log只锁定了379条记录。&lt;/derived2&gt;&lt;/derived2&gt;&lt;/derived2&gt;&lt;/derived2&gt;&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;如何优化&lt;derived2&gt;呢？可以看到我们在运行完&lt;derived2&gt;后还是要和cm_log做join,那么我们能不能之前和cm_log做join呢？仔细分析语句不难发现，其基本思想是如果cm_log的ref_table是EmpCertificate就关联emp_certificate表，如果ref_table是Employee就关联employee表，我们完全可以拆成两部分，并用union连接起来，注意这里用union，而不用union all是因为原语句有“distinct”来得到唯一的记录，而union恰好具备了这种功能。如果原语句中没有distinct不需要去重，我们就可以直接使用union all了，因为使用union需要去重的动作，会影响SQL性能。&lt;/derived2&gt;&lt;/derived2&gt;&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;优化过的语句如下：&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt;    emp.id  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt;    cm_log cl  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt;    employee emp        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt; cl.ref_table = &lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'Employee'&lt;/span&gt;        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; cl.ref_oid = emp.id   &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;where&lt;/span&gt;    cl.last_upd_date &amp;gt;=&lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'2013-11-07 15:03:00'&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; cl.last_upd_date&amp;lt;=&lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'2013-11-08 16:00:00'&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; emp.is_deleted = &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0&lt;/span&gt;   &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;union&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt;    emp.id  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt;    cm_log cl  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt;    emp_certificate ec        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt; cl.ref_table = &lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'EmpCertificate'&lt;/span&gt;        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; cl.ref_oid = ec.id   &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt;    employee emp        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt; emp.id = ec.emp_id   &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;where&lt;/span&gt;    cl.last_upd_date &amp;gt;=&lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'2013-11-07 15:03:00'&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; cl.last_upd_date&amp;lt;=&lt;span class="hljs-string" style="color: rgb(165, 194, 97);"&gt;'2013-11-08 16:00:00'&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; emp.is_deleted = &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;4.不需要了解业务场景，只需要改造的语句和改造之前的语句保持结果一致&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;5.现有索引可以满足，不需要建索引&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;6.用改造后的语句实验一下，只需要10ms 降低了近200倍！&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;+&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+--------------+------------+--------+---------------------------------+-------------------+---------+-----------------------+------+-------------+&lt;/span&gt; | id | select_type  | table      | type   | possible_keys                   | key               | key_len | ref                   | rows | Extra       | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+--------------+------------+--------+---------------------------------+-------------------+---------+-----------------------+------+-------------+&lt;/span&gt; |  1 | PRIMARY      | cl         | range  | cm_log_cls_id,idx_last_upd_date | idx_last_upd_date | 8       | NULL                  |  379 | Using where | |  1 | PRIMARY      | emp        | eq_ref | PRIMARY                         | PRIMARY           | 4       | meituanorg.cl.ref_oid |    1 | Using where | |  2 | UNION        | cl         | range  | cm_log_cls_id,idx_last_upd_date | idx_last_upd_date | 8       | NULL                  |  379 | Using where | |  2 | UNION        | ec         | eq_ref | PRIMARY,emp_certificate_empid   | PRIMARY           | 4       | meituanorg.cl.ref_oid |    1 |             | |  2 | UNION        | emp        | eq_ref | PRIMARY                         | PRIMARY           | 4       | meituanorg.ec.emp_id  |    1 | Using where | | NULL | UNION RESULT | &amp;lt;union1,2&amp;gt; | ALL    | NULL                            | NULL              | NULL    | NULL                  | NULL |             | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+--------------+------------+--------+---------------------------------+-------------------+---------+-----------------------+------+-------------+&lt;/span&gt; 53 rows in &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;set&lt;/span&gt; (&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0.01&lt;/span&gt; sec) &lt;/code&gt;&lt;/pre&gt;&lt;h3 id="明确应用场景" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 22px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;明确应用场景&lt;/h3&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;举这个例子的目的在于颠覆我们对列的区分度的认知，一般上我们认为区分度越高的列，越容易锁定更少的记录，但在一些特殊的情况下，这种理论是有局限性的。&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt;    *  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt;    stage_poi sp  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;where&lt;/span&gt;    sp.accurate_result=&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1&lt;/span&gt;     &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; (       sp.sync_status=&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0&lt;/span&gt;        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;or&lt;/span&gt; sp.sync_status=&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;2&lt;/span&gt;        &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;or&lt;/span&gt; sp.sync_status=&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;4&lt;/span&gt;    ); &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;0.先看看运行多长时间,951条数据6.22秒，真的很慢。&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;951 rows in &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;set&lt;/span&gt; (&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;6.22&lt;/span&gt; sec) &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;1.先explain，rows达到了361万，type = ALL表明是全表扫描。&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;+&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+-------+------+---------------+------+---------+------+---------+-------------+&lt;/span&gt; | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra       | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+-------+------+---------------+------+---------+------+---------+-------------+&lt;/span&gt; |  1 | SIMPLE      | sp    | ALL  | NULL          | NULL | NULL    | NULL | 3613155 | Using where | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+-------+------+---------------+------+---------+------+---------+-------------+&lt;/span&gt; &lt;p&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;2.所有字段都应用查询返回记录数，因为是单表查询 0已经做过了951条。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;3.让explain的rows 尽量逼近951。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;看一下accurate_result = 1的记录数：&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;count&lt;/span&gt;(&lt;em&gt;),accurate_result &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt; stage_poi  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;group&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;by&lt;/span&gt; accurate_result; +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+-----------------+&lt;/span&gt; | count(&lt;/em&gt;) | accurate_result | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+-----------------+&lt;/span&gt; |     1023 |              -1 | |  2114655 |               0 | |   972815 |               1 | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+-----------------+&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;我们看到accurate_result这个字段的区分度非常低，整个表只有-1,0,1三个值，加上索引也无法锁定特别少量的数据。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;再看一下sync_status字段的情况：&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;count&lt;/span&gt;(&lt;em&gt;),sync_status &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt; stage_poi  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;group&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;by&lt;/span&gt; sync_status; +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+-------------+&lt;/span&gt; | count(&lt;/em&gt;) | sync_status | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+-------------+&lt;/span&gt; |     3080 |           0 | |  3085413 |           3 | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+-------------+&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;同样的区分度也很低，根据理论，也不适合建立索引。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;问题分析到这，好像得出了这个表无法优化的结论，两个列的区分度都很低，即便加上索引也只能适应这种情况，很难做普遍性的优化，比如当sync_status 0、3分布的很平均，那么锁定记录也是百万级别的。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;4.找业务方去沟通，看看使用场景。业务方是这么来使用这个SQL语句的，每隔五分钟会扫描符合条件的数据，处理完成后把sync_status这个字段变成1,五分钟符合条件的记录数并不会太多，1000个左右。了解了业务方的使用场景后，优化这个SQL就变得简单了，因为业务方保证了数据的不平衡，如果加上索引可以过滤掉绝大部分不需要的数据。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;5.根据建立索引规则，使用如下语句建立索引&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;alter&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;table&lt;/span&gt; stage_poi &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;add&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;index&lt;/span&gt; idx_acc_status(accurate_result,sync_status); &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;6.观察预期结果,发现只需要200ms，快了30多倍。&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;952 rows in &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;set&lt;/span&gt; (&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0.20&lt;/span&gt; sec) &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;我们再来回顾一下分析问题的过程，单表查询相对来说比较好优化，大部分时候只需要把where条件里面的字段依照规则加上索引就好，如果只是这种“无脑”优化的话，显然一些区分度非常低的列，不应该加索引的列也会被加上索引，这样会对插入、更新性能造成严重的影响，同时也有可能影响其它的查询语句。所以我们第4步调差SQL的使用场景非常关键，我们只有知道这个业务场景，才能更好地辅助我们更好的分析和优化查询语句。&lt;/p&gt;&lt;h3 id="无法优化的语句" style="font-family: &amp;quot;PingFang SC&amp;quot;, Verdana, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; line-height: 1.1; color: rgb(42, 41, 53); margin-top: 0.8em; margin-bottom: 1rem; font-size: 22px; padding: 0px; text-shadow: rgba(255, 255, 255, 0.75) 0px 1px 0px; background-color: rgb(253, 253, 253);"&gt;无法优化的语句&lt;/h3&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt; c.id, c.name, c.position, c.sex, c.phone, c.office_phone, c.feature_info, c.birthday, c.creator_id, c.is_keyperson, c.giveup_reason, c.status, c.data_source, from_unixtime(c.created_time) &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;as&lt;/span&gt; created_time, from_unixtime(c.last_modified) &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;as&lt;/span&gt; last_modified, c.last_modified_user_id&lt;br /&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt; contact c&lt;br /&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt; contact_branch cb &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt;  c.id = cb.contact_id&lt;br /&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt; branch_user bu &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt;  cb.branch_id = bu.branch_id &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; bu.status &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;in&lt;/span&gt; ( &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1&lt;/span&gt;, &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;2&lt;/span&gt;)&lt;br /&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt; org_emp_info oei &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt;  oei.data_id = bu.user_id &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; oei.node_left &amp;gt;= &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;2875&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; oei.node_right &amp;lt;= &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;10802&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; oei.org_category = - &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1&lt;/span&gt;&lt;br /&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;order&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;by&lt;/span&gt; c.created_time &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;desc&lt;/span&gt;  &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;limit&lt;/span&gt; &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;0&lt;/span&gt; , &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;10&lt;/span&gt;; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;还是几个步骤。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;0.先看语句运行多长时间，10条记录用了13秒，已经不可忍受。&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;10 rows in &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;set&lt;/span&gt; (&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;13.06&lt;/span&gt; sec) &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;1.explain&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;+&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+-------+--------+-------------------------------------+-------------------------+---------+--------------------------+------+----------------------------------------------+&lt;/span&gt; | id | select_type | table | type   | possible_keys                       | key                     | key_len | ref                      | rows | Extra                                        | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+-------+--------+-------------------------------------+-------------------------+---------+--------------------------+------+----------------------------------------------+&lt;/span&gt; |  1 | SIMPLE      | oei   | ref    | idx_category_left_right,idx_data_id | idx_category_left_right | 5       | const                    | 8849 | Using where; Using temporary; Using filesort | |  1 | SIMPLE      | bu    | ref    | PRIMARY,idx_userid_status           | idx_userid_status       | 4       | meituancrm.oei.data_id   |   76 | Using where; Using index                     | |  1 | SIMPLE      | cb    | ref    | idx_branch_id,idx_contact_branch_id | idx_branch_id           | 4       | meituancrm.bu.branch_id  |    1 |                                              | |  1 | SIMPLE      | c     | eq_ref | PRIMARY                             | PRIMARY                 | 108     | meituancrm.cb.contact_id |    1 |                                              | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----+-------------+-------+--------+-------------------------------------+-------------------------+---------+--------------------------+------+----------------------------------------------+&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;从执行计划上看，mysql先查org_emp_info表扫描8849记录，再用索引idx_userid_status关联branch_user表，再用索引idx_branch_id关联contact_branch表，最后主键关联contact表。&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;rows返回的都非常少，看不到有什么异常情况。我们在看一下语句，发现后面有order by + limit组合，会不会是排序量太大搞的？于是我们简化SQL，去掉后面的order by 和 limit，看看到底用了多少记录来排序。&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="language-sql hljs" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;"&gt;&lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;select&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;count&lt;/span&gt;(&lt;em&gt;) &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;from&lt;/span&gt; contact c&lt;br /&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt; contact_branch cb &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt;  c.id = cb.contact_id&lt;br /&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt; branch_user bu &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt;  cb.branch_id = bu.branch_id &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; bu.status &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;in&lt;/span&gt; ( &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1&lt;/span&gt;, &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;2&lt;/span&gt;)&lt;br /&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;inner&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;join&lt;/span&gt; org_emp_info oei &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;on&lt;/span&gt;  oei.data_id = bu.user_id &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; oei.node_left &amp;gt;= &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;2875&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; oei.node_right &amp;lt;= &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;10802&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;and&lt;/span&gt; oei.org_category = - &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1&lt;/span&gt;&lt;br /&gt; +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+&lt;/span&gt; | &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;count&lt;/span&gt;(&lt;/em&gt;) | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+&lt;/span&gt; |   &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;778878&lt;/span&gt; | +&lt;span class="hljs-comment" style="color: rgb(188, 148, 88); font-style: italic;"&gt;----------+&lt;/span&gt; &lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;row&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;in&lt;/span&gt; &lt;span class="hljs-keyword" style="font-weight: 700; color: rgb(194, 98, 48);"&gt;set&lt;/span&gt; (&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;5.19&lt;/span&gt; sec) &lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;发现排序之前居然锁定了778878条记录，如果针对70万的结果集排序，将是灾难性的，怪不得这么慢，那我们能不能换个思路，先根据contact的created_time排序，再来join会不会比较快呢？&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;于是改造成下面的语句，也可以用straight_join来优化：&lt;/p&gt;&lt;p style="margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Lantinghei SC&amp;quot;, &amp;quot;Microsoft Yahei&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft Sans Serif&amp;quot;, &amp;quot;WenQuanYi Micro Hei&amp;quot;, sans-serif; background-color: rgb(253, 253, 253);"&gt;select c.id, c.name, c.position, c.sex, c.phone, c.office_phone, c.feature_info, c.birthday, c.creator_id, c.is_keyperson, c.giveup_reason, c.status, c.data_source, from_unixtime(c.created_time) as created_time, from_unixtime(c.last_modified) as last_modified, c.last_modified_user_id&lt;br&gt;from contact c&lt;br&gt;where exists ( select 1 from contact_branch cb&lt;br&gt;inner join branch_user bu&lt;br&gt;on cb.branch_id = bu.branch_id&lt;br&gt;and bu.status in ( 1, 2)&lt;br&gt;inner join org_emp_info oei&lt;br&gt;on oei.data_id = bu.user_id&lt;br&gt;and oei.node_left &amp;gt;= 2875&lt;br&gt;and oei.node_right &amp;lt;= 10802&lt;br&gt;and oei.org_category = - 1&lt;br&gt;where c.id = cb.contact_id&lt;br&gt;)&lt;br&gt;order by c.created_time desc limit 0 , 10;&lt;/p&gt;&lt;pre style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);"&gt;&lt;code class="hljs kotlin" style="font-family: Courier, &amp;quot;Courier New&amp;quot;, monospace; color: rgb(230, 225, 220); background: rgb(35, 35, 35); padding: 0.5em; margin: 0px; display: block; overflow-x: auto;"&gt;验证一下效果 预计在&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;1&lt;/span&gt;ms内，提升了&lt;span class="hljs-number" style="color: rgb(165, 194, 97);"&gt;13000&lt;/span&gt;多倍！&lt;/p&gt; &lt;pre&gt;&lt;code class="language-sql"&gt;&amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;10&amp;lt;/span&amp;gt; rows &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;in&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;set&amp;lt;/span&amp;gt; (&amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;0.00&amp;lt;/span&amp;gt; sec) &amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;p style=&amp;quot;margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;amp;quot;PingFang SC&amp;amp;quot;, &amp;amp;quot;Lantinghei SC&amp;amp;quot;, &amp;amp;quot;Microsoft Yahei&amp;amp;quot;, &amp;amp;quot;Hiragino Sans GB&amp;amp;quot;, &amp;amp;quot;Microsoft Sans Serif&amp;amp;quot;, &amp;amp;quot;WenQuanYi Micro Hei&amp;amp;quot;, sans-serif; background-color: rgb(253, 253, 253);&amp;quot;&amp;gt;本以为至此大工告成，但我们在前面的分析中漏了一个细节，先排序再join和先join再排序理论上开销是一样的，为何提升这么多是因为有一个limit！大致执行过程是：mysql先按索引排序得到前10条记录，然后再去join过滤，当发现不够10条的时候，再次去10条，再次join，这显然在内层join过滤的数据非常多的时候，将是灾难的，极端情况，内层一条数据都找不到，mysql还傻乎乎的每次取10条，几乎遍历了这个数据表！&amp;lt;/p&amp;gt;&amp;lt;p style=&amp;quot;margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;amp;quot;PingFang SC&amp;amp;quot;, &amp;amp;quot;Lantinghei SC&amp;amp;quot;, &amp;amp;quot;Microsoft Yahei&amp;amp;quot;, &amp;amp;quot;Hiragino Sans GB&amp;amp;quot;, &amp;amp;quot;Microsoft Sans Serif&amp;amp;quot;, &amp;amp;quot;WenQuanYi Micro Hei&amp;amp;quot;, sans-serif; background-color: rgb(253, 253, 253);&amp;quot;&amp;gt;用不同参数的SQL试验下：&amp;lt;/p&amp;gt;&amp;lt;pre style=&amp;quot;font-family: Courier, &amp;amp;quot;Courier New&amp;amp;quot;, monospace; font-size: 9px; padding: 0px; margin-bottom: 1rem; line-height: 1.42857; background: rgb(238, 238, 238); border-color: rgb(238, 238, 238);&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-sql hljs&amp;quot; style=&amp;quot;font-family: Courier, &amp;amp;quot;Courier New&amp;amp;quot;, monospace; color: rgb(230, 225, 220); background-image: initial; background-color: rgb(35, 35, 35); padding: 0.5em; margin: 0px; white-space: pre-wrap; display: block; overflow-x: auto;&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;select&amp;lt;/span&amp;gt;    sql_no_cache   c.id,    c.name,    c.position,    c.sex,    c.phone,    c.office_phone,    c.feature_info,    c.birthday,    c.creator_id,    c.is_keyperson,    c.giveup_reason,    c.status,    c.data_source,    from_unixtime(c.created_time) &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;as&amp;lt;/span&amp;gt; created_time,    from_unixtime(c.last_modified) &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;as&amp;lt;/span&amp;gt; last_modified,    c.last_modified_user_id     &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;from&amp;lt;/span&amp;gt;    contact c    &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;where&amp;lt;/span&amp;gt;    &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;exists&amp;lt;/span&amp;gt; (       &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;select&amp;lt;/span&amp;gt;          &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;1&amp;lt;/span&amp;gt;               &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;from&amp;lt;/span&amp;gt;          contact_branch cb                &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;inner&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;join&amp;lt;/span&amp;gt;          branch_user bu                                  &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;on&amp;lt;/span&amp;gt;  cb.branch_id = bu.branch_id                                  &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;and&amp;lt;/span&amp;gt; bu.status &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;in&amp;lt;/span&amp;gt; (                &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;1&amp;lt;/span&amp;gt;,             &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;2&amp;lt;/span&amp;gt;)                          &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;inner&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;join&amp;lt;/span&amp;gt;             org_emp_info oei                                           &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;on&amp;lt;/span&amp;gt;  oei.data_id = bu.user_id                                           &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;and&amp;lt;/span&amp;gt; oei.node_left &amp;amp;gt;= &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;2875&amp;lt;/span&amp;gt;                                           &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;and&amp;lt;/span&amp;gt; oei.node_right &amp;amp;lt;= &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;2875&amp;lt;/span&amp;gt;                                           &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;and&amp;lt;/span&amp;gt; oei.org_category = - &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;1&amp;lt;/span&amp;gt;                          &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;where&amp;lt;/span&amp;gt;             c.id = cb.contact_id                  )            &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;order&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;by&amp;lt;/span&amp;gt;       c.created_time &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;desc&amp;lt;/span&amp;gt;  &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;limit&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt; ,       &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;10&amp;lt;/span&amp;gt;; Empty &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;set&amp;lt;/span&amp;gt; (&amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;2&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hljs-keyword&amp;quot; style=&amp;quot;font-weight: 700; color: rgb(194, 98, 48);&amp;quot;&amp;gt;min&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hljs-number&amp;quot; style=&amp;quot;color: rgb(165, 194, 97);&amp;quot;&amp;gt;18.99&amp;lt;/span&amp;gt; sec) &amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;p style=&amp;quot;margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;amp;quot;PingFang SC&amp;amp;quot;, &amp;amp;quot;Lantinghei SC&amp;amp;quot;, &amp;amp;quot;Microsoft Yahei&amp;amp;quot;, &amp;amp;quot;Hiragino Sans GB&amp;amp;quot;, &amp;amp;quot;Microsoft Sans Serif&amp;amp;quot;, &amp;amp;quot;WenQuanYi Micro Hei&amp;amp;quot;, sans-serif; background-color: rgb(253, 253, 253);&amp;quot;&amp;gt;2 min 18.99 sec！比之前的情况还糟糕很多。由于mysql的nested loop机制，遇到这种情况，基本是无法优化的。这条语句最终也只能交给应用系统去优化自己的逻辑了。 通过这个例子我们可以看到，并不是所有语句都能优化，而往往我们优化时，由于SQL用例回归时落掉一些极端情况，会造成比原来还严重的后果。所以，第一：不要指望所有语句都能通过SQL优化，第二：不要过于自信，只针对具体case来优化，而忽略了更复杂的情况。&amp;lt;/p&amp;gt;&amp;lt;p style=&amp;quot;margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;amp;quot;PingFang SC&amp;amp;quot;, &amp;amp;quot;Lantinghei SC&amp;amp;quot;, &amp;amp;quot;Microsoft Yahei&amp;amp;quot;, &amp;amp;quot;Hiragino Sans GB&amp;amp;quot;, &amp;amp;quot;Microsoft Sans Serif&amp;amp;quot;, &amp;amp;quot;WenQuanYi Micro Hei&amp;amp;quot;, sans-serif; background-color: rgb(253, 253, 253);&amp;quot;&amp;gt;慢查询的案例就分析到这儿，以上只是一些比较典型的案例。我们在优化过程中遇到过超过1000行，涉及到16个表join的“垃圾SQL”，也遇到过线上线下数据库差异导致应用直接被慢查询拖死，也遇到过varchar等值比较没有写单引号，还遇到过笛卡尔积查询直接把从库搞死。再多的案例其实也只是一些经验的积累，如果我们熟悉查询优化器、索引的内部原理，那么分析这些案例就变得特别简单了。&amp;lt;/p&amp;gt;&amp;lt;p style=&amp;quot;margin-top: 0px; margin-bottom: 1rem; padding: 0px; font-size: 1.5rem; line-height: 1.75; color: rgb(51, 51, 51); font-family: &amp;amp;quot;PingFang SC&amp;amp;quot;, &amp;amp;quot;Lantinghei SC&amp;amp;quot;, &amp;amp;quot;Microsoft Yahei&amp;amp;quot;, &amp;amp;quot;Hiragino Sans GB&amp;amp;quot;, &amp;amp;quot;Microsoft Sans Serif&amp;amp;quot;, &amp;amp;quot;WenQuanYi Micro Hei&amp;amp;quot;, sans-serif; background-color: rgb(253, 253, 253);&amp;quot;&amp;gt;本文以一个慢查询案例引入了MySQL索引原理、优化慢查询的一些方法论;并针对遇到的典型案例做了详细的分析。其实做了这么长时间的语句优化后才发现，任何数据库层面的优化都抵不上应用系统的优化，同样是MySQL，可以用来支撑Google/FaceBook/Taobao应用，但可能连你的个人网站都撑不住。套用最近比较流行的话：“查询容易，优化不易，且写且珍惜！”&amp;lt;/p&amp;gt; &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Tue, 12 Feb 2019 08:25:00 GMT</pubDate>
    </item>
    <item>
      <title>设计模式学习总结</title>
      <link>https://cliveyuan.cn/article/14</link>
      <content:encoded>&lt;p&gt;&lt;br&gt;&lt;table class="table table-bordered"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;设计模式&lt;br&gt;&lt;/td&gt;&lt;td&gt;特点&lt;br&gt;&lt;/td&gt;&lt;td&gt;总结&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;代理模式&lt;br&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;1. 两个参与角色：代理人、被代理人&lt;/p&gt;&lt;p&gt;2.对于代理人来说这件事一定要做，但是自己又不想做或者没时间做，找代理&lt;/p&gt;&lt;p&gt;3.代理人必须获取被代理人的个人资料（持有被代理人的引用）&lt;/p&gt;&lt;/td&gt;&lt;td&gt;办事要求人，所以找代理&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;br&gt;&lt;/td&gt;&lt;td&gt;&lt;br&gt;&lt;/td&gt;&lt;td&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;/table&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 23 Jan 2019 05:26:00 GMT</pubDate>
    </item>
    <item>
      <title>动态代理</title>
      <link>https://cliveyuan.cn/article/13</link>
      <content:encoded>&lt;h1&gt;jdk动态代理&lt;/h1&gt; &lt;p&gt;针对接口进行代理，代理者实现&lt;code&gt;InvokeHandler&lt;/code&gt;&lt;/p&gt; &lt;h1&gt;cglib动态代理&lt;/h1&gt; &lt;p&gt;针对类进行代理，代理者实现&lt;code&gt;MethodIntecptor&lt;/code&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Tue, 22 Jan 2019 16:37:00 GMT</pubDate>
    </item>
    <item>
      <title>spring学习总结</title>
      <link>https://cliveyuan.cn/article/12</link>
      <content:encoded>&lt;h1&gt;spring是什么&lt;/h1&gt; &lt;p&gt;spring是一个简化企业应用开发复杂性的轻量级开源框架&lt;/p&gt; &lt;h1&gt;spring优点&lt;/h1&gt; &lt;p&gt;方便解耦，简化开发 支持AOP编程 易于集成&lt;/p&gt; &lt;h1&gt;spring原理&lt;/h1&gt; &lt;p&gt;IoC/DI: java反射机制 AOP：java动态代理、cglib代理&lt;/p&gt; &lt;h1&gt;spring 思想&lt;/h1&gt; &lt;p&gt;AOP: 解耦，专人做专事 BOP：面向Bean编程，一切从Bean开始 OOP：封装、继承、多态 IOC：控制权反转 DI/DL：先理清关系再赋值&lt;/p&gt;</content:encoded>
      <pubDate>Tue, 22 Jan 2019 15:41:00 GMT</pubDate>
    </item>
    <item>
      <title>Interface与abstract类的区别</title>
      <link>https://cliveyuan.cn/article/11</link>
      <content:encoded>&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;font color="#df3434" face="Microsoft YaHei, SF Pro Display, Roboto, Noto, Arial, PingFang SC, sans-serif"&gt;&lt;span style="outline-style: initial; cursor: pointer;"&gt;&lt;b&gt;Java&lt;/b&gt;&lt;/span&gt;&lt;/font&gt;中，抽象类和接口有相似的地方。下面我们就来细说说接口和抽象类的异同。&lt;/p&gt;&lt;h2 id="首先是相同的地方" style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 8px; margin-bottom: 16px; font-size: 24px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 32px; overflow-wrap: break-word;"&gt;&lt;a name="t0" style="outline-style: initial; outline-width: 0px; color: rgb(78, 161, 219); cursor: pointer; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;&lt;/a&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;相同之处：&lt;/span&gt;&lt;/h2&gt; &lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;1. 接口和抽象类都能定义方法和属性。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;2. 接口和抽象类都是看作是一种特殊的类。大部分的时候，定义的方法要子类来实现&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;3. 抽象类和接口都可以不含有抽象方法。接口没有方法就可以作为一个标志。比如可序列化的接口Serializable，没有方法的接口称为空接口。没有抽象方法的抽象类，小编不知道有什么作用，总之是可以通过编译的。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;4. 抽象类和接口都不能创建对象。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;5. 抽象类和接口都能利用多态性原理来使用抽象类引用指向子类对象。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;6. 继承和实现接口或抽象类的子类必须实现接口或抽象类的所有的方法，抽象类若有没有实现的方法就继续作为抽象类，要加abstract修饰。若接口的子类没有实现的方法，也要变为抽象类。&lt;/span&gt;&lt;/p&gt;&lt;h2 id="下面是接口和抽象类的不同点" style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 8px; margin-bottom: 16px; font-size: 24px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 32px; overflow-wrap: break-word;"&gt;&lt;a name="t1" style="outline-style: initial; outline-width: 0px; color: rgb(78, 161, 219); cursor: pointer; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;&lt;/a&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;不同之处：&lt;/span&gt;&lt;/h2&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;1. 接口能够多实现，而抽象类只能单独被继承，其本质就是，一个类能继承多个接口，而只能继承一个抽象类。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;2. 方法上，抽象类的方法可以用abstract 和public或者protect修饰。而接口默认为public abttact 修饰。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;3. 抽象类的方法可以有需要子类实现的抽象方法，也可以有具体的方法。而接口在老版本的jdk中，只能有抽象方法，但是Java8版本的接口中，接口可以带有默认方法。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;4. 属性上，抽象类可以用各种各样的修饰符修饰。而接口的属性是默认的public static final&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;5. 抽象类中可以含有静态代码块和静态方法，而接口不能含有静态方法和静态代码块。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;6. 抽象类可以含有构造方法，接口不能含有构造方法。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;7. 设计层面上，抽象类表示的是子类“是不是”属于某一类的子类，接口则表示“有没有”特性“能不能”做这种事。如飞机和鸟都能飞，但是他们在设计上实现一个Fly接口，实现fly()方法。远比两个类继承飞行物抽象类好得多。因为，飞机和鸟有太多的属性不一样。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;8. 设计层面上，另外一点，抽象类可以是一个模板，因为可以自己带集体方法，所以要加一个实现类都能有的方法，直接在抽象类中写出并实现就好，接口在以前的版本则不行。新版本Java8才有默认方法。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;9. 既然说到&lt;font color="#df3434"&gt;&lt;span style="outline-style: initial; cursor: pointer;"&gt;Java&amp;nbsp;&lt;/span&gt;&lt;/font&gt;8 那么就来说明，Java8中的接口中的默认方法是可以被多重继承的。而抽象类不行。&lt;/span&gt;&lt;/p&gt;&lt;p style="outline-style: initial; outline-width: 0px; padding: 0px; margin-top: 0px; margin-bottom: 16px; font-family: &amp;quot;microsoft yahei&amp;quot;; color: rgb(51, 51, 51); line-height: 26px; overflow-x: auto; overflow-wrap: break-word;"&gt;&lt;span style="outline-style: initial; outline-width: 0px; font-family: &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, Roboto, Noto, Arial, &amp;quot;PingFang SC&amp;quot;, sans-serif; overflow-wrap: break-word;"&gt;10. 另外，接口只能继承接口。而抽象类可以继承普通的类，也能继承接口和抽象类。&lt;/span&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Mon, 07 Jan 2019 02:45:00 GMT</pubDate>
    </item>
    <item>
      <title>Java 配置环境变量</title>
      <link>https://cliveyuan.cn/article/8</link>
      <content:encoded>&lt;p&gt;&lt;strong style="margin: 0px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;br&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong style="margin: 0px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;(1)新建-&amp;gt;变量名"&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;JAVA_HOME&lt;/span&gt;"，变量值"&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;C:\Java\${jdk_path}&lt;/span&gt;"（即JDK的安装路径）&amp;nbsp;&lt;br style="margin: 0px; padding: 0px;"&gt;(2)编辑-&amp;gt;变量名"&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;Path&lt;/span&gt;"，在原变量值的最后面加上“&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;;&lt;/span&gt;&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin&lt;/span&gt;”&amp;nbsp;&lt;br style="margin: 0px; padding: 0px;"&gt;(3)新建-&amp;gt;变量名“&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;CLASSPATH&lt;/span&gt;”,变量值“&lt;span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);"&gt;.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar&lt;/span&gt;”&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong style="margin: 0px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif;"&gt;&lt;br&gt;&lt;/strong&gt;&lt;br&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Thu, 03 Jan 2019 14:35:00 GMT</pubDate>
    </item>
    <item>
      <title>MyBatis使用中遇到过的坎</title>
      <link>https://cliveyuan.cn/article/7</link>
      <content:encoded>&lt;ul&gt; &lt;li&gt;使用枚举进行if判断时不能直接使用枚举本身,而是要用xx.name()来获取枚举本身字符串;&lt;/li&gt; &lt;li&gt;使用if判断的并且和或要小写and,or (大写的不能被识别)&lt;/li&gt; &lt;/ul&gt;</content:encoded>
      <pubDate>Thu, 27 Dec 2018 06:11:00 GMT</pubDate>
    </item>
    <item>
      <title>Mac下移动硬盘的使用</title>
      <link>https://cliveyuan.cn/article/5</link>
      <content:encoded>&lt;p&gt;转自:&lt;a href="https://blog.csdn.net/u014443884/article/details/78687490" target="_blank"&gt;https://blog.csdn.net/u014443884/article/details/78687490&lt;/a&gt;&lt;/p&gt; &lt;hr /&gt; &lt;blockquote&gt; &lt;p&gt;ntfs的移动硬盘默认可以识别但是以only read的方式挂载的，需要读写的时候肯能无法使用 mac自带的mount_ntfs就可以挂载移动硬盘，默认挂载的时候ntfs的硬盘是只读的，所以这个时候需要先umount掉，然后再使用mount_ntfs命令以读写的方式挂载&lt;/p&gt; &lt;/blockquote&gt; &lt;hr /&gt; &lt;p&gt;1.首先查看本地已经挂载的ntfs硬盘：&lt;/p&gt; &lt;pre&gt;&lt;code&gt;mount | grep ntfs  &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;结果如下：&lt;/p&gt; &lt;pre&gt;&lt;code&gt;clive@cliveyuans-MacBook-Pro:~$ mount | grep ntfs  /dev/disk0s3 on /Volumes/BOOTCAMP (ntfs, local, read-only, noowners) /dev/disk3s1 on /Volumes/系统保留 (ntfs, local, nodev, nosuid, read-only, noowners) /dev/disk3s2 on /Volumes/clive-2 (ntfs, local, nodev, nosuid, read-only, noowners) &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;2.然后卸载该硬盘：&lt;/p&gt; &lt;pre&gt;&lt;code&gt;umount /dev/disk3s2 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;3.本地创建一个挂载目录，然后使用mount_ntfs再次挂载：&lt;/p&gt; &lt;pre&gt;&lt;code&gt;mkdir mnt mount_ntfs -o rw,nobrowse /dev/disk3s2  mnt &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;strong&gt;如果上述方法没用, 那么可以下载这个软件试试  &lt;a href="http://www.ntfsformac.cn/xiazai.html" target="_blank"&gt;NTFS For Mac&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 19 Dec 2018 13:29:00 GMT</pubDate>
    </item>
    <item>
      <title>分布式锁的几种实现方式</title>
      <link>https://cliveyuan.cn/article/4</link>
      <content:encoded>&lt;p&gt;转自:&lt;br /&gt; &lt;a href="http://www.cnblogs.com/austinspark-jessylu/p/8043726.html" target="_blank"&gt;http://www.cnblogs.com/austinspark-jessylu/p/8043726.html&lt;/a&gt;&lt;a href="http://www.cnblogs.com/austinspark-jessylu/p/8043726.html" target="_blank"&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded>
      <pubDate>Wed, 05 Dec 2018 03:29:00 GMT</pubDate>
    </item>
    <item>
      <title>第一篇文章</title>
      <link>https://cliveyuan.cn/article/2</link>
      <content:encoded>&lt;h2&gt;Hello  World.&lt;/h2&gt; &lt;blockquote&gt; &lt;p&gt;第一篇文章总得写点儿什么?...&lt;/p&gt; &lt;/blockquote&gt; &lt;hr /&gt; &lt;pre&gt;&lt;code class="language-java"&gt;public static void main(String[] args){     System.out.println(\&amp;quot;Hello Tale.\&amp;quot;); } &lt;/code&gt;&lt;/pre&gt;</content:encoded>
      <pubDate>Thu, 23 Feb 2017 14:46:24 GMT</pubDate>
    </item>
  </channel>
</rss>

