<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>执子之手</title>
    <link>https://blog.orchidflower.cn/</link>
    <description>Recent content on 执子之手</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-CN</language>
    <lastBuildDate>Fri, 10 May 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.orchidflower.cn/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>在Jenkins Maven Plugin中指定不同的JDK版本</title>
      <link>https://blog.orchidflower.cn/2024/05/10/Using-diffrent-JDK-version-in-Jenkins-maven-plugin/</link>
      <pubDate>Fri, 10 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2024/05/10/Using-diffrent-JDK-version-in-Jenkins-maven-plugin/</guid>
      <description>&lt;h1 id=&#34;1-问题&#34;&gt;1. 问题&lt;/h1&gt;
&lt;p&gt;新版本的&lt;code&gt;Jenkins&lt;/code&gt;中的&lt;code&gt;Maven&lt;/code&gt;插件对&lt;code&gt;JDK&lt;/code&gt;版本的要求提高了，如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Jenkins &amp;gt;= 1.520 requires Java 6 thus Maven jobs must be launched with Java &amp;gt;= 6.&lt;/li&gt;
&lt;li&gt;Jenkins &amp;gt;= 1.612 requires Java 7 thus Maven jobs must be launched with Java &amp;gt;= 7.&lt;/li&gt;
&lt;li&gt;Jenkins &amp;gt;= 2.54 requires Java 8 thus Maven jobs must be launched with Java &amp;gt;= 8.&lt;/li&gt;
&lt;li&gt;Jenkins &amp;gt;= 2.357 requires Java 11 thus Maven jobs must be launched with Java &amp;gt;= 11.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;但是有些项目必须要求&lt;code&gt;JDK 1.8&lt;/code&gt;编译才能够成功（例如有些第三方依赖库只支持&lt;code&gt;JDK8&lt;/code&gt;）。正常情况下在命令行下使用&lt;code&gt;Maven&lt;/code&gt;编译可以通过&lt;code&gt;export JAVA_HOME&lt;/code&gt;的方式来解决。但是在&lt;code&gt;Jenkins Maven Plugin&lt;/code&gt;中没有办法指定&lt;code&gt;JDK&lt;/code&gt;版本。如果强制指定在&lt;code&gt;Jenkins&lt;/code&gt;任务中（&lt;code&gt;Maven&lt;/code&gt;类型项目）指定&lt;code&gt;JDK8&lt;/code&gt;，则编译的时候会报如下信息，然后强制选择新版本的&lt;code&gt;JDK&lt;/code&gt;：&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>无损扩容Linux磁盘分区容量</title>
      <link>https://blog.orchidflower.cn/2022/12/01/Expand-Linux-Partition-without-Data-Loss/</link>
      <pubDate>Thu, 01 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2022/12/01/Expand-Linux-Partition-without-Data-Loss/</guid>
      <description>&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;公司有台虚拟机，当初安装的时候给的磁盘容量偏小（80G），最近频繁报磁盘空间不足。因为上面跑了比较重要的服务，没有办法重装，只好考虑如何扩容。物理机上面的空闲空间还比较多，通过虚拟机管理软件修改了虚拟机的配置，很容易的把虚拟磁盘容量调大了，调整到了215G。&lt;/p&gt;
&lt;p&gt;虚拟磁盘调整后，就需要在&lt;code&gt;Linux&lt;/code&gt;系统中进行扩容操作。扩容主要有两步工作要做：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;调整分区大小：将新增的空间添加到分区内容；需要用到工具&lt;code&gt;parted&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;调整文件系统大小：分区容量扩大后，使用&lt;code&gt;resize2fs&lt;/code&gt;命令将文件系统扩容到整个磁盘容量。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;备注&lt;/strong&gt;：当时分区的时候没有选择&lt;code&gt;LVM&lt;/code&gt;管理，如果使用&lt;code&gt;LVM&lt;/code&gt;管理可以通过&lt;code&gt;lvextend&lt;/code&gt;命令进行分区的扩容，具体方法参考附录中的链接。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>奇怪现象：两个Consumer消费同一个分区（Partition）</title>
      <link>https://blog.orchidflower.cn/2022/05/27/Two-Kafka-Consumer-consume-one-partition/</link>
      <pubDate>Fri, 27 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2022/05/27/Two-Kafka-Consumer-consume-one-partition/</guid>
      <description>&lt;p&gt;最近生产上碰到一个奇怪的问题，现场人员反馈&lt;code&gt;Kafka&lt;/code&gt;工作不正常。经过开发人员检查，发现一个奇怪的现象：线上两台服务器竟然在同时消费一个&lt;code&gt;Kafka&lt;/code&gt; &lt;code&gt;Topic&lt;/code&gt;中的一个分区（&lt;code&gt;Partition&lt;/code&gt;）。&lt;/p&gt;
&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;我们的程序要实现的功能是这样的：系统会定时扫描库存表，根据库存情况决定是否要执行出库操作。之前是采用定时任务处理，执行策略是1分钟一次，为了防止多台服务器并发执行，使用&lt;code&gt;Quartz&lt;/code&gt;集群模式确保定时任务只在一台服务器上执行。最近客户提出需求，某些时候客户希望响应更及时一些，譬如某项请求到达的时候，就要立即检查库存并决定是否需要出库。因此，开发人员对系统进行了调整，改为使用&lt;code&gt;Kafka&lt;/code&gt; &lt;code&gt;Consumer&lt;/code&gt;来触发扫描库存动作；定时任务和接口处同时负责发送触发库存扫描的消息。&lt;/p&gt;
&lt;p&gt;相关的代码如下：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Consumer&lt;/code&gt;用来处理扫描库存的功能：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#00a8c8&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;LibraryOutboundTriggerConsumer&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;OutboundService&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;outboundService&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;BoxInfoService&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;boxInfoService&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75af00&#34;&gt;@KafkaListener&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;topics&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;${fwm.core.topic.library-outbound-trigger}&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;consume&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;ConsumerRecord&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;record&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#111&#34;&gt;log&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;info&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;\n\n&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#111&#34;&gt;log&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;info&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;=====================开始执行出库扫描=====================&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#00a8c8&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;boxInfoService&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;hasBoxUpdateTask&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;())&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;            &lt;span style=&#34;color:#111&#34;&gt;log&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;info&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;=====================存在料箱更新任务，执行出库扫描结束=====================&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;            &lt;span style=&#34;color:#00a8c8&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#111&#34;&gt;Stopwatch&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;stopwatch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Stopwatch&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;createStarted&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#00a8c8&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15&lt;/span&gt;&lt;span&gt;            &lt;span style=&#34;color:#111&#34;&gt;boxInfoService&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;startOutboundTask&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;90&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16&lt;/span&gt;&lt;span&gt;            &lt;span style=&#34;color:#111&#34;&gt;outboundService&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;outboundTaskScan&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;finally&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18&lt;/span&gt;&lt;span&gt;            &lt;span style=&#34;color:#111&#34;&gt;boxInfoService&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;stopOutboundTask&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#111&#34;&gt;log&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;info&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;=====================执行出库扫描结束,总耗时{}ms=====================&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;stopwatch&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;elapsed&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;TimeUnit&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;MILLISECONDS&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Flex布局添加滚动条需要注意的规则</title>
      <link>https://blog.orchidflower.cn/2022/03/02/Adding-Scrollbar-In-Flex-Layout/</link>
      <pubDate>Wed, 02 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2022/03/02/Adding-Scrollbar-In-Flex-Layout/</guid>
      <description>&lt;p&gt;好久不写前端代码了，有些生疏了。最近用Electron写了一个客户端程序，碰到了Flex布局添加滚动条的问题，耗费了不少时间，所以总结一下要点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;根据滚动条的方向，确定好父元素的&lt;code&gt;flex-flow&lt;/code&gt;方向：&lt;/strong&gt; 如果要设置水平滚动条，那么父元素的&lt;code&gt;flex-flow&lt;/code&gt;要设置为&lt;code&gt;row&lt;/code&gt;；如果要设置纵向滚动条，那么父元素的&lt;code&gt;flex-flow&lt;/code&gt;要设置为&lt;code&gt;column&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;元素本身&lt;code&gt;flex&lt;/code&gt;设置为1；&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;滚动方向的大小（宽度或者高度）设置为0&lt;/strong&gt;，非滚动方向大小设置为&lt;code&gt;100%&lt;/code&gt;或者一个你喜欢的宽度；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;如果元素本身还有子元素，需要特别注意子元素的高度需要设置为&lt;code&gt;100%&lt;/code&gt;&lt;/strong&gt;。如果没有设置，则会导致子元素本身的高度不受限制，从而撑爆了元素本身。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;特别需要注意的就是第4点：布局的时候经常使用到&lt;code&gt;el-row/el-col&lt;/code&gt;，其最后生成的html代码就会出现嵌套的&lt;code&gt;div&lt;/code&gt;组合，是一个典型的父子结构。这时就要注意在&lt;code&gt;el-col&lt;/code&gt;上设置相应的高度为&lt;code&gt;100%&lt;/code&gt;，否则就会出现撑爆了的结果。&lt;/p&gt;
&lt;p&gt;下面是最终的代码，相关要点添加了注释：&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>RSA证书格式</title>
      <link>https://blog.orchidflower.cn/2021/11/26/RSA-certificate-format/</link>
      <pubDate>Fri, 26 Nov 2021 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2021/11/26/RSA-certificate-format/</guid>
      <description>&lt;h1 id=&#34;1-tldr&#34;&gt;1. TL;DR&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;# -----BEGIN CERTIFICATE-----&lt;/code&gt; 开头的是证书。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# -----BEGIN RSA PRIVATE KEY-----&lt;/code&gt; 开头是遵循的&lt;code&gt;PKCS#1&lt;/code&gt;规范，其内容只是一个RSA私钥。它本质上只是来自PKCS#8的关键对象，但前面没有版本或算法标识符。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# -----BEGIN PRIVATE KEY-----&lt;/code&gt; 开头遵循的是&lt;code&gt;PKCS#8&lt;/code&gt;规范，并指示密钥类型包含在密钥数据本身中。&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Jenkins工作空间页面崩溃问题解决</title>
      <link>https://blog.orchidflower.cn/2021/10/22/Jenkins-crashed-in-workspace-page/</link>
      <pubDate>Fri, 22 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2021/10/22/Jenkins-crashed-in-workspace-page/</guid>
      <description>&lt;h1 id=&#34;1-问题&#34;&gt;1. 问题&lt;/h1&gt;
&lt;p&gt;最近发现一个问题：在 &lt;code&gt;Jenkins&lt;/code&gt; 中打开某些项目的工作空间（&lt;code&gt;WorkSpace&lt;/code&gt;）的时候，页面会崩溃，显示如下的错误信息：
&lt;img src=&#34;http://blog-cache.orchidflower.cn/mweb/16317740172888.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;查看 &lt;code&gt;Jenkins&lt;/code&gt; 日志发现如下错误信息，提示的是路径无效错误（&lt;code&gt;InvalidPathException&lt;/code&gt;），该目录应该是中文名字，猜测是编码转换出了错误。
&lt;img src=&#34;http://blog-cache.orchidflower.cn/mweb/16317740902097.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;2-解决&#34;&gt;2. 解决&lt;/h1&gt;
&lt;p&gt;由于是使用 &lt;code&gt;Docker&lt;/code&gt; 运行的 &lt;code&gt;Jenkins&lt;/code&gt;，登录进 &lt;code&gt;Jenkins&lt;/code&gt; 容器内部，查看对应的目录：
&lt;img src=&#34;http://blog-cache.orchidflower.cn/mweb/16317741870998.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;发现在容器内部看到的目录就是乱码了。而在外部环境可以正常显示目录：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://blog-cache.orchidflower.cn/mweb/16317743090169.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Vue进行条件编译发布</title>
      <link>https://blog.orchidflower.cn/2021/09/24/Vue-compile-on-condition/</link>
      <pubDate>Fri, 24 Sep 2021 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2021/09/24/Vue-compile-on-condition/</guid>
      <description>&lt;p&gt;最近碰到一个问题：公司新申请了一个公众号，这个新公众号的功能与之前一个公众号功能基本一致，只是两个公众号的用户协议有些区别，所以就会公用一份代码。现在需要解决发布的问题，需要确保发布到两个不同公众号的页面是正确的，不同公众号的用户看到正确的用户协议。&lt;/p&gt;
&lt;p&gt;经过上网查找方案，发现 &lt;code&gt;Vue&lt;/code&gt; 脚手架中提供的 &lt;code&gt;vue-cli-service&lt;/code&gt; 内置了类似的功能，可以用来实现类似功能，这里简单说一下其涉及到的改动要点，更多细节可以参考&lt;code&gt;vue-cli&lt;/code&gt;的文档&lt;a href=&#34;https://cli.vuejs.org/zh/guide/mode-and-env.html&#34;&gt;模式和环境变量&lt;/a&gt;。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>MySQL如何保存emoji字符</title>
      <link>https://blog.orchidflower.cn/2021/07/22/How-Could-MySQL-Save-emoji/</link>
      <pubDate>Thu, 22 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2021/07/22/How-Could-MySQL-Save-emoji/</guid>
      <description>&lt;h1 id=&#34;1-问题&#34;&gt;1. 问题&lt;/h1&gt;
&lt;h2 id=&#34;11-发现问题&#34;&gt;1.1 发现问题&lt;/h2&gt;
&lt;p&gt;最近生产环境日志中报了一个异常：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;2021-07-11 20:54:41.632 ERROR 26289 --- [XNIO-1 task-11] c.e.t.s.t.mp.WxMpMessageRouterService    :
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;### Error updating database.  Cause: java.sql.SQLException: Incorrect string value: &amp;#39;\xF0\x9F\xA6\x84&amp;#39; for column &amp;#39;NICK_NAME&amp;#39; at row 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;### The error may exist in com/eveus/tap/account/mapper/AccountMapper.java (best guess)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;### The error may involve com.eveus.tap.account.mapper.AccountMapper.insert-Inline
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;### The error occurred while setting parameters
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;### SQL: INSERT INTO tap_account  ( open_id, avatar, nick_name, country, province, city, gender, secret,         status, IS_DISABLED,     is_subscribe, create_time, update_time )  VALUES
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;  ( ?, ?, ?, ?, ?, ?, ?, ?,         ?, ?,     ?, ?, ? )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;### Cause: java.sql.SQLException: Incorrect string value: &amp;#39;\xF0\x9F\xA6\x84&amp;#39; for column &amp;#39;NICK_NAME&amp;#39; at row 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;; uncategorized SQLException; SQL state [HY000]; error code [1366]; Incorrect string value: &amp;#39;\xF0\x9F\xA6\x84&amp;#39; for column &amp;#39;NICK_NAME&amp;#39; at row 1; nested exception is java.sql.SQLException:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt; Incorrect string value: &amp;#39;\xF0\x9F\xA6\x84&amp;#39; for column &amp;#39;NICK_NAME&amp;#39; at row 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;org.springframework.jdbc.UncategorizedSQLException:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&lt;/span&gt;&lt;span&gt;### Error updating database.  Cause: java.sql.SQLException: Incorrect string value: &amp;#39;\xF0\x9F\xA6\x84&amp;#39; for column &amp;#39;NICK_NAME&amp;#39; at row 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&lt;/span&gt;&lt;span&gt;### The error may exist in com/eveus/tap/account/mapper/AccountMapper.java (best guess)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15&lt;/span&gt;&lt;span&gt;### The error may involve com.eveus.tap.account.mapper.AccountMapper.insert-Inline
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16&lt;/span&gt;&lt;span&gt;### The error occurred while setting parameters
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17&lt;/span&gt;&lt;span&gt;### SQL: INSERT INTO tap_account  ( open_id, avatar, nick_name, country, province, city, gender, secret,         status, IS_DISABLED,     is_subscribe, create_time, update_time )  VALUES
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18&lt;/span&gt;&lt;span&gt;  ( ?, ?, ?, ?, ?, ?, ?, ?,         ?, ?,     ?, ?, ? )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19&lt;/span&gt;&lt;span&gt;### Cause: java.sql.SQLException: Incorrect string value: &amp;#39;\xF0\x9F\xA6\x84&amp;#39; for column &amp;#39;NICK_NAME&amp;#39; at row 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20&lt;/span&gt;&lt;span&gt;; uncategorized SQLException; SQL state [HY000]; error code [1366]; Incorrect string value: &amp;#39;\xF0\x9F\xA6\x84&amp;#39; for column &amp;#39;NICK_NAME&amp;#39; at row 1; nested exception is java.sql.SQLException:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21&lt;/span&gt;&lt;span&gt; Incorrect string value: &amp;#39;\xF0\x9F\xA6\x84&amp;#39; for column &amp;#39;NICK_NAME&amp;#39; at row 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22&lt;/span&gt;&lt;span&gt;        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:89)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23&lt;/span&gt;&lt;span&gt;        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24&lt;/span&gt;&lt;span&gt;        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25&lt;/span&gt;&lt;span&gt;        at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:88)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26&lt;/span&gt;&lt;span&gt;        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27&lt;/span&gt;&lt;span&gt;        at com.sun.proxy.$Proxy134.insert(Unknown Source)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28&lt;/span&gt;&lt;span&gt;        at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:271)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29&lt;/span&gt;&lt;span&gt;        at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:60)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30&lt;/span&gt;&lt;span&gt;        at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:96)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31&lt;/span&gt;&lt;span&gt;        at com.sun.proxy.$Proxy186.insert(Unknown Source)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32&lt;/span&gt;&lt;span&gt;        at com.baomidou.mybatisplus.extension.service.IService.save(IService.java:59)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33&lt;/span&gt;&lt;span&gt;        at com.eveus.tap.account.service.impl.AccountServiceImpl.addAccount(AccountServiceImpl.java:151)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34&lt;/span&gt;&lt;span&gt;        at com.eveus.tap.account.service.impl.AccountServiceImpl.ensureLoad(AccountServiceImpl.java:226)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35&lt;/span&gt;&lt;span&gt;        at com.eveus.tap.account.service.impl.AccountServiceImpl$$FastClassBySpringCGLIB$$34fe95c8.invoke(&amp;lt;generated&amp;gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;36&lt;/span&gt;&lt;span&gt;        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;37&lt;/span&gt;&lt;span&gt;        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;38&lt;/span&gt;&lt;span&gt;        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;39&lt;/span&gt;&lt;span&gt;        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;40&lt;/span&gt;&lt;span&gt;        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;41&lt;/span&gt;&lt;span&gt;        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;42&lt;/span&gt;&lt;span&gt;        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;43&lt;/span&gt;&lt;span&gt;        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;44&lt;/span&gt;&lt;span&gt;        at com.eveus.tap.account.service.impl.AccountServiceImpl$$EnhancerBySpringCGLIB$$cbb1e26b.ensureLoad(&amp;lt;generated&amp;gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;45&lt;/span&gt;&lt;span&gt;        at com.eveus.tap.server.taxer.mp.handler.SubscribeHandler.handle(SubscribeHandler.java:54)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;46&lt;/span&gt;&lt;span&gt;        at me.chanjar.weixin.mp.api.WxMpMessageRouterRule.service(WxMpMessageRouterRule.java:226)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;47&lt;/span&gt;&lt;span&gt;        at me.chanjar.weixin.mp.api.WxMpMessageRouter.route(WxMpMessageRouter.java:203)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;48&lt;/span&gt;&lt;span&gt;        at me.chanjar.weixin.mp.api.WxMpMessageRouter.route(WxMpMessageRouter.java:154)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;49&lt;/span&gt;&lt;span&gt;        at me.chanjar.weixin.mp.api.WxMpMessageRouter.route(WxMpMessageRouter.java:233)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;看错误信息是因为 &lt;code&gt;MySQL&lt;/code&gt; 字符编码不正确导致无法保存特殊字符导致的。把字符还原一下，发现 &lt;code&gt;\xF0\x9F\xA6\x84&lt;/code&gt; 代表的字符内容是：🦄，是一个 &lt;code&gt;Emoji&lt;/code&gt; 字符。&lt;/p&gt;
&lt;p&gt;当使用对 &lt;code&gt;utf8&lt;/code&gt; 编码的时候，和一般汉字占用3个字节不同，&lt;code&gt;Emoji&lt;/code&gt; 字符的编码会比较特殊一点，占用4个字节。而由于历史的原因，&lt;code&gt;MySQL&lt;/code&gt; 使用的 &lt;code&gt;utf8&lt;/code&gt; 编码最长支持3个字节，如果要保存4个字节的 &lt;code&gt;unicode&lt;/code&gt;，则需要使用 &lt;code&gt;utf8mb4&lt;/code&gt; 编码。上述错误应该是因此而出。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>MyBatis Plus中主键生成方式ASSIGN_ID的算法分析</title>
      <link>https://blog.orchidflower.cn/2021/07/02/MyBatis-ASSIGN_ID-Algorithm/</link>
      <pubDate>Fri, 02 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2021/07/02/MyBatis-ASSIGN_ID-Algorithm/</guid>
      <description>&lt;p&gt;&lt;code&gt;MyBatis Plus&lt;/code&gt; 中提供了 &lt;code&gt;ASSIGN_ID&lt;/code&gt; 这种方式生成主键，使用起来非常方便，只要在&lt;code&gt;PO&lt;/code&gt;上定义一下就可以了，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#00a8c8&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;Order&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Model&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;Order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75af00&#34;&gt;@TableId&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;IdType&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;ASSIGN_ID&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Long&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;//...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样在保存的时候，&lt;code&gt;MyBatis Plus&lt;/code&gt;会负责生成主键值，自动设置到字段&lt;code&gt;id&lt;/code&gt;中。
一直好奇这个主键是怎么生成的，抽时间查看了一下源码，特意记录一下。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Linux常用命令介绍 05 - unzip</title>
      <link>https://blog.orchidflower.cn/2021/02/26/linux-command-introduction-05-unzip/</link>
      <pubDate>Fri, 26 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2021/02/26/linux-command-introduction-05-unzip/</guid>
      <description>&lt;p&gt;unzip命令可以用来解压zip文件。用法比较简单，但是有些不太常用的命令需要记录一下。&lt;/p&gt;
&lt;h1 id=&#34;1-查看文件列表&#34;&gt;1. 查看文件列表&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;unzip -l ShadowHunters.epub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查看更详细信息，包括压缩率等&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;unzip -lv ShadowHunters.epub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;2-解压文件&#34;&gt;2. 解压文件&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;unzip -d ./temp ShadowHunters.epub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;3-解压一个文件&#34;&gt;3. 解压一个文件&lt;/h1&gt;
&lt;p&gt;使用&lt;code&gt;-p&lt;/code&gt;命令，将文件内容输出到标准输出，然后使用重定向创建文件：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;unzip -p ShadowHunters.epub ops/xhtml/cover.html &amp;gt; cover.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;4-更新文件&#34;&gt;4. 更新文件&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;zip -u ShadowHunters.epub ops/xhtml/cover.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>如何在Ubuntu上静态编译Golang&#43;GoCV程序</title>
      <link>https://blog.orchidflower.cn/2020/12/18/How-to-build-static-binary-with-gocv/</link>
      <pubDate>Fri, 18 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/12/18/How-to-build-static-binary-with-gocv/</guid>
      <description>&lt;p&gt;最近做了一个图像增强程序，用到了OpenCV。为了方便发布，我将代码使用&lt;code&gt;Golang&lt;/code&gt;+&lt;code&gt;GoCV&lt;/code&gt;重写，但是编译的时候发现比较麻烦，特别记录一下，以备后查。
本文对应版本如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ubuntu 18.04.5 LTS&lt;/li&gt;
&lt;li&gt;Golang 1.15.6&lt;/li&gt;
&lt;li&gt;OpenCV 4.5.0&lt;/li&gt;
&lt;li&gt;GoCV 0.2.5&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;1-golang环境准备&#34;&gt;1. Golang环境准备&lt;/h1&gt;
&lt;h2 id=&#34;11-安装golang&#34;&gt;1.1 安装Golang&lt;/h2&gt;
&lt;p&gt;下载对应的包，然后解压，设置&lt;code&gt;PATH&lt;/code&gt;路径即可，不多说了。&lt;/p&gt;
&lt;h2 id=&#34;12-设置gopath&#34;&gt;1.2 设置GOPATH&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;go get&lt;/code&gt;下载的包将下载到&lt;code&gt;$GOPATH&lt;/code&gt;目录中。
这里设置成&lt;code&gt;/home/ubuntu/.go&lt;/code&gt;。不设置的话将自动设置成&lt;code&gt;~/go&lt;/code&gt;目录。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#111&#34;&gt;cd&lt;/span&gt; /home/ubuntu/.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#111&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;GOPATH&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/home/ubuntu/.go
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;13-下载gocv源码&#34;&gt;1.3 下载GoCV源码&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 设置代理翻墙，要不然下载不了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;git config --global http.proxy&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;http://127.0.0.1:12346
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;git config --global https.proxy&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;http://127.0.0.1:12346
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#111&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;http_proxy&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;http://127.0.0.1:12346
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#111&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;https_proxy&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;http://127.0.0.1:12346
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span&gt;go get -v -u -d gocv.io/x/gocv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>删除启动台Launchpad上无效的图标</title>
      <link>https://blog.orchidflower.cn/2020/12/04/Delete-Invalid-Icon-from-Lauchpad/</link>
      <pubDate>Fri, 04 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/12/04/Delete-Invalid-Icon-from-Lauchpad/</guid>
      <description>&lt;p&gt;今天删除软件的时候碰到一个问题，软件虽然被删除了，但是图标依然在启动台上。怎么也删不掉。上网搜了搜，找到一个办法可以解决。特此记录一下。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 切换到目录 /private/var/folders&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#111&#34;&gt;cd&lt;/span&gt; /private/var/folders
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 寻找 com.apple.dock.launchpad 目录，图标信息存在该目录中的一个sqlite3数据库中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;sudo find . &lt;span style=&#34;color:#111&#34;&gt;|&lt;/span&gt; grep com.apple.dock.launchpad
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 确定好目录，然后使用cd转入对应的目录。目录名不同机器上不一样&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 使用sqlite3工具查询一下&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;sqlite3 db &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;select * from apps where title like &amp;#39;eclipse%&amp;#39;;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 确认之后可以使用delete语句删除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;sqlite3 db &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;delete from apps where title like &amp;#39;eclipse%&amp;#39;;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 然后杀掉Dock进程，就好了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;killall Dock
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>禁用CleanMyMacX HealthMonitor</title>
      <link>https://blog.orchidflower.cn/2020/11/27/How-to-Disable-CleanMyMacX-HealthMonitor/</link>
      <pubDate>Fri, 27 Nov 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/11/27/How-to-Disable-CleanMyMacX-HealthMonitor/</guid>
      <description>&lt;p&gt;&lt;code&gt;CleanMyMacX&lt;/code&gt; 是&lt;code&gt;Mac&lt;/code&gt;平台上优秀的卸载工具。虽然&lt;code&gt;Mac&lt;/code&gt;上的应用安装卸载比&lt;code&gt;Windows&lt;/code&gt;上简单很多，&lt;code&gt;AppStore&lt;/code&gt;上的软件采用的是沙盒模型，删除的时候会把相关的数据一并删除；但是大量的非&lt;code&gt;AppStore&lt;/code&gt;软件在删除对应的app之后不会同时删除对应的数据。 &lt;code&gt;CleanMyMacX&lt;/code&gt; 这种类型的软件会扫描这些相关的数据并一起删除。&lt;/p&gt;
&lt;p&gt;最近发现 &lt;code&gt;CleanMyMacX&lt;/code&gt; 会附带一个后台服务：&lt;code&gt;CleanMyMacX HealthMonitor&lt;/code&gt;，即使软件本身退出这个后台服务还一直运行。这就有点360的味道了，让人不爽。最主要的是这个进程对资源的占用还是有的，没有到那种可以完全忽略的地步。因此想办法禁用它。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>使用MyBatis ResultHandler解决巨大结果集导出Excel引发的OOM</title>
      <link>https://blog.orchidflower.cn/2020/09/04/Using-MyBatis-ResultHandler-to-export-huge-resultset-avoiding-OOM/</link>
      <pubDate>Fri, 04 Sep 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/09/04/Using-MyBatis-ResultHandler-to-export-huge-resultset-avoiding-OOM/</guid>
      <description>&lt;p&gt;当一次要导出非常多数据的时候，例如100w条，如果使用&lt;code&gt;MyBatis&lt;/code&gt;将全部结果都查询到&lt;code&gt;list&lt;/code&gt;中，经常会导致内存溢出。这个时候，我们可以使用&lt;code&gt;MyBatis&lt;/code&gt;的&lt;code&gt;ResultHandler&lt;/code&gt;来使用游标方式访问数据，从而避免&lt;code&gt;OOM&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ResultHandler&lt;/code&gt;是MyBatis提供的一个接口，通过该接口可以让&lt;code&gt;MyBatis&lt;/code&gt;以流式的方式处理结果集，而不必等待整个结果集全部准备完毕，在准备好一条记录后就调用该接口中的&lt;code&gt;handleResult&lt;/code&gt;方法：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#00a8c8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;handleResult&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;ResultContext&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;T&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;resultContext&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;要使用&lt;code&gt;ResultHandler&lt;/code&gt;需要在&lt;code&gt;Mapper&lt;/code&gt;层声明的时候做一定的处理。这里简单描述一下。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>使用Python写一个Alfred Workflow</title>
      <link>https://blog.orchidflower.cn/2020/08/21/Build-Alfred-workflow-using-python/</link>
      <pubDate>Fri, 21 Aug 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/08/21/Build-Alfred-workflow-using-python/</guid>
      <description>&lt;h1 id=&#34;1-alfred-和-workflows-介绍&#34;&gt;1. &lt;code&gt;Alfred&lt;/code&gt; 和 &lt;code&gt;Workflows&lt;/code&gt; 介绍&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;Alfred&lt;/code&gt; 号称是 &lt;code&gt;Mac&lt;/code&gt; 上最强大的效率工具，一直在 &lt;code&gt;Mac&lt;/code&gt; 平台的工具类中排名榜首。它在&lt;code&gt;Spotlight&lt;/code&gt; （ &lt;code&gt;Mac&lt;/code&gt; 自带的搜索和快速启动引擎）基础上优化了快速启动与搜索的功能，还引入了 &lt;code&gt;Workflows&lt;/code&gt; 等强大的扩展功能，使之成为了一个拥有无限自动化潜力的「工具平台」软件，可以用它来实现近乎一切有关自动化的想法。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Worflows&lt;/code&gt; 是 &lt;code&gt;Alfred&lt;/code&gt; 的高端应用方式，它以流的方式来进行工作，从输入 -&amp;gt; 动作 -&amp;gt; 输出，将各种工具串联在一起进行工作，非常开放，用来将各种功能串联起来执行，可以定制完成各种想要实现的功能，潜力无限。&lt;/p&gt;
&lt;p&gt;虽然网上已经有很多别人写好的 &lt;code&gt;Workflow&lt;/code&gt;，但总是不够用，毕竟各自的偷懒点不同，因此有必要学会 &lt;code&gt;Workflow&lt;/code&gt; 的编写，可以更好的满足自己的要求。&lt;/p&gt;
&lt;h1 id=&#34;2-开始写一个workflows&#34;&gt;2. 开始写一个&lt;code&gt;Workflows&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;今天想写一个生成随机字符串的&lt;code&gt;Workflow&lt;/code&gt;，可选接收一个长度参数，生成指定长度的字符串，这个字符串可以由数字、字符、数字+字符等构成。下面说一下整个创建过程。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Mac休眠模式调整</title>
      <link>https://blog.orchidflower.cn/2020/08/11/How-to-change-hibernate-mod-for-Mac/</link>
      <pubDate>Tue, 11 Aug 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/08/11/How-to-change-hibernate-mod-for-Mac/</guid>
      <description>&lt;p&gt;手头的Mac已经用了三年了，之前合盖睡眠的时候感觉掉电还不明显，最近几次系统升级后感觉掉电的情况明显了，一个晚上会掉5%左右，虽然不多，但是还是不爽。
经过搜索，发现可以通过修改休眠模式，来解决这个问题，特此记录一下。&lt;/p&gt;
&lt;h1 id=&#34;1-pmset及参数介绍&#34;&gt;1. pmset及参数介绍&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;pmset&lt;/code&gt;是Mac的一个系统命令，可以用来修改和电源管理相关的参数。看&lt;code&gt;man&lt;/code&gt;中的帮助：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;pmset can modify the values of any of the power management settings defined below. You may specify one or more
setting &amp;amp; value pairs on the command-line invocation of pmset.  The -a, -b, -c, -u flags determine whether the
settings apply to battery ( -b ), charger (wall power) ( -c ), UPS ( -u ) or all ( -a ).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;简单来说就是可以通过&lt;code&gt;pmset -b&lt;/code&gt;或&lt;code&gt;pmset -c&lt;/code&gt;,&lt;code&gt;pmset -a&lt;/code&gt;等命令修改电源配置参数。当然也可以通过&lt;code&gt;pmset -g&lt;/code&gt;命令查询当前的配置参数或日志等。例如以下命令可以查看当前系统的电源相关配置：&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>使用KeepAlived配置Nginx高可用</title>
      <link>https://blog.orchidflower.cn/2020/07/20/Use-keepalived-for-high-availability-support-for-nginx/</link>
      <pubDate>Mon, 20 Jul 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/07/20/Use-keepalived-for-high-availability-support-for-nginx/</guid>
      <description>&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;最近为一个传统行业的客户开发了一个生产调度系统。但是他的生产环境是自己搭建的，不是购买的云服务，因此碰到了一些问题。&lt;/p&gt;
&lt;p&gt;客户购买了多台高性能的物理机，在上面自行搭建虚拟机。但是只有虚拟机，没有提供类似负载均衡、数据库等基础服务。为了解决负载均衡问题，我们自行安装了 &lt;code&gt;Nginx&lt;/code&gt; 。为了保证系统健壮和性能，安装 &lt;code&gt;Nginx&lt;/code&gt; 的两台虚拟机（Ubuntu 18.04.3 LTS，172.16.45.22，172.16.45.26）分别部署在两台不同的物理机上（172.16.45.11， 172.168.45.12）。然后 &lt;code&gt;DNS&lt;/code&gt; 解析到两台 &lt;code&gt;Nginx&lt;/code&gt; 主机上。&lt;/p&gt;
&lt;p&gt;现在的问题是：客户的要求是任何一台物理机出现问题都要能够保证系统可用，验证的方式是测试的时候会直接断开物理机的网线，这将导致通过 &lt;code&gt;DNS&lt;/code&gt; 解析出来的 &lt;code&gt;Nginx&lt;/code&gt; 主机必然有一台是无法使用的。访问显然会出问题。&lt;/p&gt;
&lt;p&gt;经过考虑，最后选定解决办法是：使用 &lt;code&gt;KeepAlived&lt;/code&gt; 做高可用，两台 &lt;code&gt;Nginx&lt;/code&gt; 共同维护一个虚拟IP（172.16.45.50），&lt;code&gt;DNS&lt;/code&gt; 解析到这个虚拟IP上。&lt;/p&gt;
&lt;p&gt;这里简单记录一下安装 &lt;code&gt;KeepAlived&lt;/code&gt; 的过程以及碰到的一些问题及解决方案。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>如何修改Ubuntu服务器上的DNS设置</title>
      <link>https://blog.orchidflower.cn/2020/07/10/How-to-Change-DNS-on-Ubuntu/</link>
      <pubDate>Fri, 10 Jul 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/07/10/How-to-Change-DNS-on-Ubuntu/</guid>
      <description>&lt;p&gt;公司的几台服务器安装的时候设置了联通的DNS服务器，由于公司网络切换到了电信，最近经常出现解析服务器IP失败的情况。所以想着要更换一下DNS服务器，以提高网络访问速度。&lt;/p&gt;
&lt;p&gt;因为历史原因，服务器操作系统主要有 &lt;code&gt;Ubuntu 16.04 LTS&lt;/code&gt; 和 &lt;code&gt;Ubuntu 18.04 LTS&lt;/code&gt; 两种。实际修改中发现，他们的配置方法是不一样的，特此记录一下。&lt;/p&gt;
&lt;h1 id=&#34;1-ubuntu-1604-lts&#34;&gt;1. Ubuntu 16.04 LTS&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;16.04 LTS&lt;/code&gt;上主要修改两个文件。&lt;/p&gt;
&lt;h2 id=&#34;21-更新resolvconf&#34;&gt;2.1 更新resolv.conf&lt;/h2&gt;
&lt;p&gt;首先修改文件：&lt;code&gt;/etc/resolvconf/resolv.conf.d/base&lt;/code&gt;文件，内容如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#00a8c8&#34;&gt;nameserver&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;114&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;.114.114.114&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;nameserver&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;223&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;.5.5.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后执行：&lt;code&gt;resolvconf -u&lt;/code&gt;命令就可以更新dns服务器了。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在Mac上编译RedisDesktopManager（1）国际化处理</title>
      <link>https://blog.orchidflower.cn/2020/07/01/How-to-build-Redis-Desktop-Manager-on-Mac/</link>
      <pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/07/01/How-to-build-Redis-Desktop-Manager-on-Mac/</guid>
      <description>&lt;h1 id=&#34;1-概述&#34;&gt;1. 概述&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Redis Desktop Manager（RedisDesktopManager，RDM）是一个快速、简单、支持跨平台的 Redis 桌面管理工具，基于 Qt 5 开发，支持通过 SSH Tunnel 连接。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;ndash; 开源中国上面对项目的介绍&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RedisDesktopManager&lt;/code&gt; 是一款优秀的 &lt;code&gt;Redis&lt;/code&gt; 客户端。最初是作为开源项目发布的，官方也会发布编译好的版本。后来，作者做了一些商业化处理，上架了&lt;code&gt;App Store&lt;/code&gt;，从此不再发布编译后的版本，也在开源版本中阉割掉了 &lt;code&gt;SSH Tunnel&lt;/code&gt; 功能。有鉴于此，网上有很多人写教程来说明如何从源码构建一个发行版本，但是目前见到的教程多多少少都有一些问题。最近花了一些时间尝试完善整个编译过程，目前进展不错。以后会陆续说明编译过程中碰到的问题以及对应的解决办法。&lt;/p&gt;
&lt;p&gt;今天首先来说一下国际化的问题。&lt;/p&gt;
&lt;p&gt;目前网上流行的 &lt;code&gt;RedisDesktopManager&lt;/code&gt; 编译方法都没有对国际化文件进行处理，所以编译后的版本没有国际化功能，界面只显示英文，语言切换功能无效。经过对相关源码的分析，终于找到了正确的编译处理方法，现在可以完美切换语言。效果如图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://blog-cache.orchidflower.cn/2020-07-02-15936592204991.jpg&#34; alt=&#34;-w800&#34;&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>如何在Mac上编译vcmi（续）-cpack打包后异常退出</title>
      <link>https://blog.orchidflower.cn/2020/06/26/How-to-build-vcmi-on-mac-part3/</link>
      <pubDate>Fri, 26 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/06/26/How-to-build-vcmi-on-mac-part3/</guid>
      <description>&lt;h1 id=&#34;1-现象&#34;&gt;1. 现象&lt;/h1&gt;
&lt;p&gt;VCMI编译之后可以使用&lt;code&gt;cpack&lt;/code&gt;命令（cmake的一个功能）打包成dmg文件，以便于分发。打包过程中会把需要的依赖文件都打包到最后的&lt;code&gt;.app&lt;/code&gt;文件中，这样就可以保证在其他机器上也可以正常运行编译后的VCMI。
按照之前的文档，编译之后直接执行没有问题，但是使用&lt;code&gt;cpack&lt;/code&gt;打包之后运行缺会异常退出。经过观察基本上发生在第一次战斗中，玩家操作完毕，电脑AI获得控制权的时候就会崩溃退出。&lt;/p&gt;
&lt;h1 id=&#34;2-分析&#34;&gt;2. 分析&lt;/h1&gt;
&lt;p&gt;最初怀疑是新版本代码有问题，所以切换到之前版本的代码编译，发现还是有同样的问题。后来经过分析退出的时间点，怀疑是&lt;code&gt;vcmi&lt;/code&gt;的AI代码有问题，因为对代码部分不是很熟悉，所以很长时间没有进展。
后来经过查看&lt;code&gt;cpack&lt;/code&gt;的工作原理，怀疑是AI库对应的依赖文件没有正确打包导致的。&lt;/p&gt;
&lt;p&gt;使用&lt;code&gt;otool -L&lt;/code&gt;分析动态库依赖，发现AI目录下的文件没有进行依赖库的处理。还是指向&lt;code&gt;/usr/local/...&lt;/code&gt;下面的dylib文件。而&lt;code&gt;vcmiclient/vcmiserver&lt;/code&gt;已经进行了处理。因此怀疑是因为引入了两份动态库导致的问题，&lt;code&gt;vcmiclient&lt;/code&gt;已经加载了一份动态库，但是当执行到AI库的时候又要从其他位置加载另一份同名的动态库，可能是因为这个原因导致了崩溃。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>如何在Mac上编译vcmi（续）-解决无法播放MP3的问题</title>
      <link>https://blog.orchidflower.cn/2020/06/21/How-to-build-vcmi-on-mac-part2/</link>
      <pubDate>Sun, 21 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/06/21/How-to-build-vcmi-on-mac-part2/</guid>
      <description>&lt;h1 id=&#34;1-问题&#34;&gt;1. 问题&lt;/h1&gt;
&lt;p&gt;按照上一篇文档的步骤编译之后，发现mp3格式的背景音乐无法播放。通过直接执行&lt;code&gt;vcmiclient&lt;/code&gt;可以看到在控制台中输出如下信息：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;Warning: Cannot open Music/MainMenu: Unrecognized audio format
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;Unable to play music (music parameter was NULL)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;原因是我本地环境使用的&lt;code&gt;sdl2_mixer&lt;/code&gt;是通过brew安装的，当时无法按照官方文档介绍通过&lt;code&gt;brew install sdl2_mixer --with-smpeg2&lt;/code&gt;进行安装。
因为发现无法播放mp3音乐，所以我对这个库进行了一些了解，发现brew官方的版本屏蔽了mp3格式的支持。查看brew官方的源码可以看到：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#00a8c8&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;install&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#111&#34;&gt;inreplace&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;SDL2_mixer.pc.in&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;@prefix@&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;HOMEBREW_PREFIX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#111&#34;&gt;args&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;%W[
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --prefix=&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;#{&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;prefix&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-dependency-tracking
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-flac
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-flac-shared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-midi-fluidsynth
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-midi-fluidsynth-shared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-mod-mikmod-shared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-mod-modplug-shared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-mp3-mpg123
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-mp3-mpg123-shared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-mp3-smpeg
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --disable-music-ogg-shared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --enable-music-mod-mikmod
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --enable-music-mod-modplug
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;      --enable-music-ogg
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#d88200&#34;&gt;    ]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#111&#34;&gt;system&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;./configure&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;args&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#111&#34;&gt;system&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;make&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;install&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24&lt;/span&gt;&lt;span&gt;  &lt;span style=&#34;color:#00a8c8&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到有关mp3的选项都被disabled掉了。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>如何在Mac上编译vcmi</title>
      <link>https://blog.orchidflower.cn/2020/05/09/How-to-build-vcmi-on-mac/</link>
      <pubDate>Sat, 09 May 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/05/09/How-to-build-vcmi-on-mac/</guid>
      <description>&lt;p&gt;&lt;code&gt;vcmi&lt;/code&gt;是英雄无敌三的开源引擎。与&lt;code&gt;fheroes2&lt;/code&gt;类似，它依托于英雄无敌3的游戏数据，使用完全重写、开源的引擎，实现了原版游戏的绝大多数功能。相比于原版游戏，对高清分辨率的支持也更好，譬如增加了宽屏分辨率的支持。&lt;code&gt;vcmi&lt;/code&gt;使用&lt;code&gt;c++&lt;/code&gt;语言编写，依赖库主要包括：&lt;code&gt;boost&lt;/code&gt;，&lt;code&gt;ffmpeg&lt;/code&gt;；图形库使用的是&lt;code&gt;SDL2&lt;/code&gt;。另外，图形启动工具依赖于&lt;code&gt;QT5&lt;/code&gt;。&lt;code&gt;vcmi&lt;/code&gt;支持平台包括&lt;code&gt;Windows&lt;/code&gt;，&lt;code&gt;MacOS&lt;/code&gt;，&lt;code&gt;Android&lt;/code&gt;和&lt;code&gt;Linux&lt;/code&gt;，算是全平台支持了。&lt;/p&gt;
&lt;p&gt;不过官方的发布系统好像有点问题，&lt;code&gt;MacOS&lt;/code&gt;版本最新到2019年9月，后面的版本没有构建成功。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vcmi.eu/img/2017/09/vcmionmac.jpg&#34; alt=&#34;VCMI介绍图片&#34;&gt;&lt;/p&gt;
&lt;p&gt;英雄无敌3，全称《魔法门之英雄无敌Ⅲ》，是1999年由&lt;code&gt;New World Computing&lt;/code&gt;在&lt;code&gt;Windows&lt;/code&gt;平台上开发的回合制策略魔幻游戏，其出版商是&lt;code&gt;3DO&lt;/code&gt;。在PC版发布之后，&lt;code&gt;3DO&lt;/code&gt;和&lt;code&gt;Loki Software&lt;/code&gt;分别推出了可在苹果机和Linux系统上运行的版本。&lt;/p&gt;
&lt;p&gt;该作是魔法门之英雄无敌系列的第三代。游戏情节参照第一次贯穿了《魔法门VI：天堂之令》，并且部分作为了《魔法门VII：血统与荣耀》的前传。玩家可以选择六个战役之中的一个来进行情节模式，也可以选择场景来进行与电脑或其他玩家的对抗。之后，又陆续发布了《末日之刃》、《死亡阴影》两个资料片，后来又发布了《英雄无敌历代记》共计8个战役。&lt;/p&gt;
&lt;p&gt;英雄无敌3历来被称为英雄无敌系列的经典之作，可以说是这个系列游戏的巅峰之作。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vcmi&lt;/code&gt;的官网有编译方法的说明，但是有些小的地方有些小问题。特此记录一下，以备后查。本次编译使用&lt;code&gt;cmake&lt;/code&gt;在命令行下面完成。需要确保已经安装了&lt;code&gt;xcode&lt;/code&gt;及&lt;code&gt;brew&lt;/code&gt;。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>如何在Mac上编译fheroes2</title>
      <link>https://blog.orchidflower.cn/2020/05/08/How-to-build-fheroes2-on-mac/</link>
      <pubDate>Fri, 08 May 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/05/08/How-to-build-fheroes2-on-mac/</guid>
      <description>&lt;p&gt;&lt;code&gt;fheroes2&lt;/code&gt;是&lt;code&gt;英雄无敌2&lt;/code&gt;的开源引擎，它基于英雄无敌2的游戏数据，采用完全重写的引擎实现了绝大多数原版游戏的功能。使用的图形引擎是&lt;code&gt;SDL&lt;/code&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Free implementation of Heroes of the Might and Magic II engine. SDL is used.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;fheroes2&lt;/code&gt;最初是在&lt;code&gt;SourceForge&lt;/code&gt;上面开源的，不过最近两年基本停止更新了。最近在&lt;code&gt;Github&lt;/code&gt;上偶然发现了有人在继续开发了，并且对图形引擎进行了更新，同时支持&lt;code&gt;SDL2&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://github.com/ihhub/fheroes2/raw/master/docs/images/screenshots/screenshot_world_map.png?raw=true&#34; alt=&#34;英雄无敌2&#34;&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>使用HttpServletRequestWrapper解决无法多次获取request Body的问题</title>
      <link>https://blog.orchidflower.cn/2020/04/30/Using-HttpServletRequestWrapper-solve-getInputStream/</link>
      <pubDate>Thu, 30 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/04/30/Using-HttpServletRequestWrapper-solve-getInputStream/</guid>
      <description>&lt;p&gt;在使用AOP编程的时候，经常碰到需要多次获取整个请求的body的情况。例如：典型场景下我们要在AOP切面中做日志记录或权限校验，此时需要调用&lt;code&gt;request.getInputStream&lt;/code&gt;获取输入流，从而读取整个请求的消息体。但是这通常会触发一个异常：&lt;code&gt;java.lang.IllegalStateException: getInputStream() can&#39;t be called after getReader()&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;出现这个问题的原因是默认的&lt;code&gt;HttpServletRequest&lt;/code&gt;对象中的&lt;code&gt;getInputStream&lt;/code&gt;,&lt;code&gt;getReader&lt;/code&gt;函数式只允许调用一次。在一次请求中，除了我们在切面中调用&lt;code&gt;getInputStream&lt;/code&gt;之外，&lt;code&gt;Spring MVC&lt;/code&gt;框架在进行参数转换的时候还需要调用&lt;code&gt;getInputStream&lt;/code&gt;方法读取整个请求的消息体，然后转回为请求参数，这违背了只调用一次的原则，从而触发了以异常，&lt;/p&gt;
&lt;p&gt;为了解决这个问题，我们可以引入&lt;code&gt;HttpServletRequestWrapper&lt;/code&gt;这个对象。这个类封装了&lt;code&gt;HttpServletRequest&lt;/code&gt;的行为，我们可以继承这个类，从而使用一个新类模拟原始&lt;code&gt;HttpServletRequest&lt;/code&gt;的行为。然后使用过滤器（filter）将原始的&lt;code&gt;HttpServletRequest&lt;/code&gt;对象替换为&lt;code&gt;HttpServletRequestWrapper&lt;/code&gt;对象。&lt;/p&gt;
&lt;p&gt;最近在项目中有需求为API请求增加参数签名校验，使用了AOP切面功能，因此碰到了上面的问题：参数校验切面中需要在读取整个请求报文，然后对报文进行hmac算法从而计算签名值。下面说一下具体的解决办法，以代码为主。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Linux常用命令介绍 04 - journalctl</title>
      <link>https://blog.orchidflower.cn/2020/04/20/linux-command-introduction-04-journalctl/</link>
      <pubDate>Mon, 20 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/04/20/linux-command-introduction-04-journalctl/</guid>
      <description>&lt;p&gt;&lt;code&gt;journalctl&lt;/code&gt;命令是&lt;code&gt;Systemd&lt;/code&gt;日志系统的一个命令，主要用途是用来查看通过&lt;code&gt;Systemd&lt;/code&gt;日志系统记录的日志。在&lt;code&gt;Systemd&lt;/code&gt;出现之前，&lt;code&gt;Linux&lt;/code&gt;系统及各应用的日志都是分别管理的，&lt;code&gt;Systemd&lt;/code&gt;开始统一管理了所有&lt;code&gt;Unit&lt;/code&gt;的启动日志，这样带来的好处就是可以只用一个 &lt;code&gt;journalctl&lt;/code&gt;命令，查看所有内核和应用的日志。&lt;/p&gt;
&lt;h1 id=&#34;1-基础用法&#34;&gt;1. 基础用法&lt;/h1&gt;
&lt;h2 id=&#34;11-查看所有日志&#34;&gt;1.1 查看所有日志&lt;/h2&gt;
&lt;p&gt;不用添加任何任何参数运行可以查看本次启动以来的所有日志。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 显示本次启动以来的全部日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;journalctl 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;12-查看内核日志&#34;&gt;1.2 查看内核日志&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;-k&lt;/code&gt;参数可以查看内核日志。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 显示内核日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;journalctl -k
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Linux常用命令介绍 03 - tree</title>
      <link>https://blog.orchidflower.cn/2020/04/07/linux-command-introduction-03-tree/</link>
      <pubDate>Tue, 07 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/04/07/linux-command-introduction-03-tree/</guid>
      <description>&lt;p&gt;tree命令的作用是以树状图的形式列出目录的内容。通常在写文档时需要列一下文件目录结构，这个时候&lt;code&gt;tree&lt;/code&gt;命令就非常有用了&lt;/p&gt;
&lt;h1 id=&#34;1-安装使用&#34;&gt;1. 安装&amp;amp;使用&lt;/h1&gt;
&lt;p&gt;我用的Ubuntu上默认没有安装&lt;code&gt;tree&lt;/code&gt;命令。可以通过：&lt;code&gt;sudo apt install tree&lt;/code&gt;命令安装。其他的发行版参考对应的命令。&lt;/p&gt;
&lt;p&gt;直接使用&lt;code&gt;tree&lt;/code&gt;命令或者&lt;code&gt;tree [directory]&lt;/code&gt;命令即可列出目录中的内容。&lt;/p&gt;
&lt;h1 id=&#34;2-只列出目录&#34;&gt;2. 只列出目录&lt;/h1&gt;
&lt;p&gt;默认情况下，&lt;code&gt;tree&lt;/code&gt;命令会同时列出目录中的文件。例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 列出全部内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;tree .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;├── Cargo.lock
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span&gt;├── Cargo.toml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span&gt;└── src
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span&gt;    └── main.rs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; directory, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; files
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果不想显示文件，则可以使用&lt;code&gt;-d&lt;/code&gt;参数，只列出文件夹：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 只列出目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;tree -d .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;└── src
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; directory
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Linux常用命令介绍 02 - ssh</title>
      <link>https://blog.orchidflower.cn/2020/03/29/linux-command-introduction-02-ssh/</link>
      <pubDate>Sun, 29 Mar 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/03/29/linux-command-introduction-02-ssh/</guid>
      <description>&lt;p&gt;SSH在Linux中占有重要的地位。通常我们远程登录服务器都是通过ssh协议，但是ssh命令（或者SSH协议）能够实现的功能还有很多。我日常用到一些，但是肯定还有各种各样的用法，有兴趣的朋友可以自行搜索更多资料。&lt;/p&gt;
&lt;h1 id=&#34;1-防止掉线&#34;&gt;1. 防止掉线&lt;/h1&gt;
&lt;p&gt;使用SSH连接服务器时候，通常第一个要修改的选项就是防止掉线。总体上来说有两类方法来防止服务器掉线：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客户端/客户端工具发送心跳包；&lt;/li&gt;
&lt;li&gt;服务器端发送心跳包。
如果有服务器的控制权，可以修改ssh的配置选项，推荐使用第二种方案，通常更有保障一些。如果没有服务器的控制权，那就只能用第一种了。&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Mac上面的文件比较功能</title>
      <link>https://blog.orchidflower.cn/2020/03/20/How-to-compare-file-on-mac/</link>
      <pubDate>Fri, 20 Mar 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/03/20/How-to-compare-file-on-mac/</guid>
      <description>&lt;p&gt;以前在Windows上一直使用TotalCmd，它的比较功能非常棒。不论是目录还是文件，只要按下F10，就能够比较，还能够同步，非常方便。切换到Mac也有好几年了，一直没有找到完全匹配上的替代品。现在用的是ForkLift，常用功能还可以，但是比较功能差距很大。目前正在想办法自己写一些脚本增强一下功能。&lt;/p&gt;
&lt;p&gt;目前实现了一个脚本，通过&lt;code&gt;ForkLift&lt;/code&gt;调用，可以满足基本的比较功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用&lt;code&gt;file&lt;/code&gt;判断文件类型，对文本类型调用&lt;code&gt;FileMerge&lt;/code&gt;进行源码比较；&lt;/li&gt;
&lt;li&gt;如果不是，则只用&lt;code&gt;cmp&lt;/code&gt;功能比较内容是否相等；&lt;/li&gt;
&lt;li&gt;后期考虑增加对目录类型的支持，引入目录比较工具。&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Linux常用命令介绍 01 - curl</title>
      <link>https://blog.orchidflower.cn/2020/03/13/linux-command-introduction-01-curl/</link>
      <pubDate>Fri, 13 Mar 2020 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2020/03/13/linux-command-introduction-01-curl/</guid>
      <description>&lt;p&gt;很久没有更新博客了。之前一直用hexo，配置起来稍显复杂，单个的时间一长有些忘了，搞不起来了，于是荒废了很长时间。最近下定决心迁移到了Hugo上。总体感觉Hugo速度确实快，这一点非常喜欢。以后有时间可以介绍一下这次迁移的过程。&lt;/p&gt;
&lt;p&gt;这几年一直不间断的与Linux打交道，但是Linux的命令一直没有深入研究过，所以碰到问题的时候还是要各种搜索，挺麻烦的。这次想整理一个常用命令的介绍系列，把平常用到的命令简单介绍一下。不会是详尽的帮助类介绍，更多的是基于场景的介绍：譬如要实现什么功能用什么参数之类的。作为以后的备查吧，就不用再到处搜索了。：）&lt;/p&gt;
&lt;p&gt;第一个命令介绍curl。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>iOS证书及推送相关概念</title>
      <link>https://blog.orchidflower.cn/2018/09/04/ios-push-and-certificate/</link>
      <pubDate>Tue, 04 Sep 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/09/04/ios-push-and-certificate/</guid>
      <description>&lt;h1 id=&#34;1i-os开发中碰到的概念&#34;&gt;1.i OS开发中碰到的概念&lt;/h1&gt;
&lt;h2 id=&#34;11-开发者账号&#34;&gt;1.1 开发者账号&lt;/h2&gt;
&lt;p&gt;苹果对开发者账号分为如下几类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;个人 Individual  （$99/year，可以上架Apple Store，最大UUID数目100）&lt;/li&gt;
&lt;li&gt;组织 Organizations。又可以写分为两类：
&lt;ul&gt;
&lt;li&gt;组织 Organization  （普通账号，$99/year，能够上传Apple Store，最大UUID数目100）&lt;/li&gt;
&lt;li&gt;企业账号 Enterprise Program  （企业账号，$299/year，能够进行企业发布，不能够发布到Apple Store，不限制UUID数目）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;教育机构（Educational Institutions）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;http://blog-cache.orchidflower.cn/15264592291888.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 08 - 日志</title>
      <link>https://blog.orchidflower.cn/2018/07/13/migrating-to-spring-boot-08-logging/</link>
      <pubDate>Fri, 13 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/07/13/migrating-to-spring-boot-08-logging/</guid>
      <description>&lt;p&gt;SpringBoot默认的日志配置通常来说足够满足要求：日志记录到控制台，也能够配置日志的级别，样式等等。但是其也有些不足：没有了之前logback提供的热更新日志配置的功能。&lt;/p&gt;
&lt;p&gt;logback有个非常好用的配置是“scan”，当“scan=true”的时候默认一分钟刷新一次配置。这样可以自动更新系统的日志级别。对于在线系统可以方便修改日志级别获取更加详细的日志，方便定位错误。这样可以保证服务不中断的情况下调整日志级别获取更多日志信息。但是默认的SpringBoot配置中不支持这种选项。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 07 - Redis发布订阅机制</title>
      <link>https://blog.orchidflower.cn/2018/07/09/migrating-to-spring-boot-07-Redis-Pub-Sub/</link>
      <pubDate>Mon, 09 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/07/09/migrating-to-spring-boot-07-Redis-Pub-Sub/</guid>
      <description>&lt;p&gt;Redis中的发布订阅机制（Pub/Sub）是基于channel这一概念的，这有些类似于Kafka中的基于topic的消息机制，只是不支持持久化。如果publish的消息，没有任何client处于&amp;quot;subscribe&amp;quot;状态，消息将会被丢弃。如果client在subcribe时，链接断开后重连，那么此期间的消息也将丢失。Redis server将会&amp;quot;尽力&amp;quot;将消息发送给处于subscribe状态的client，但是仍不会保证每条消息都能被正确接收。&lt;/p&gt;
&lt;p&gt;为了解耦发布者(publisher)和订阅者(subscriber)之间的关系，Redis 使用了 channel (频道)作为两者的中介：发布者将信息直接发布给 channel ，而 channel 负责将信息发送给适当的订阅者，发布者和订阅者之间没有相互关系，也不知道对方的存在。&lt;/p&gt;
&lt;p&gt;Spring Data Redis组件对Pub/Sub机制进行了抽象，提供了类似JMS的编程模式。Spring Data Redis使用了一个Container（RedisMessageListenerContainer）来解决发布订阅机制。这个Container使用一个Redis链接解决了多个topic订阅的问题。它把其他的订阅、发布者隔离成基本的POJO对象，而不用与Redis对象打交道。这简化了整个编程模型。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 06 - Swagger</title>
      <link>https://blog.orchidflower.cn/2018/07/06/migrating-to-spring-boot-06-swagger/</link>
      <pubDate>Fri, 06 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/07/06/migrating-to-spring-boot-06-swagger/</guid>
      <description>&lt;p&gt;随着技术的发展，现在的Web系统架构基本都由原来的后端渲染（例如JSP），变成了：前端渲染、前后端分离的形态。前端和后端的唯一联系，变成了API接口。API文档变成了前后端开发人员联系的纽带，变得越来越重要，swagger就是一款让你更好的书写API文档的框架。没有API文档工具之前，大家都是手写API文档的，在什么地方书写的都有，有在Wiki上写的，有在Word里面写的，也有在对应的项目目录下readme.md上写的，每个公司都有每个公司的玩法，无所谓好坏。另外还有专门针对API文档开发的应用，例如showdoc之类的。&lt;/p&gt;
&lt;p&gt;书写API文档的工具有很多，但是能称之为“框架”的，估计也只有swagger了。使用Swagger有个好处就是文档与代码结合紧密，更新代码的同时也会更新文档，不用担心同步的问题。而且在Java中使用Swagger也比较方便。&lt;/p&gt;
&lt;p&gt;云认证平台提供的Restful接口是基于CXF实现的。网上现有的关于Swagger的文档多数是基于Spring MVC的，并不适用于CXF。下面我将针对CXF+SpringBoot的组合如何使用Swagger进行介绍。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>SpringBoot中使用Jackson导致Long型数据精度丢失问题</title>
      <link>https://blog.orchidflower.cn/2018/06/22/Handling-Bigint-using-Jackson-in-Springboot/</link>
      <pubDate>Fri, 22 Jun 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/06/22/Handling-Bigint-using-Jackson-in-Springboot/</guid>
      <description>&lt;p&gt;数据库中有一个bigint类型数据，对应java后台类型为Long型，在某个查询页面中碰到了问题：页面上显示的数据和数据库中的数据不一致。例如数据库中存储的是：1475797674679549851，显示出来却成了1475797674679550000，后面几位全变成了0，精度丢失了。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Spring使用POI导出Excel内存溢出问题的解决（续）</title>
      <link>https://blog.orchidflower.cn/2018/06/15/Solving-OutOfMemoryException-Happened-when-Exporting-Excel-using-POI-in-Spring-Part2/</link>
      <pubDate>Fri, 15 Jun 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/06/15/Solving-OutOfMemoryException-Happened-when-Exporting-Excel-using-POI-in-Spring-Part2/</guid>
      <description>&lt;p&gt;上篇文章介绍了一个方法，解决了导出Excel过程中内存溢出的问题。但是有些问题还没有搞明白，那就是为什么要这样打开数据库游标？为什么fetchSize必须为：-2147483648？这里面涉及到数据库游标的更多信息，这一篇文章将深入介绍这方面内容。&lt;/p&gt;
&lt;p&gt;在数据库中，游标是一个十分重要的概念。游标提供了一种对从表中检索出的数据进行操作的灵活手段，就本质而言，游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标总是与一条SQL 选择语句相关联因为游标由结果集（可以是零条、一条或由相关的选择语句检索出的多条记录）和结果集中指向特定记录的游标位置组成。&lt;/p&gt;
&lt;p&gt;MySQL数据库游标通常有两种形式：Client Side Cursor（客户端游标）和Server Side Cursor（服务器端游标）。默认情况下，客户端游标会把整个结果集获取到客户端内存中，如果结果集太大，就会引发Out Of Memory错误；而服务器端游标会将结果集缓存在服务器端，客户端从服务器端分批获得结果集。&lt;/p&gt;
&lt;p&gt;MySQL默认是使用客户端游标的，因为通常情况下，程序处理的结果集不会特别大，对小结果集使用客户端游标效率更高：结果集一次性传输到客户端，客户端可以自行处理，服务器端也可以为其他客户端提供服务。但是针对大结果集，默认的客户端游标处理方式满足不了要求，针对这种情况，MySQL的Java客户端做了一个特殊的处理。下面参照官方帮助看一下。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Spring使用POI导出Excel内存溢出问题的解决</title>
      <link>https://blog.orchidflower.cn/2018/06/11/Solving-OutOfMemoryException-Happened-when-Exporting-Excel-using-POI-in-Spring/</link>
      <pubDate>Mon, 11 Jun 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/06/11/Solving-OutOfMemoryException-Happened-when-Exporting-Excel-using-POI-in-Spring/</guid>
      <description>&lt;p&gt;云认证平台提供将认证记录导出为Excel的功能。但是当业务量慢慢发展起来以后，就碰到一个比较棘手的问题：需要导出的认证记录太多，导出Excel的时候经常碰到服务器内存溢出问题。例如当要导出30w条记录的时候，服务端内存占用会超过2G，继续增加Heap空间不是一个非常合适的方案，因为无法预知一共需要多少内存。&lt;/p&gt;
&lt;p&gt;因此，这两天特意找了一下解决方案，终于有了解决方案。最终方案导出256w条记录的时候，服务器内战占用1.6G，不再继续增加。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 05 - 事务管理</title>
      <link>https://blog.orchidflower.cn/2018/06/01/migrating-to-spring-boot-05-transaction-management/</link>
      <pubDate>Fri, 01 Jun 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/06/01/migrating-to-spring-boot-05-transaction-management/</guid>
      <description>&lt;p&gt;Spring项目中使用数据库的方式多种多样，注入MyBatis、JDBC、Hibernate等等都是支持的。之前的系统是基于MyBatis的。&lt;/p&gt;
&lt;p&gt;关于如何Spring Boot和MyBatis网上有很多文章，可以参考。有时间我也会专门写一篇介绍集成的过程。本文讲的就是MyBatis移植到Spring Boot方面碰到的一些问题，主要是事务控制方面的。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 04 - Redis</title>
      <link>https://blog.orchidflower.cn/2018/05/24/migrating-to-spring-boot-04-Redis/</link>
      <pubDate>Thu, 24 May 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/05/24/migrating-to-spring-boot-04-Redis/</guid>
      <description>&lt;p&gt;相比于Spring来说，在SpringBoot中使用Redis大幅简化了。通过使用&lt;code&gt;spring-boot-starter-data-redis&lt;/code&gt;，使用Redis变得非常简单。&lt;/p&gt;
&lt;p&gt;基本步骤如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;添加依赖&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-data-redis&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;配置application.properties/yaml&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spring&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;redis&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;host&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;192.168.2.230&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;port&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;6379&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;password&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;xxxxxx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;database&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;timeout&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3000ms&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;注入RedisTemplate使用&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75af00&#34;&gt;@Autowired&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#111&#34;&gt;StringRedisTemplate&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;stringRedisTemplate&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;就是这么简单。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 03 - Servlet和Filter</title>
      <link>https://blog.orchidflower.cn/2018/05/18/migrating-to-spring-boot-03-Servlet-Filter/</link>
      <pubDate>Fri, 18 May 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/05/18/migrating-to-spring-boot-03-Servlet-Filter/</guid>
      <description>&lt;p&gt;原先云认证中有几个特殊加载的组件：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;checkingServlet&lt;/code&gt;&lt;/strong&gt;：一个Servlet，用于检查系统的状态，主要用于负载均衡LB检测服务是否正常使用。该Servlet定义了了一组URL，可以用来检查系统的状态，例如：/checking/database（检查数据库是否可以访问），/checking/version（返回系统版本号），/checking（总体检查系统状态）等。这些功能理论上不适用Servlet也能够实现，但是由于历史原因采用了Servlet，这次一直也不考虑重新编写。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ClientCertificateFromProxyFilter&lt;/code&gt;&lt;/strong&gt;：一个Filter，用于检查负载均衡转发过来的客户端证书，配合Spring Security完成双向SSL的认证工作。&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 02 - 异常处理</title>
      <link>https://blog.orchidflower.cn/2018/05/15/migrating-to-spring-boot-02-Exception-Handler/</link>
      <pubDate>Tue, 15 May 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/05/15/migrating-to-spring-boot-02-Exception-Handler/</guid>
      <description>&lt;p&gt;首先说一下背景信息。云认证平台是一个传统的Spring项目，从上到下可以分为：API层（对应Spring Controller）、Service层、DAO层（MyBatis）几层。为了方便处理，从开发规范上我们要求了Service层的异常在Service层自行处理。&lt;/p&gt;
&lt;p&gt;为了实现这一点，在接口定义上，从API层调用Service层的请求会有统一的返回基类：&lt;code&gt;CommonResult&lt;/code&gt;。其定义如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#00a8c8&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#75af00&#34;&gt;CommonResult&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;implements&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Serializable&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;long&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;serialVersionUID&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1L&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * success 请求成功与否的标志。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;boolean&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;success&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Boolean&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;FALSE&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * resultCode 返回码。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;resultCode&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * message 详细信息。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;message&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;所有需要从API层调用到的Service层的返回值都是该类或者该类的子类。如果是Service层之间互相调用，则不受此限制。&lt;/p&gt;
&lt;p&gt;本章的内容主要与AOP有关。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 01 - 插件加载</title>
      <link>https://blog.orchidflower.cn/2018/05/09/migrating-to-spring-boot-01-loading-plugin/</link>
      <pubDate>Wed, 09 May 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/05/09/migrating-to-spring-boot-01-loading-plugin/</guid>
      <description>&lt;p&gt;首先简单说一下云平台的业务功能：&lt;em&gt;云平台上提供了多种多样的服务，这些服务可能来源于不同的供应商。也就是说对于某一种服务来说，可能会有多个供应商提供相同的服务；而对于某一个供应商来说，它可能提供多种服务。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;之前的云平台中有一个插件机制，使用插件机制解决了供应商与系统的耦合度问题。系统抽象了服务层，服务层在合适的时机加载插件以调用供应商的服务。&lt;/p&gt;
&lt;p&gt;加载相关的代码大概类似这样：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#111&#34;&gt;ClassLoader&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;localClassLoader&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;Thread&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;currentThread&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;().&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;getContextClassLoader&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#00a8c8&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;str&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;providerClassNames&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#00a8c8&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#111&#34;&gt;Class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;localClass&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;localClassLoader&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;loadClass&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;str&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#111&#34;&gt;XXXServiceProvider&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;localProvider&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;XXXServiceProvider&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;localClass&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;newInstance&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#111&#34;&gt;localProvider&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;initial&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;();&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 初始化插件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#00a8c8&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;Exception&lt;/span&gt; &lt;span style=&#34;color:#111&#34;&gt;e&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;providerClassNames是一个数组，其中并所有插件的主类名字。通过获取到的ClassLoader，对插件主类进行加载，从而获得插件对象。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移到SpringBoot 00 - 背景介绍</title>
      <link>https://blog.orchidflower.cn/2018/05/08/migrating-to-spring-boot-00-background/</link>
      <pubDate>Tue, 08 May 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/05/08/migrating-to-spring-boot-00-background/</guid>
      <description>&lt;p&gt;最近因为发布方面的原因，需要对项目进行一次改造，趁着这次机会，对云平台项目进行了彻底的重构，迁移到了Spring Boot上。改造过程中，从传统的Spring项目迁移到Spring Boot上，还是碰到了一些问题的，也因此留下了这个系列的笔记。其中的内容，应该对希望把传统的Spring项目迁移到Spring Boot的人会有所帮助。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Apache HttpClient 使用（上）</title>
      <link>https://blog.orchidflower.cn/2018/04/23/Apache-HttpClient-Manual/</link>
      <pubDate>Mon, 23 Apr 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/04/23/Apache-HttpClient-Manual/</guid>
      <description>&lt;p&gt;HttpClient是Apache Jakarta Common下的子项目，用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包，并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中，比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。&lt;/p&gt;
&lt;p&gt;目前最新的版本是4.5，支持HTTP 1.0/HTTP 1.1协议。正在开发中的5.0版本（还在Beta阶段）支持HTTP/2协议。&lt;/p&gt;
&lt;h1 id=&#34;1-特性&#34;&gt;1. 特性&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;基于标准、纯净的java语言。实现了Http1.0和Http1.1&lt;/li&gt;
&lt;li&gt;以可扩展的面向对象的结构实现了Http全部的方法（GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE）。&lt;/li&gt;
&lt;li&gt;支持HTTPS协议。&lt;/li&gt;
&lt;li&gt;通过Http代理建立透明的连接。&lt;/li&gt;
&lt;li&gt;利用CONNECT方法通过Http代理建立隧道的https连接。&lt;/li&gt;
&lt;li&gt;Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。&lt;/li&gt;
&lt;li&gt;插件式的自定义认证方案。&lt;/li&gt;
&lt;li&gt;便携可靠的套接字工厂使它更容易的使用第三方解决方案。&lt;/li&gt;
&lt;li&gt;连接管理器支持多线程应用。支持设置最大连接数，同时支持设置每个主机的最大连接数，发现并关闭过期的连接。&lt;/li&gt;
&lt;li&gt;自动处理Set-Cookie中的Cookie。&lt;/li&gt;
&lt;li&gt;插件式的自定义Cookie策略。&lt;/li&gt;
&lt;li&gt;Request的输出流可以避免流中内容直接缓冲到socket服务器。&lt;/li&gt;
&lt;li&gt;Response的输入流可以有效的从socket服务器直接读取相应内容。&lt;/li&gt;
&lt;li&gt;在http1.0和http1.1中利用KeepAlive保持持久连接。&lt;/li&gt;
&lt;li&gt;直接获取服务器发送的response code和 headers。&lt;/li&gt;
&lt;li&gt;设置连接超时的能力。&lt;/li&gt;
&lt;li&gt;实验性的支持http1.1 response caching。&lt;/li&gt;
&lt;li&gt;源代码基于Apache License 可免费获取。&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    
    <item>
      <title>Apache HttpClient 使用（下）</title>
      <link>https://blog.orchidflower.cn/2018/04/23/Apache-HttpClient-Manual-Part2/</link>
      <pubDate>Mon, 23 Apr 2018 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2018/04/23/Apache-HttpClient-Manual-Part2/</guid>
      <description>&lt;h1 id=&#34;4-链接池&#34;&gt;4. 链接池&lt;/h1&gt;
&lt;p&gt;通常我们可以使用&lt;code&gt;PoolingHttpClientConnectionManager&lt;/code&gt;来创建一个链接池。&lt;/p&gt;
&lt;h2 id=&#34;41-对于链接池的管理&#34;&gt;4.1 对于链接池的管理&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;// 设置最大连接数  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;cm.setMaxTotal(200);  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;// 设置每个主机地址的并发数  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;cm.setDefaultMaxPerRoute(20);  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;// 通过PoolingHttpClientConnectionManager，来获取CloseableHttpClient  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;// 创建http GET请求  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;HttpGet httpGet = new HttpGet(&amp;#34;http://www.baidu.com/&amp;#34;);    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;// 执行请求  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;response = httpClient.execute(httpGet);    
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>在线API列表</title>
      <link>https://blog.orchidflower.cn/onlineapis/</link>
      <pubDate>Sat, 27 Jan 2018 09:17:30 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/onlineapis/</guid>
      <description>经常需要去网上找各种开源项目的帮助，在此特意列一个列表，方便以后查找。随时更新。 1. Java 1.1 Spring SpringBoot Reference Spring Framework 4.x Reference Spring Framework 5.x Reference Spring data redis documentation Springfox Reference documentation 1.2 MyBatis MyBatis Introduction MyBatis Generator Documentation 2. Golang</description>
    </item>
    
    <item>
      <title>Spring应用因Session Timeout设置引起的GC问题</title>
      <link>https://blog.orchidflower.cn/2017/08/29/Spring-Session-Timeout-caused-GC-failure/</link>
      <pubDate>Tue, 29 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/08/29/Spring-Session-Timeout-caused-GC-failure/</guid>
      <description>&lt;p&gt;最近在客户的要求下，对系统进行了压测。自己压测的时候一切指标都挺正常。但是客户却反馈说压测的时候有时候会碰到性能衰减很厉害，不稳定。于是有了下面这次的排查过程。客户反馈说问题是发生在多次连续压测之后碰到的，所以进行了一系列的测试。&lt;/p&gt;
&lt;p&gt;先说一下测试环境的一些信息：测试主机是阿里云的ECS，配置是2C + 16G。为了方便，数据库采用的是Docker搭建的，版本是5.6.X。另外，这台机器上还安装了Zookeeper 3.4.X 和Kafka 1.0。系统本身是一个标准的Spring + CXF的应用，提供给客户使用的服务是标准的Restful接口。&lt;/p&gt;
&lt;h1 id=&#34;1-重现问题&#34;&gt;1. 重现问题&lt;/h1&gt;
&lt;p&gt;因为客户反馈是多次压测之后碰到的，因此首先尝试连续压测多次看看能不能重现问题。为了可能存在的数据库性能问题，临时申请了RDS作为数据库；另外为了尽快发现问题，将程序占用内存缩小到1G。这次测试测出了客户所说的问题，通过jconsole监控也发现了问题原因，应该是因为GC导致的。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://blog-cache.orchidflower.cn/15035654400984.jpg&#34; alt=&#34;&#34;&gt;
看图表可以发现，压测5~6分钟之后，Java的GC占用了大量的CPU时间（左上图中的蓝色线），而且内存占用一直居高不下（右上图）。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>使用Docker运行Jenkins（二）</title>
      <link>https://blog.orchidflower.cn/2017/08/20/Use-Webhook-between-Gogs-and-Jenkins/</link>
      <pubDate>Sun, 20 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/08/20/Use-Webhook-between-Gogs-and-Jenkins/</guid>
      <description>&lt;p&gt;Gitea 是一款极易搭建的自助 Git 服务，最初是fork子Gogs项目（Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务）。Gitea使用 Go 语言开发。使用 Go 语言开发使得 Gitea 能够通过独立的二进制分发，并且支持 Go 语言支持的 所有平台，包括 Linux、Mac OS X、Windows 以及 ARM 平台。&lt;/p&gt;
&lt;p&gt;Gitea占用资源小，比起Gitlab这种庞然大物来说简直是精致得要命。但是作为小团队的项目管理用来替代Gitlab还是基本能够满足需求的。而且Gitea（包括Gogs）社区还是挺活跃的，新功能也在逐渐增加中，个人很看好它的前景。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>使用Docker运行Jenkins服务（一）</title>
      <link>https://blog.orchidflower.cn/2017/08/13/How-to-setup-Jenkins-in-Docker/</link>
      <pubDate>Sun, 13 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/08/13/How-to-setup-Jenkins-in-Docker/</guid>
      <description>&lt;h1 id=&#34;1-jenkins是什么&#34;&gt;1. Jenkins是什么？&lt;/h1&gt;
&lt;p&gt;某百科的解释是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Jenkins是一个开源软件项目，是基于Java开发的一种持续集成工具，用于监控持续重复的工作，旨在提供一个开放易用的软件平台，使软件的持续集成变成可能。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个解释大体上是靠谱的，Jenkins的核心作用就是一个CI（持续集成）工具。CI的概念是：持续集成指的是，频繁地（一天多次）将代码集成到主干。持续集成的目的，就是让产品可以快速迭代，同时还能保持高质量。它的核心措施是，代码集成到主干之前，必须通过自动化测试。只要有一个测试用例失败，就不能集成。而Jenkins能够完成这些自动化构建、测试的大部分工作。&lt;/p&gt;
&lt;p&gt;Jenkins的前身是Hudson。这其中的渊源涉及到Oracle收购Java引起的版权纷争。有兴趣的可以看附录里面的相关链接。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Shell脚本中的一些特殊变量</title>
      <link>https://blog.orchidflower.cn/2017/08/05/Some-special-parameters-in-Shell/</link>
      <pubDate>Sat, 05 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/08/05/Some-special-parameters-in-Shell/</guid>
      <description>&lt;p&gt;Shell脚本的一些参数总是感觉记不住，特此记录一下，以备后查。&lt;/p&gt;
&lt;h1 id=&#34;1-参数说明&#34;&gt;1. 参数说明&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;当前脚本的文件名&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;mdash;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;&amp;mdash;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$n&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;传递给脚本或函数的参数。n 是一个数字，表示第几个参数。例如，第一个参数是$1，第二个参数是$2。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$#&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;传递给脚本或函数的参数个数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$*&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;传递给脚本或函数的所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$@&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;传递给脚本或函数的所有参数。被双引号(&amp;quot; &amp;ldquo;)包含时，与 $* 稍有不同，下面将会讲到。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$?&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;上个命令的退出状态，或函数的返回值。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$$&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;当前Shell进程ID。对于 Shell 脚本，就是这些脚本所在的进程ID。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
    </item>
    
    <item>
      <title>xargs使用复杂参数</title>
      <link>https://blog.orchidflower.cn/2017/07/30/How-to-using-argument-in-xargs/</link>
      <pubDate>Sun, 30 Jul 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/07/30/How-to-using-argument-in-xargs/</guid>
      <description>&lt;p&gt;一般情况下xargs只处理一个参数，因此可以这样使用，最后的rm会自动补齐一个参数：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;find . | grep hello | xargs rm
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;但是有时候需要多个参数才能够正常运行，这时候怎么办呢？可以这样：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;ls -1 2016*.log | xargs -I % -t tar czvf %.tar.gz % --remove-files
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上述命令的意思是将当前目录中所有&lt;code&gt;2016*.log&lt;/code&gt;文件使用tar打包成tar.gz文件，并删除源文件。其中：&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>如何无密码登录SSH</title>
      <link>https://blog.orchidflower.cn/2017/07/23/How-to-login-without-password-over-SSH/</link>
      <pubDate>Sun, 23 Jul 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/07/23/How-to-login-without-password-over-SSH/</guid>
      <description>&lt;p&gt;我们在用&lt;code&gt;Jenkins&lt;/code&gt;做发布工具的时候，经常用到的功能是通过&lt;code&gt;SSH&lt;/code&gt;通道完成各种功能。例如使用&lt;code&gt;scp&lt;/code&gt;命令拷贝安装包到服务器上，通过&lt;code&gt;ssh -t&lt;/code&gt;命令执行服务器上的脚本等。&lt;/p&gt;
&lt;p&gt;这时就需要配置无密码登录，否则无法做到自动执行命令。如果每次都手动输入密码，想想都不现实。要实现无密码登录，需要配置好SSH允许证书登录。&lt;/p&gt;
&lt;p&gt;其原理是使用了公钥体系，假设有服务器Server，用户在服务器Client上，用户在服务器Client上有私钥Private Key，在服务器Server上有对应的公钥Public Key。这样访问的时候Server就能够通过公钥体系进行验证：要求用户使用其私钥进行签名，从而确保用户拥有私钥，以此验证用户身份。如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://blog-cache.orchidflower.cn/mweb/sshauthentication.png&#34; alt=&#34;公钥体系原理图&#34;&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在alias命令中使用单引号</title>
      <link>https://blog.orchidflower.cn/2017/07/16/How-to-using-single-quota-in-alias-command/</link>
      <pubDate>Sun, 16 Jul 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/07/16/How-to-using-single-quota-in-alias-command/</guid>
      <description>&lt;p&gt;Linux中的alias命令可以将一条复杂的命令缩短为一个简单的指令，实际工作中经常会用到。使用alias的时候命令本身需要使用单引号包括起来。但是如果命令本身中包含单引号怎么办呢？&lt;/p&gt;
&lt;p&gt;例如，下面这条命令：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;ps -ef &lt;span style=&#34;color:#111&#34;&gt;|&lt;/span&gt; grep shadowsocks/server.py &lt;span style=&#34;color:#111&#34;&gt;|&lt;/span&gt; grep -v grep &lt;span style=&#34;color:#111&#34;&gt;|&lt;/span&gt; awk &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其作用是获取任务的pid。其中用到的&lt;code&gt;awk&lt;/code&gt;的参数需要用到单引号。alias也可以使用双引号，但是如果用双引号，其中的内容会被转义解释成具体获得的值。而不是命令本身。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>如何在Mac上添加一个虚拟IP</title>
      <link>https://blog.orchidflower.cn/2017/07/09/How-to-add-one-virtual-IP-on-Mac/</link>
      <pubDate>Sun, 09 Jul 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/07/09/How-to-add-one-virtual-IP-on-Mac/</guid>
      <description>&lt;p&gt;最近忙着系统重构，因为经常处于移动办公的状态，访问公司的服务器不是很方便，所以一些基础服务都是搭建在本机上。但是使用的时候碰到了一些问题，最大的问题是网络地址切换导致的：IP地址总是不固定。有些服务（例如FastDFS）需要有明确的IP地址来绑定服务。不固定的IP地址会给这些服务带来麻烦，需要修改配置重启服务。
这种情况下，最好的解决办法是能够给Mac分配一个固定的IP，不管怎么切换网络一直存在。幸好这个是可以解决的，而且并不复杂。方法如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;ifconfig lo0 alias 192.168.255.199
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其原理是给网络设备loopback增加一个alias。loopback设备一直存在，而且与en0设备独立，可以一直存在。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Let&#39;s Encrypt免费证书的使用</title>
      <link>https://blog.orchidflower.cn/2017/07/02/How-to-use-Let-s-Encrypt/</link>
      <pubDate>Sun, 02 Jul 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/07/02/How-to-use-Let-s-Encrypt/</guid>
      <description>&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;因为云认证服务的商户认证体系是基于双向&lt;code&gt;SSL&lt;/code&gt;的，如果服务器端没有启用&lt;code&gt;SSL&lt;/code&gt;证书，则整个认证体系必须重构。目前的现状是申请&lt;code&gt;SSL&lt;/code&gt;证书费用比较高（一年2-3w），而且周期比较长，赶不上目前的测试进度。所以只能使用免费证书来支撑一下了。&lt;/p&gt;
&lt;p&gt;免费证书服务提供商据我所知有几个：&lt;code&gt;Let&#39;s Encrypt&lt;/code&gt;, &lt;code&gt;StartSSL&lt;/code&gt;, &lt;code&gt;StarCom&lt;/code&gt;。但是&lt;code&gt;StartSSL&lt;/code&gt;, &lt;code&gt;StarCom&lt;/code&gt;前一阵子被&lt;code&gt;Chrome&lt;/code&gt;、&lt;code&gt;Firefox&lt;/code&gt;等设置为不可信（签名流程不规范，不符合安全监管要求之类的原因），因此目前可选的只有&lt;code&gt;let&#39;s encrypt&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Let&#39;s Encrypt&lt;/code&gt;是国外一个公共的免费 &lt;code&gt;SSL&lt;/code&gt; 项目，由 &lt;code&gt;Linux&lt;/code&gt; 基金会托管，它的来头不小，由&lt;code&gt;Mozilla&lt;/code&gt;、思科、&lt;code&gt;Akamai&lt;/code&gt;、&lt;code&gt;IdenTrust&lt;/code&gt;和&lt;code&gt;EFF&lt;/code&gt;等组织发起，目的就是向网站自动签发和管理免费证书，以便加速互联网由 &lt;code&gt;HTTP&lt;/code&gt; 过渡到 &lt;code&gt;HTTPS&lt;/code&gt;。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Kafka介绍与使用</title>
      <link>https://blog.orchidflower.cn/2017/06/25/How-to-use-Kafka/</link>
      <pubDate>Sun, 25 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/06/25/How-to-use-Kafka/</guid>
      <description>&lt;p&gt;Apache Kafka是分布式发布-订阅消息系统。它最初由LinkedIn公司开发，之后成为Apache项目的一部分。Kafka是一种快速、可扩展的、设计内在就是分布式的，分区的和可复制的提交日志服务。
Apache Kafka与传统消息系统相比，有以下不同：&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;它将消息持久化到磁盘，因此可用于批量消费，例如ETL，以及实时应用程序。&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>在Ubuntu 16.04 LTS上设置DOCKER_OPTS</title>
      <link>https://blog.orchidflower.cn/2017/06/22/Using-DOCKER-OPTS-on-Ubuntu-16-04-LTS/</link>
      <pubDate>Thu, 22 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/06/22/Using-DOCKER-OPTS-on-Ubuntu-16-04-LTS/</guid>
      <description>&lt;p&gt;之前一直使用&lt;code&gt;Ubuntu 14.04&lt;/code&gt;来跑Docker。今天在16.04 LTS上跑Docker的时候发现设置&lt;code&gt;DOCKER_OPTS&lt;/code&gt;的时候有些区别，特此记录一下。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在Mac上运行SOAPUI 5.3.0</title>
      <link>https://blog.orchidflower.cn/2017/06/21/Running-SOAPUI-5-3-0-on-Mac-OSX/</link>
      <pubDate>Wed, 21 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/06/21/Running-SOAPUI-5-3-0-on-Mac-OSX/</guid>
      <description>&lt;h1 id=&#34;0-前言&#34;&gt;0. 前言&lt;/h1&gt;
&lt;p&gt;Mac上找不到特别好的SOAP Webservice测试工具。以前用过SOAP UI，感觉很好。但是SOAP UI在Mac上安装有些问题。特此记录一下安装过程。&lt;/p&gt;
&lt;p&gt;SoapUI目前最新的版本是5.3.0，目前已经开源。SmartBear在SOAP UI之后发布了新版本更名为SOAPUI NG。SOAPUI NG体积大了很多，而且功能更加繁琐，个人感觉还不如以前的版本好用。SoapUI以前收费，到了5.2.1以后版本就开源并且免费了。&lt;/p&gt;
&lt;p&gt;SoapUI在Mac会出现无响应的现象：界面能够打开，但是画面卡住，鼠标显示成旋转彩球，无法操作。要正常使用需要修改一下才行。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在Mac上如何安装FastDFS</title>
      <link>https://blog.orchidflower.cn/2017/06/18/How-to-install-FastDFS-on-Mac/</link>
      <pubDate>Sun, 18 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/06/18/How-to-install-FastDFS-on-Mac/</guid>
      <description>&lt;p&gt;项目中用到了FastDFS来做文件存储。最近重构的时候，因为经常处于移动办公的状态，所以访问公司的服务器不是很方便，所以感觉有必要在本机上搭建一套FastDFS的测试环境。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;FastDFS是什么？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;FastDFS是一个开源的轻量级分布式文件系统，它对文件进行管理，功能包括：文件存储、文件同步、文件访问（文件上传、文件下载）等，解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务，如相册网站、视频网站等等。
FastDFS为互联网量身定制，充分考虑了冗余备份、负载均衡、线性扩容等机制，并注重高可用、高性能等指标，使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
FastDFS里面有两种角色：Tracker、Storage。Tracker主要做调度工作，在访问上起负载均衡的作用。Storage存储节点存储文件，完成文件管理的所有功能：存储、同步和提供存取接口，FastDFS同时对文件的meta data进行管理。所谓文件的meta data就是文件的相关属性，以键值对（key value pair）方式表示，如：width=1024，其中的key为width，value为1024。文件meta data是文件属性列表，可以包含多个键值对。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;</description>
    </item>
    
    <item>
      <title>Nginx配置导致的SSL证书认证失败</title>
      <link>https://blog.orchidflower.cn/2017/06/03/SSL-Authentication-Failure-caused-by-Nginx-Proxy/</link>
      <pubDate>Sat, 03 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/06/03/SSL-Authentication-Failure-caused-by-Nginx-Proxy/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;注： 这是在之前博客上发过的文章，在实际使用中经常会有人碰到，特意转贴过来。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;目前公司对外开放了一个云服务平台，提供一些功能供商户接入使用。整个项目的架构是基于Spring + MyBatis的。另外，商户端的服务接口是基于SOAP WebService的，这部分使用CXF实现。
安全方面采用了Spring Security，可以对商户提供证书认证或密码认证。但是出于安全考虑，目前只开放了证书认证。为了使用证书认证商户，我们创建了一个自签名的CA，用来生成商户使用的客户端证书。在验证上，使用Nginx验证客户端证书是否是指定CA产生的。另外，为了防止被作废的证书（例如给商户颁发了新证书后，原证书应该作废，但是原证书也是由指定CA产生的）再次使用，在代码层面对证书进行了进一步的验证（这一点是通过Nginx将客户端证书作为Header传递到Java后台实现的，有时间以后再讲）。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>DelegatingFilterProxy源码分析</title>
      <link>https://blog.orchidflower.cn/2017/06/02/The-source-code-of-DelegatingFilterProxy/</link>
      <pubDate>Fri, 02 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/06/02/The-source-code-of-DelegatingFilterProxy/</guid>
      <description>&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter-name&amp;gt;&lt;/span&gt;springSecurityFilterChain&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter-name&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter-class&amp;gt;&lt;/span&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter-class&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter-mapping&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter-name&amp;gt;&lt;/span&gt;springSecurityFilterChain&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter-name&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;url-pattern&amp;gt;&lt;/span&gt;/documentation/*&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/url-pattern&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter-mapping&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;用过Spring Security的人都会熟悉以上代码，一般教程上都会说明，使用Spring Security就需要在web.xml中指定以上代码。从这个配置中，可能会给我们造成一个错觉，以为DelegatingFilterProxy类就是springSecurity的入口，但其实这个类位于spring-web这个jar下面，说明这个类本身是和springSecurity无关。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>使用Docker&#43;Apache2&#43;WebSVN搭建SVN服务器</title>
      <link>https://blog.orchidflower.cn/2017/05/26/Running-SVN-Server-using-Docker-Apache2-WebSVN/</link>
      <pubDate>Fri, 26 May 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/05/26/Running-SVN-Server-using-Docker-Apache2-WebSVN/</guid>
      <description>&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;虽然现在的SVN已经用的越来越少，很多人都切换到了Git上。但是以前的一些历史项目还是需要SVN支持的。
之前的SVN服务器是直接搭建在一台Ubuntu服务器上的。当时一起搭建了WebSVN。也曾经研究过怎么搭建WebSVN，但是现在也不能够工作了，时间长久了也忘了怎么搭建了。所以想研究一下怎么使用Docker来完成一样的工作。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在Tomcat中使用ThreadLocal以及Session</title>
      <link>https://blog.orchidflower.cn/2017/05/04/ThreadLocal-and-Session-in-Tomcat/</link>
      <pubDate>Thu, 04 May 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/05/04/ThreadLocal-and-Session-in-Tomcat/</guid>
      <description>&lt;p&gt;最近运营同事在管理平台（生产环境）上碰到一个问题：登录之后会莫名其妙地变成未登录状态，被踢回登录页面。&lt;/p&gt;
&lt;p&gt;管理平台使用的Spring MVC框架实现的后台接口，React实现的前台页面。之前引入React的时候已经做过前后端分离。但是当时考虑到技术栈的原因，没有对登录体系进行彻底改造，没有引入AccessToken来维护登录状态，依然保留了Java的Session机制。考虑到管理平台属于内部使用，访问量不大，因此直接在Nginx层使用iphash进行了Session粘滞，确保同一个用户的请求总是被同一个的后台Tomcat处理，这样就可以使用传统的session机制保持用户登录状态。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Java SSL握手记录分析</title>
      <link>https://blog.orchidflower.cn/2017/04/28/Java-SSL-Handshake-Log/</link>
      <pubDate>Fri, 28 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/04/28/Java-SSL-Handshake-Log/</guid>
      <description>&lt;p&gt;公司项目当中经常使用CXF库连接WebService服务，而且我们自己提供的服务也是基于CXF的SOAP服务，经常需要指导客户怎么连接我们的服务。CXF库整个体系架构比较庞大，相关的类、知识点都比较多。尤其是连接SSL双向认证服务的时候，经常碰到问题。&lt;/p&gt;
&lt;p&gt;使用双向SSL认证的时候，在Spring中配置起来非常简单，但是一旦出错就比较难找问题。经过多次尝试，最后发现还是分析SSL握手记录比较靠谱，比较容易找出真正的问题所在。特此记录一下自己的一些心得，以作备忘并希望能够帮到其他人。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>通过Zabbix监控业务数据（续）</title>
      <link>https://blog.orchidflower.cn/2017/04/20/Monitoring-data-in-mysql-using-Zabbixpart2/</link>
      <pubDate>Thu, 20 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/04/20/Monitoring-data-in-mysql-using-Zabbixpart2/</guid>
      <description>&lt;p&gt;昨天配置好报警条件之后，今天早上检查发现昨天晚上发出了报警。但是看上去像是误报。
在凌晨2:44:02触发了警报，然后在2:44:32警报解除，持续时间30秒。如下两图：
&lt;img src=&#34;http://blog-cache.orchidflower.cn/14926526126564.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://blog-cache.orchidflower.cn/14926526236724.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;从感觉上像是误报。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>通过Zabbix监控业务数据</title>
      <link>https://blog.orchidflower.cn/2017/04/19/Monitoring-data-in-mysql-in-Zabbix/</link>
      <pubDate>Wed, 19 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/04/19/Monitoring-data-in-mysql-in-Zabbix/</guid>
      <description>&lt;p&gt;为了事后分析服务质量，我们的云认证系统将商户访问记录保存到了数据库中（MySQL）。在日志中我们记录了商户每次访问的返回结果，耗费时间等信息。通过这些信息我们可以分析发现服务什么时候性能比较低，什么时候处理效果比较差。&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;/ul&gt;
&lt;p&gt;鉴于此，一直想对这个报警体系进行改造，最后选择通过Zabbix实现这个功能。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在Linode节点上开启BBR算法</title>
      <link>https://blog.orchidflower.cn/2017/04/17/Enable-BBR-on-Linode/</link>
      <pubDate>Mon, 17 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/04/17/Enable-BBR-on-Linode/</guid>
      <description>&lt;p&gt;BBR是Google开源的TCP拥堵控制算法，与2016年9月开源。BBR的目的是要尽量跑满带宽, 并且尽量不要有排队的情况, 其使用效果并不比速锐差。&lt;/p&gt;
&lt;p&gt;Linux kernel 4.9+ 已支持 tcp_bbr。我在Linode安装了4.10.10内核，可以开启BBR。但是Linode自带的4.9无法开启。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在VSCode中为Vue.js开发启用静态类型检查Flow</title>
      <link>https://blog.orchidflower.cn/2017/04/11/Using-flow-js-for-vue-in-VSCode/</link>
      <pubDate>Tue, 11 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/04/11/Using-flow-js-for-vue-in-VSCode/</guid>
      <description>&lt;p&gt;众所周知，Javascript是一种弱类型（或者称为动态类型）语言，即变量的类型是不确定的。例如，下面代码中的&lt;code&gt;temp&lt;/code&gt;一开始是字符串，后来又变成了数字：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;temp&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#d88200&#34;&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75af00&#34;&gt;temp&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#111&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;弱类型语言变量类型完全由当时的值决定，所以称为“弱类型”。这样设计有其好处，可以写出非常简洁的代码。但是在构建大型项目的时候，无法在编译期发现问题会导致很难发现问题，反而会为程序员带来非常大的负担。这实际上限制了JS项目的规模，无法开发过于复杂的项目。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Node.js 使用Redis发布订阅模式</title>
      <link>https://blog.orchidflower.cn/2017/03/30/Nodejs-using-redis-publish-subscribe/</link>
      <pubDate>Thu, 30 Mar 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/03/30/Nodejs-using-redis-publish-subscribe/</guid>
      <description>&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;最近在用Node.js做一个管理系统的时候碰到了一个场景：为了访问性能，系统在内存中（不是Redis）缓存了一些常用数据，例如系统菜单树之类的。但是什么时候刷新这些缓存就成了问题。当然在单服务器模式下也不是大问题，只要在更新数据的时候删除内存中的缓存数据即可。但是这一方法在分布式服务中就无效了：同时会有多个这种系统在跑，但是只有一台服务器接到了处理请求，其他服务器根本没有办法刷新内存中的数据。
当然有人会说将缓存放到Redis中不就解决问题了？但是如果数据量稍大一些，而且访问频繁、更新却不频繁，放到Redis中每次访问都会对Redis带来不小的压力，显得很没有必要。
这种情况下，自然就可以使用Redis的发布订阅机制来解决问题了：当数据更新之后，只要发布一个消息到Redis，所有服务器都可以收到消息，执行刷新缓存的操作了。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Docker for Mac磁盘性能低下的解决办法</title>
      <link>https://blog.orchidflower.cn/2017/03/29/Performance-regression-on-Docker-for-Mac/</link>
      <pubDate>Wed, 29 Mar 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/03/29/Performance-regression-on-Docker-for-Mac/</guid>
      <description>&lt;p&gt;最近备份恢复Gogs的时候，发现同样的配置参数在Mac上访问Gogs的用户首页特别慢，大概耗时8秒，而在Linux上面运行的时候不到1秒钟。后来就上网搜索，加上自己试验，最后找到了原因应该是Gogs镜像本身的问题（可能是采用了alpine这一内核，但是具体原因不详，有待进一步实验）。&lt;/p&gt;
&lt;p&gt;这个过程中曾经怀疑是Docker运行MySQL过慢的原因，虽然最终发现不是，但是搜索过程中发现了Docker for Mac确实有性能问题，那就是对大量磁盘IO的操作性能会非常差，大概会差10倍。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Electron开发使用Vue Devtools</title>
      <link>https://blog.orchidflower.cn/2017/03/29/Using-Vue-Devtools-in-Electron/</link>
      <pubDate>Wed, 29 Mar 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/03/29/Using-Vue-Devtools-in-Electron/</guid>
      <description>&lt;p&gt;最近在用Electron + Vue.js 2.0写一个桌面工具。使用下来感觉Electron用起来还是挺爽的。之前为了开发跨平台的桌面应用，我曾经用过Python+wxPython，Swing，SWT等各种技术，但是都有这样那样的问题（例如打包比较麻烦、界面各平台不太一致等）。而Electron基于目前成熟的前端技术，通过内嵌的浏览器内核实现了统一的表现形式，这一点用于做跨平台开发真是太方便了。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在Ubuntu 14.04上安装Docker 17.03.0-ce</title>
      <link>https://blog.orchidflower.cn/2017/03/28/install-docker-17-03-0-ce-on-ubuntu-14-04/</link>
      <pubDate>Tue, 28 Mar 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/03/28/install-docker-17-03-0-ce-on-ubuntu-14-04/</guid>
      <description>&lt;h1 id=&#34;0-概述&#34;&gt;0. 概述&lt;/h1&gt;
&lt;p&gt;Docker在1.13.x版本之后更新了版本号规则，区分了社区版和企业版。这导致了安装方式有所变化。所以特意参考官方的帮助重新整理了一下安装步骤。&lt;/p&gt;
&lt;p&gt;适应范围：Ubuntu 14.04。安装版本：17.03.0-ce（社区版）。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Node.js从入门到放弃（一）-基础知识</title>
      <link>https://blog.orchidflower.cn/2017/02/27/nodejs-learning-note-01/</link>
      <pubDate>Mon, 27 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/02/27/nodejs-learning-note-01/</guid>
      <description>&lt;p&gt;最近一周比较忙，一直忙着搭建开发平台。之前不就刚用Golang搭建了一个服务端开发平台。完成之后，就需要针对Golang开发的服务开发一个管理平台，用Golang也能做，但是感觉还是麻烦，最后决定使用Node.js。&lt;/p&gt;
&lt;p&gt;这次搭建的平台倾向于使用比较新的一些Node.js特性，例如ES6、async/await解决回调地狱等。之前用过Node.js，但是属于浅尝辄止，这次准备充分了解一下。因此有了这些学习笔记。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>安装Go语言调试工具dlv</title>
      <link>https://blog.orchidflower.cn/2017/02/15/install-golang-debugger-dlv-on-mac/</link>
      <pubDate>Wed, 15 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/02/15/install-golang-debugger-dlv-on-mac/</guid>
      <description>&lt;p&gt;Dlv，也成为Delve，是Go语言的源码调试工具。由&lt;code&gt;derekparker&lt;/code&gt;开发，开源与Github。在Mac上配置Go语言开发环境的时候，经常碰到的问题就是Dlv调用总是不成功，无法启动应用，无法调试等等。大部分的问题都与Mac的安全机制有关。Mac上使用codesign对应用进行签名，没有签名的程序会受到一些限制，例如无法作为调试程序。&lt;/p&gt;
&lt;p&gt;当然如果为了方便，你可以通过Homebrew安装Homebrew编译好的Dlv。下面描述的是如何从源码构建这一工具。Delve作者专门写了一篇文档（请看附录的链接），描述如何对Dlv进行自签名。方法是生成一个自签名的证书，然后从源码编译安装Dlv。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Hexo博客提交搜索引擎</title>
      <link>https://blog.orchidflower.cn/2017/02/14/submit-to-search-engine/</link>
      <pubDate>Tue, 14 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/02/14/submit-to-search-engine/</guid>
      <description>&lt;p&gt;新博客上线多天之后，通过百度和Google仍然搜索不到我写的内容。忽然意识到这应该是网站没有被搜索引擎索引。经过搜索，发现还真是这么回事。直接搜索：&lt;code&gt;site:orchidflower.oschina.io&lt;/code&gt;和&lt;code&gt;site:orchidflower.github.io&lt;/code&gt;，发现真的没有找到相关的记录。&lt;/p&gt;
&lt;p&gt;经过上网查找原因，找到了一些资料，原来Hexo已经有这方面的解决方案了。&lt;/p&gt;
&lt;p&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;/p&gt;</description>
    </item>
    
    <item>
      <title>从一台没有外网连接的阿里云主机上访问微信API</title>
      <link>https://blog.orchidflower.cn/2017/02/12/access-weixin-qyapi-from-one-server-without-internet-on-aliyun/</link>
      <pubDate>Sun, 12 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/02/12/access-weixin-qyapi-from-one-server-without-internet-on-aliyun/</guid>
      <description>&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;公司的生产环境是部署在阿里云上的。Zabbix最初装在一台没有外网连接的ECS上，通过Nginx进行访问。但是后来发现如果需要报警，需要从Zabbix这台主机访问微信公众号服务器（qyapi.weixin.qq.com）。运维的兄弟最初选择了固定带宽的网络，但是考虑到费用问题，后期想切换到按量付费的网络，但是阿里云居然不支持这种切换（这里吐槽一下阿里的设计）。&lt;/p&gt;
&lt;p&gt;由于该主机是按照包月包年方式购买的，退掉重新申请主机安装Zabbix显然不划算。在主机到期之前，必须想办法实现在没有外网的情况下访问微信服务器（考虑到费用问题，原先固定带宽已经被修改成了0M，也就没有费用了）。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>在Mac上启用Docker的Bash Completion</title>
      <link>https://blog.orchidflower.cn/2017/02/12/enable-docker-bash-completion-on-mac/</link>
      <pubDate>Sun, 12 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/02/12/enable-docker-bash-completion-on-mac/</guid>
      <description>&lt;h1 id=&#34;1-背景&#34;&gt;1. 背景&lt;/h1&gt;
&lt;p&gt;在Ubuntu上使用Docker的时候，使用tab键自动完成docker命令感觉非常方便，例如：只需要输入image或者container ID的前几位就可以使用Tab键补齐整个命令行。但是在Mac上却没有办法实现相同的操作。&lt;/p&gt;
&lt;p&gt;经过搜索终于找到了原因：原来是因为没有启用Bash completion功能导致的。而实际上Docker安装包内已经提供了针对Docker的&lt;code&gt;Bash Completion&lt;/code&gt;脚本，只需要启用即可。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>使用Hexo搭建个人博客</title>
      <link>https://blog.orchidflower.cn/2017/01/24/hexo-deploy/</link>
      <pubDate>Tue, 24 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/01/24/hexo-deploy/</guid>
      <description>&lt;h1 id=&#34;0-什么是hexo&#34;&gt;0. 什么是Hexo&lt;/h1&gt;
&lt;p&gt;Hexo 是高效的静态站点生成框架，它基于 Node.js。 通过 Hexo 你可以轻松地使用 Markdown 编写文章，除了 Markdown 本身的语法之外，还可以使用 Hexo 提供的 标签插件 来快速的插入特定形式的内容。
网上关于Hexo介绍的文章已经很多，这里不写一般的安装部署步骤，只写一些不常提到的地方。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>关于</title>
      <link>https://blog.orchidflower.cn/about/</link>
      <pubDate>Sun, 22 Jan 2017 16:47:06 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/about/</guid>
      <description>我 Orchidflower，常用马甲还有 Orchid，千面怪等。 1975 年 5 月出生，金牛座。山东青岛人，毕业于南开，现工作于上海。 兴趣不广，偏好计</description>
    </item>
    
    <item>
      <title>安个新家</title>
      <link>https://blog.orchidflower.cn/2017/01/22/hello-world/</link>
      <pubDate>Sun, 22 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://blog.orchidflower.cn/2017/01/22/hello-world/</guid>
      <description>一直找不到合适的博客供应商，之前用过CSDN，体验一直不好。最近在研究Node.js，所以发现了Hexo Hexo，感觉还是不错的，挺有兴趣尝</description>
    </item>
    
  </channel>
</rss>
