<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang=""><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="https://zerodollar.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://zerodollar.github.io/" rel="alternate" type="text/html" hreflang="" /><updated>2019-05-05T20:45:42+08:00</updated><id>https://zerodollar.github.io/feed.xml</id><title type="html">敞开心扉</title><subtitle>个人知识管理</subtitle><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><entry><title type="html">Apple Pay的PassKit了解</title><link href="https://zerodollar.github.io/business/passkit/" rel="alternate" type="text/html" title="Apple Pay的PassKit了解" /><published>2017-12-17T00:00:00+08:00</published><updated>2017-12-17T00:00:00+08:00</updated><id>https://zerodollar.github.io/business/passkit</id><content type="html" xml:base="https://zerodollar.github.io/business/passkit/">&lt;h2 id=&quot;对照&quot;&gt;对照&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;英文&lt;/th&gt;
      &lt;th&gt;中午&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;store card&lt;/td&gt;
      &lt;td&gt;购物卡&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pass&lt;/td&gt;
      &lt;td&gt;凭证&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;ul&gt;
  &lt;li&gt;和https://passkit.com 什么关系？&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;具体开发例子&quot;&gt;具体开发例子&lt;/h2&gt;
&lt;p&gt;参考 &lt;a href=&quot;http://www.jianshu.com/p/23c2f8cf449c&quot;&gt;iOS PassKit Wallet 开发&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;1apple-pay-入门&quot;&gt;1.&lt;a href=&quot;https://developer.apple.com/apple-pay/get-started/cn/&quot;&gt;Apple Pay 入门&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;使用者：购物时无需输入账单、送货和联系人详细信息 （保存在Wallet中）
开发者：无需负责管理和保护实际的信用卡和借记卡卡号（使用Touch ID为付款授权）&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Apple Pay  (使用PassKit )
    &lt;ul&gt;
      &lt;li&gt;可销售实物商品: 如食品杂货、服装和电器&lt;/li&gt;
      &lt;li&gt;提供各种服务: 如俱乐部会员、酒店预订和活动门票&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;App 内购买项目(使用StoreKit)
    &lt;ul&gt;
      &lt;li&gt;可销售虚拟商品: 如适用于您的 App 的优质内容及订阅数字内容&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;参考&lt;a href=&quot;https://developer.apple.com/library/content/ApplePay_Guide/&quot;&gt;《Apple Pay 编程指南》(Apple Pay Programming Guide)&lt;/a&gt;,&lt;/p&gt;
&lt;h3 id=&quot;开发前提条件&quot;&gt;开发前提条件&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;通过付款处理机构或网关设置一个帐户。&lt;/li&gt;
  &lt;li&gt;通过“证书、标识符和描述文件”（“Certificates, Identifiers &amp;amp; Profiles”）注册一个商家 ID&lt;/li&gt;
  &lt;li&gt;生成一个 Apple Pay 证书，用于加密和解密付款令牌。&lt;/li&gt;
  &lt;li&gt;在您的 App 中包括一个 Apple Pay 授权。&lt;/li&gt;
  &lt;li&gt;遵循《App 审核准则》(“App Review Guidelines”)第 29 节中列出的要求。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;其他约束&quot;&gt;其他约束&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;支付供应商， 开发更简单 ?&lt;/li&gt;
  &lt;li&gt;如何显示 Apple Pay 按钮&lt;/li&gt;
  &lt;li&gt;如何显示付款单&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;touch-id&quot;&gt;Touch ID&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://baike.baidu.com/item/Touch%20ID&quot;&gt;Touch ID&lt;/a&gt;是苹果公司的一种指纹识别技术,硬件锁定,一机一Touch ID,只与一个处理器匹配&lt;/p&gt;

&lt;h2 id=&quot;2passkit-framework&quot;&gt;2.&lt;a href=&quot;https://developer.apple.com/documentation/passkit&quot;&gt;PassKit Framework&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;PassKit  API支持Apple Pay的开发框架&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;app增加Apple Pay，在不离开app情况下完成：
    &lt;ul&gt;
      &lt;li&gt;购买实物商品: 如食品杂货、服装和电器&lt;/li&gt;
      &lt;li&gt;购买各种服务: 如俱乐部会员、酒店预订和活动门票&lt;/li&gt;
      &lt;li&gt;给慈善组织捐款：&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;管理钱包中凭证，增加、更新到钱包中：可以通过网络、邮件发送，设置呈现的时间、位置
    &lt;ul&gt;
      &lt;li&gt;登机牌boarding passes&lt;/li&gt;
      &lt;li&gt;票据tickets&lt;/li&gt;
      &lt;li&gt;礼物卡gift cards&lt;/li&gt;
      &lt;li&gt;会员卡、积分卡loyalty cards&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;包含2个主题&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Apple Pay&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.apple.com/documentation/passkit/wallet&quot;&gt;Wallet&lt;/a&gt; &lt;br /&gt;
  其中列出了钱包使用的API: PKxxx 类族&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;21下载passkit&quot;&gt;2.1下载PassKit&lt;/h3&gt;
&lt;p&gt;访问&lt;a href=&quot;https://developer.apple.com/wallet/&quot;&gt;Wallet and PassKit&lt;/a&gt;和
&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/PassKit/Reference/PassKit_WebService/WebService.html&quot;&gt;PassKit Web Service Reference&lt;/a&gt;
&lt;a href=&quot;https://developer.apple.com/library/content/navigation/index.html?filter=passkit&quot;&gt;搜索passkit信息&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download Badges and Guidelines  下载 Add-to-Apple-Wallet.zip &lt;br /&gt;
Example Passes and Sample Code  下载 WalletCompanionFiles.zip&lt;/p&gt;

&lt;h2 id=&quot;3wallet-developer-guide&quot;&gt;3.&lt;a href=&quot;https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/PassKit_PG/index.html&quot;&gt;Wallet Developer Guide&lt;/a&gt;&lt;/h2&gt;

&lt;h3 id=&quot;31-钱包生态设计&quot;&gt;3.1 钱包生态设计&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;创建、分发凭证&lt;br /&gt;
商户Server负责分发pass给用户。苹果的mail/safari/icloud可以增加pass， 商户App可以用PassKit框架增加pass。&lt;/li&gt;
  &lt;li&gt;钱包管理凭证&lt;br /&gt;
pass包含文本、图片、条码。 商户Server可以设置风格、图片、颜色、文本。钱包展现pass，用户可以管理（包括删除）pass。&lt;/li&gt;
  &lt;li&gt;商户app使用PassKit使用凭证&lt;br /&gt;
app使用PassKit 框架提供API与凭证交互。app不要重复钱包的功能，最好实现钱包不具备的功能丰富用户体验（比如航班选座位，更新Pass）。 商户app未安装，对应的pass也要有效可用。app只能使用和其权限匹配的pass。&lt;/li&gt;
  &lt;li&gt;商户server更新凭证&lt;br /&gt;
凭证信息变更，商户server推送通知到终端、app获取最新版本凭证（不是变更列表）。除了pass type ID/serial number外，其他信息都可以修改。
注意更新、新增的场景，不要让用户迷惑
    &lt;ul&gt;
      &lt;li&gt;更新：修改车票、卡余额&lt;/li&gt;
      &lt;li&gt;新增：面包券修改成饮料券，用户容易迷惑，面包券失效、新增饮料券&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;凭证兑现&lt;br /&gt;
商户负责凭证有效期、使用次数，使用的效果（比如更新余额）。 几个不完整方案的场景：
    &lt;ul&gt;
      &lt;li&gt;一次性优惠券&lt;br /&gt;
凭证条码有唯一ID，商户DB保存该ID，用户使用时，扫描条码获取ID，从Server查询凭证是否有效。
删除过期的凭证需要用户同意。&lt;/li&gt;
      &lt;li&gt;有余额的购物卡&lt;br /&gt;
除了验证有效，还需要查询凭证的余额、记录交易、更新Server端凭证余额，Server更新钱包中凭证。（不要依赖凭证上信息，可能是过期的）
如果要验证用户是卡持有人，一种是凭证上有用户照片，另外一种是Server端存储照片app上显示，或者询问ID。&lt;/li&gt;
      &lt;li&gt;会员卡&lt;br /&gt;
全年使用相同的卡，偶尔展示活动信息。 除了可以和前面一样由Server验证，这里也可以直接保存到凭证中。
比如将扫描所需信息（账号、有效期）保存在凭证中，需要有加密签名，可以用来校验信息。
原因是存储在条码中信息不需改变（一次性优惠券、存储卡都需要改变信息）。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;总结&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;PassKit&lt;/th&gt;
      &lt;th&gt;Apple&lt;/th&gt;
      &lt;th&gt;app&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;创建/分发Pass&lt;/td&gt;
      &lt;td&gt;提供SDK&lt;/td&gt;
      &lt;td&gt;- Mail/Safari增加Pass到钱包&lt;br /&gt; - 调用PassKit增加Pass到钱包&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;展现/管理Pass&lt;/td&gt;
      &lt;td&gt;- 提供SDK&lt;br /&gt;- 钱包呈现，用户管理&lt;/td&gt;
      &lt;td&gt;- 设置风格、图片、颜色、文本&lt;br /&gt; - ？&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;使用Pass&lt;/td&gt;
      &lt;td&gt;/&lt;/td&gt;
      &lt;td&gt;- 有效期、次数、范围 &lt;br /&gt; - 功能不要和钱包重复&lt;br /&gt;- 未安装app，Pass也有效可用&lt;br /&gt;- app权限和Pass类型匹配&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;32创建凭证&quot;&gt;3.2创建凭证&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;简单优惠券
可以使用多次，提供相同的信息&lt;/li&gt;
  &lt;li&gt;创建凭证包
凭证包中pass.json包括：凭证定义、图像（比如商标、图标）
    &lt;ul&gt;
      &lt;li&gt;创建目录 xxx.pass&lt;/li&gt;
      &lt;li&gt;下载&lt;a href=&quot;https://developer.apple.com/services-account/download?path=/iOS/Wallet_Support_Materials/WalletCompanionFiles.zip&quot;&gt;WalletCompanionFiles.zip&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;解压、拷贝SamplePasses中文件到 xxx.pass&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;设置 Pass Type Identifier / Team ID&lt;br /&gt;
凭证都有一个和开发者相关联的凭证类型标识。到 &lt;a href=&quot;http://developer.apple.com/account&quot;&gt;Certificates, Identifiers &amp;amp; Profiles&lt;/a&gt;选择 Identifiers,再选Pass Type IDs. 在Keychain 中获取Team ID。
 这个要付费&lt;a href=&quot;https://my.oschina.net/u/1245365/blog/196263?Certificates&quot;&gt;申请开发者账号&lt;/a&gt;才能看到，Certificates包括：
    &lt;ul&gt;
      &lt;li&gt;开发证书 （ Development Certificates ），主要是授权mac设备的开发权限&lt;/li&gt;
      &lt;li&gt;发布证书 （Distribution Certificates ）， 主要是授权mac设置发布权限  &lt;br /&gt;
 Identifiers 即“标识符”，约等于是身份证，用于创建：&lt;/li&gt;
      &lt;li&gt;App IDs        应用的唯一标示符，每一个应用的app id是不一样的&lt;/li&gt;
      &lt;li&gt;Pass Type IDs&lt;/li&gt;
      &lt;li&gt;Website Push IDs
将这2个ID填入xxx.pass/pass.json的passTypeIdentifier和teamIdentifier&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;签名、压缩凭证&lt;br /&gt;
参考&lt;a href=&quot;https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/PassKit_PG/Creating.html#//apple_ref/doc/uid/TP40012195-CH4-SW55&quot;&gt;自动签名、压缩&lt;/a&gt;。
首先下载签名证书，再用xcode编译例子中signpass工程得到工具signpass
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;signpass -p xxx.pass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;得到签名后的压缩凭证： xxx.pkpass&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;更新Offer&lt;br /&gt;
修改pass.json中以下内容
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &quot;description&quot; : &quot;Coupon for a free lollipop at Example Candy Store&quot;,
  &quot;logoText&quot; : &quot;Example Candy Store&quot;,
 
  &quot;coupon&quot; : {
      &quot;primaryFields&quot; : [
          {
              &quot;key&quot;: &quot;offer&quot;,
              &quot;value&quot;: &quot;Free lollipop&quot;
              &quot;label&quot;: &quot;On July 29&quot;
          }
      ]
  },
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;展现凭证&lt;br /&gt;
将xxx.pkpass拖入模拟器，&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;33凭证设计&quot;&gt;3.3凭证设计&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Pass Type Identifier and Serial Number 标识凭证
passTypeIdentifier ： 类型标识，建议用pass.域名逆序， 需要在Member Center注册。  通过证书控制APP可以访问哪些凭证。&lt;br /&gt;
serialNumber ： 类型标识中唯一，PassKit不理解含义，唯一区分凭证即可。&lt;br /&gt;
如果passTypeIdentifier和serialNumber相同，即使其他信息不同，也认为是同一个凭证。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;一级信息&quot;&gt;一级信息&lt;/h4&gt;
&lt;p&gt;formatVersion ： 文件格式版本，目前为1
teamIdentifier： 必须和用来签名凭证的证书中 Team ID 匹配
organizationName ： 发放凭证的公司名称
description ： 描述信息， 用户可以区分同样类型中不同的凭证&lt;/p&gt;

&lt;h4 id=&quot;样式设置外观&quot;&gt;样式设置外观&lt;/h4&gt;
&lt;p&gt;凭证样式styles 属于API，开发者无法增加、修改。 样式是另外一种分类方式&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;boardingPass: 登机牌、火车票&lt;/li&gt;
  &lt;li&gt;coupon: 优惠券、特价和其他折扣。&lt;/li&gt;
  &lt;li&gt;eventTicket: 音乐会、电影、戏剧或体育赛事门票， 可以是一次性、也可以是多次使用。&lt;/li&gt;
  &lt;li&gt;storeCard： 会员卡、折扣卡、积分卡和礼品卡。 可以有余额&lt;/li&gt;
  &lt;li&gt;generic： 其他类，比如健身房会员卡、地铁票。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不同样式的布局、图片来源不同。
参考 &lt;a href=&quot;https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/PassKit_PG/Creating.html#//apple_ref/doc/uid/TP40012195-CH4-SW1&quot;&gt;样式对应布局关系&lt;/a&gt; 
每一种凭证都预定义了一些区域，对应xxx.pass中不同字段。区域长度是有限的，过长会不显示。&lt;br /&gt;
xxx.pass中不要定义不显示的字段，如果需要可以定义在userInfo中。防止苹果修改布局导致突然显示原先隐藏的字段。&lt;/p&gt;

&lt;h4 id=&quot;苹果watch凭证&quot;&gt;苹果Watch凭证&lt;/h4&gt;
&lt;p&gt;Watch上不显示Strip图像、缩略图。
不同的凭证在watch有不同显示方式。
在手机、手表上，用户使用方式也不同。参考&lt;a href=&quot;https://developer.apple.com/watch/human-interface-guidelines/&quot;&gt;手表人机接口&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;凭证上的文本区域&quot;&gt;凭证上的文本区域&lt;/h4&gt;
&lt;p&gt;每个区域包含：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;key：唯一键， 比如boarding-gate&lt;/li&gt;
  &lt;li&gt;label： 用户可读的键，比如Gate&lt;/li&gt;
  &lt;li&gt;value： 用户可读键的值，比如F12&lt;/li&gt;
  &lt;li&gt;其他可选属性：value如何格式化&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;重要性：头区&amp;gt;主区&amp;gt;备区&amp;gt;辅助区。&lt;br /&gt;
当凭证堆在一起供选择时，只显示头区。&lt;/p&gt;

&lt;p&gt;参考&lt;a href=&quot;https://developer.apple.com/library/content/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/FieldDictionary.html#//apple_ref/doc/uid/TP40012026-CH4&quot;&gt;Field Dictionary Keys&lt;/a&gt;列出所有字段。&lt;/p&gt;

&lt;h4 id=&quot;区域格式化&quot;&gt;区域格式化&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;alignment： 对齐方式&lt;/li&gt;
  &lt;li&gt;dateStyle/timeStyle:  时间格式&lt;/li&gt;
  &lt;li&gt;currencyCode/numberStyle:  数字格式&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;凭证背面提供附加文本信息&quot;&gt;凭证背面提供附加文本信息&lt;/h4&gt;
&lt;p&gt;正面空间有限，信息简略。 背面信息backFields可以很长，用户可以滚动，还可以减小字体。
背面信息支持link，用户可以点击。&lt;/p&gt;

&lt;h4 id=&quot;条码&quot;&gt;条码&lt;/h4&gt;
&lt;p&gt;barcodes：增加条码，用来关联商户服务器中对应记录
支持多种格式，手表不支持PKBarcodeFormatCode128，显示替代条码，如果没有则不显示条码。
提供替代文本，以便条码不可以扫描时手工输入。&lt;/p&gt;

&lt;p&gt;条码中可以存储任何信息，比如签名信息，在无网络时，条码扫描仪直接校验。&lt;/p&gt;

&lt;p&gt;条码中信息数量依赖条码格式、扫描条件。比如弱光条件下廉价扫描仪，需要实际测试验证可用。&lt;/p&gt;

&lt;h4 id=&quot;凭证颜色&quot;&gt;凭证颜色&lt;/h4&gt;
&lt;p&gt;颜色默认设置，可以修改。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;backgroundColor： 背景颜色&lt;/li&gt;
  &lt;li&gt;foregroundColor： 文本颜色&lt;/li&gt;
  &lt;li&gt;labelColor： 正面label颜色&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;图像&quot;&gt;图像&lt;/h4&gt;
&lt;p&gt;可以伸缩适配分配到的区域。&lt;/p&gt;

&lt;h4 id=&quot;锁屏信息&quot;&gt;锁屏信息&lt;/h4&gt;
&lt;p&gt;为方便使用，钱包在锁屏时可以立即显示凭证关联信息。&lt;br /&gt;
凭证提供时间relevantDate、位置locations，钱包基于这些信息显示，不要提供虚假信息操纵钱包显示。&lt;br /&gt;
只支持10个相关信息，可以更新凭证时修改。&lt;/p&gt;

&lt;p&gt;还可以通过beacons（信标？）提供关联信息， 每个beacons有UUID，添加10个beacon。
可以一个UUID表示一个beacon一个位置，也可以一个UUID表示n个beancon（n个位置，比如一个连锁商店多个门面），这可以突破10个限制。
不同的样式，关联信息含义不同（比如位置，可能是100m内，也可能是1000m内）， 需要的关联信息也不同（比如登机牌需要日期）。
当然，所有样式都支持没有关联信息。&lt;/p&gt;

&lt;p&gt;关联信息提供简单说明、或路径， 不要提供公司说明、使用说明。&lt;/p&gt;

&lt;h4 id=&quot;本地化&quot;&gt;本地化&lt;/h4&gt;
&lt;p&gt;凭证支持本地化：数字日期，字符串，图片
可以根据账号信息、用户首选位置设置，减少本地化数量，从而减少凭证大小。&lt;/p&gt;

&lt;p&gt;使用字符串文件提供本地化信息，比如英语 en.lproj/pass.strings&lt;/p&gt;

&lt;h4 id=&quot;签名加密压缩&quot;&gt;签名加密、压缩&lt;/h4&gt;
&lt;p&gt;将xxx.pass中除清单、签名外所有文件用SHA-1签名，写入清单 manifest.json 
从苹果申请的证书写入signature 
最终压缩一个zip文件用来分发。&lt;/p&gt;

&lt;h4 id=&quot;调试&quot;&gt;调试&lt;/h4&gt;
&lt;p&gt;如果不能加入钱包、显示，查看日志。 模拟器看syslog，真机看xcode的控制台。
常见的错误：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;JSON格式错误&lt;/li&gt;
  &lt;li&gt;key、value拼写错误&lt;/li&gt;
  &lt;li&gt;凭证类型标识与证书不匹配&lt;/li&gt;
  &lt;li&gt;签名中没有WWDR中级证书&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;34-分发凭证&quot;&gt;3.4 分发凭证&lt;/h3&gt;
&lt;p&gt;用户不需要商户app，通过Mail/Safari/iCloud添加凭证到钱包。
邮件附件方式简单，开发阶段方便使用。网站方式比较复杂，可以进行更多控制，比如用户登录。
app可以直接添加，提供更丰富的体验。参考&lt;a href=&quot;https://developer.apple.com/documentation/passkit/pkaddpassbutton&quot;&gt;PKAddPassButton&lt;/a&gt;添加凭证到钱包。&lt;/p&gt;

&lt;h4 id=&quot;编程方式添加&quot;&gt;编程方式添加&lt;/h4&gt;
&lt;p&gt;添加一个凭证：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;1.检查设备是否支持添加凭证：  &lt;a href=&quot;https://developer.apple.com/documentation/passkit/pkaddpassesviewcontroller&quot;&gt;PKAddPassesViewController&lt;/a&gt;.&lt;a href=&quot;https://developer.apple.com/documentation/passkit/pkaddpassesviewcontroller/1619212-canaddpasses&quot;&gt;canAddPasses&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;2.使用下载的签名、加密过的凭证实例化PKPass&lt;/li&gt;
  &lt;li&gt;3.使用PKPass创建PKAddPassesViewController&lt;/li&gt;
  &lt;li&gt;4.PKAddPassesViewController显示，用户同意或拒绝添加凭证， 回调&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;添加多个凭证（比如联程登机牌）：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;1.创建PKPass对象列表&lt;/li&gt;
  &lt;li&gt;2.调用&lt;a href=&quot;https://developer.apple.com/documentation/passkit/pkpasslibrary&quot;&gt;PKPassLibrary&lt;/a&gt;.&lt;a href=&quot;https://developer.apple.com/documentation/passkit/pkpasslibrary/1617093-addpasses&quot;&gt;addPasses&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;web方式&quot;&gt;WEB方式&lt;/h4&gt;
&lt;p&gt;有多种方式，有的自动处理凭证，有的需要下载再处理，推荐方案：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;safari中打开网页，app将控制权转给safari， 自动添加&lt;/li&gt;
  &lt;li&gt;使用 SFSafariViewController 展示内容，自动添加&lt;/li&gt;
  &lt;li&gt;使用WKWebView 展示， 需要app下载、添加&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;35-更新凭证&quot;&gt;3.5 更新凭证&lt;/h3&gt;
&lt;p&gt;线下状态改变，需要更新凭证， 所有凭证的信息都可以改变，除了token和serial number。&lt;/p&gt;
&lt;h4 id=&quot;通信&quot;&gt;通信&lt;/h4&gt;
&lt;p&gt;更新凭证需要终端、苹果server、商户server协同：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;1.终端安装支持更新的凭证，向商户server订阅获取更新&lt;/li&gt;
  &lt;li&gt;2.有更新，商户server发送push通知&lt;/li&gt;
  &lt;li&gt;3.终端收到通知，向商户server获取更新列表&lt;/li&gt;
  &lt;li&gt;4.终端箱商户server获取改变的凭证最新版本
&lt;img src=&quot;https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/PassKit_PG/Art/client_server_interaction_2x.png&quot; alt=&quot;交互图&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;凭证内置webServiceURL，钱包用来访问商户server&lt;br /&gt; 默认是https，开发者设置可以打开http。
商户server通过Device library identifier、authenticationToken校验请求是否授权。
前者是PassKit指定的终端设备、商户server之间的共享密钥， 终端与不同的server有不同ID，防止server记录终端上安装的凭证列表。
后者内置在凭证中，表示请求来自安装证书的用户，而不是第三方。&lt;/p&gt;

&lt;p&gt;商户server需要记录：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;终端，由Device library ID标识， 还有push令牌&lt;/li&gt;
  &lt;li&gt;凭证，由pass type ID/序号标识，更新相关信息&lt;/li&gt;
  &lt;li&gt;订阅信息，终端和凭证双向关系互查，这是n to m关系&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;终端订阅&quot;&gt;终端订阅&lt;/h4&gt;
&lt;p&gt;当终端订阅时，向webServiceURL发送POST请求，商户server完成：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;验证Authentication token是否是凭证中内置的？&lt;/li&gt;
  &lt;li&gt;存储终端信息：device lib ID、push token&lt;/li&gt;
  &lt;li&gt;存储凭证信息&lt;/li&gt;
  &lt;li&gt;存储订阅信息&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;当终端发送DELETE请求时，表示去订阅，商户server可以立刻删除这些信息。&lt;/p&gt;

&lt;h4 id=&quot;通知终端&quot;&gt;通知终端&lt;/h4&gt;
&lt;p&gt;当凭证变更后，商户server向所有订阅该凭证的终端推送通知。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;更新凭证信息&lt;/li&gt;
  &lt;li&gt;获取订阅的终端&lt;/li&gt;
  &lt;li&gt;获取终端的push令牌&lt;/li&gt;
  &lt;li&gt;用令牌发送空消息给终端： 推送消息不可靠&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;终端请求修改serial-number&quot;&gt;终端请求修改Serial Number&lt;/h4&gt;
&lt;p&gt;终端收到推送通知，向商户server请求特定时间点（更新tag）之后修改的凭证所有序列号
商户server返回最新的更新tag、其后的所有序列号。
server能比较不同更新tag之间先后关系&lt;/p&gt;

&lt;h4 id=&quot;终端请求最新版凭证&quot;&gt;终端请求最新版凭证&lt;/h4&gt;
&lt;p&gt;终端请求指定序列号下所有变更过的凭证的最新版本，&lt;/p&gt;

&lt;h4 id=&quot;终端显示变更信息&quot;&gt;终端显示变更信息&lt;/h4&gt;
&lt;p&gt;终端比较凭证中修改的区域，如果修改区域有变更消息，终端显示该变更消息，该消息会通知用户立刻阅读。&lt;/p&gt;
&lt;h4 id=&quot;最佳实践&quot;&gt;最佳实践&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;妥善保存私钥、证书&lt;/li&gt;
  &lt;li&gt;商户server不要保存私钥、证书， 由另外一个内部server生成签名后的凭证给商户server&lt;/li&gt;
  &lt;li&gt;信息都在url中，部分限制URL长度系统有问题&lt;/li&gt;
  &lt;li&gt;更新凭证时不要修改授权令牌。因为更新可能失败，所有令牌都可能用。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;36-app与凭证互动&quot;&gt;3.6 APP与凭证互动&lt;/h3&gt;
&lt;h4 id=&quot;打开passbook功能&quot;&gt;打开Passbook功能&lt;/h4&gt;
&lt;h4 id=&quot;访问凭证&quot;&gt;访问凭证&lt;/h4&gt;
&lt;p&gt;PKPassLibrary凭证库， PKPass凭证，PKAddPassesViewController 视图控制器&lt;/p&gt;
&lt;h4 id=&quot;校验pass库是否可用&quot;&gt;校验Pass库是否可用&lt;/h4&gt;
&lt;p&gt;PKPassLibrary.isPassLibraryAvailable&lt;/p&gt;
&lt;h4 id=&quot;检查凭证是否在库中&quot;&gt;检查凭证是否在库中&lt;/h4&gt;
&lt;h4 id=&quot;获取凭证&quot;&gt;获取凭证&lt;/h4&gt;
&lt;p&gt;PKPassLibrary.passes获取app可以访问的所有凭证，无序，由app排序。&lt;/p&gt;
&lt;h4 id=&quot;读取凭证&quot;&gt;读取凭证&lt;/h4&gt;
&lt;p&gt;PKPassLibrary.passWithPassTypeIdentifier(serialNumber)&lt;/p&gt;
&lt;h4 id=&quot;增加新凭证&quot;&gt;增加新凭证&lt;/h4&gt;
&lt;h4 id=&quot;修改凭证&quot;&gt;修改凭证&lt;/h4&gt;
&lt;p&gt;终端上不能直接修改凭证，修改内容会导致签名失效，凭证需要用商户的私钥签名，app中不能存有私钥。
必须通知商户server，由server更新凭证并签名，app再下载凭证，使用replacePassWithPass更新。&lt;/p&gt;
&lt;h4 id=&quot;删除凭证&quot;&gt;删除凭证&lt;/h4&gt;
&lt;p&gt;PKPassLibrary.removePass
凭证属于用户，删除凭证必须是用户动作。没有用户授权，及时过期、失效，app也不能删除。&lt;/p&gt;

&lt;h3 id=&quot;37-奖励注册&quot;&gt;3.7 奖励注册&lt;/h3&gt;
&lt;p&gt;创建一个含有用户个人信息的凭证， 个性化凭证可以像其他凭证一样分发，安装时：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;钱包提供一个注册表格搜集用户信息&lt;/li&gt;
  &lt;li&gt;用户填写完，钱包将用户数据、个性化token传到商户server&lt;/li&gt;
  &lt;li&gt;商户server为用户创建一个账号&lt;/li&gt;
  &lt;li&gt;商户server使用凭证证书签名个性化token，返回签名后token&lt;/li&gt;
  &lt;li&gt;钱包校验token&lt;/li&gt;
  &lt;li&gt;钱包请求个性化凭证&lt;/li&gt;
  &lt;li&gt;商户server返回个性化凭证&lt;/li&gt;
  &lt;li&gt;钱包删除原始凭证，安装新的个性化凭证&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;设置凭证个性化&quot;&gt;设置凭证个性化&lt;/h4&gt;
&lt;p&gt;创建分发个性化凭证， web服务端点可以返回个性化凭证&lt;/p&gt;

&lt;h4 id=&quot;创建个性化凭证&quot;&gt;创建个性化凭证&lt;/h4&gt;
&lt;p&gt;在标准的凭证包中包括：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;personalization.json 
文件保存注册表中用户个性化信息&lt;/li&gt;
  &lt;li&gt;personalizationLogo@XX.png&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;4passkit-package-format-reference&quot;&gt;4.&lt;a href=&quot;https://developer.apple.com/library/content/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/Introduction.html&quot;&gt;PassKit Package Format Reference&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;包结构&quot;&gt;包结构&lt;/h3&gt;
&lt;p&gt;一级目录含有：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;background.png  凭证正面背景&lt;/li&gt;
  &lt;li&gt;footer.png      凭证正面靠近条形码的图像&lt;/li&gt;
  &lt;li&gt;icon.png        凭证的图标&lt;/li&gt;
  &lt;li&gt;logo.png        凭证左上角&lt;/li&gt;
  &lt;li&gt;manifest.json   清单&lt;/li&gt;
  &lt;li&gt;pass.json       凭证信息&lt;/li&gt;
  &lt;li&gt;signature       PKCS＃7签名&lt;/li&gt;
  &lt;li&gt;strip.png      凭证正面的主要字段后面图像&lt;/li&gt;
  &lt;li&gt;thumbnail.png  凭证正面的缩略图
    &lt;h3 id=&quot;顶级键&quot;&gt;顶级键&lt;/h3&gt;
    &lt;h3 id=&quot;低级键&quot;&gt;低级键&lt;/h3&gt;
    &lt;h3 id=&quot;字段字典&quot;&gt;字段字典&lt;/h3&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;5apple-pay&quot;&gt;5.&lt;a href=&quot;https://developer.apple.com/library/prerelease/content/ApplePay_Guide/index.html&quot;&gt;Apple Pay&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://developer.apple.com/library/content/ApplePay_Guide/Art/payment_intro_2x.png&quot; alt=&quot;apple pay 安全&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;配置开发环境&quot;&gt;配置开发环境&lt;/h3&gt;
&lt;p&gt;注册商家ID
创建支付处理证书&lt;/p&gt;

&lt;h3 id=&quot;创建支付请求&quot;&gt;创建支付请求&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/documentation/passkit/pkpaymentrequest&quot;&gt;PKPaymentRequest&lt;/a&gt;实例完成支付请求，包括支付项目清单、可选物流列表、收货地址、商户信息。&lt;/p&gt;

&lt;h4 id=&quot;用户是否可以付款&quot;&gt;用户是否可以付款&lt;/h4&gt;
&lt;p&gt;检查网络：PKPaymentAuthorizationViewController.canMakePaymentsUsingNetworks
检查硬件、家长控制：canMakePayments ，返回NO则不显示Apply Pay按钮
用户按下Apple Pay按钮，就必须开始付款授权过程，其他过程(比如输入优惠码)必须在之前完成。&lt;/p&gt;

&lt;h4 id=&quot;web桥接&quot;&gt;WEB桥接&lt;/h4&gt;
&lt;p&gt;基于Web的界面来购买商品和服务，必须请求从Web界面移至本机iOS代码。&lt;/p&gt;

&lt;h4 id=&quot;付款请求包括货币和地区信息&quot;&gt;付款请求包括货币和地区信息&lt;/h4&gt;
&lt;p&gt;支付请求中的所有汇总金额都使用相同的货币，使用三字符ISO货币代码，例如USD。
付款请求的国家代码表示购买发生的国家或购买地点。使用两个字符的ISO国家代码，例如US。
付款申请中商家ID必须与应用授权中的某个商家ID匹配。&lt;/p&gt;

&lt;h4 id=&quot;付款请求有一个付款汇总项目清单&quot;&gt;付款请求有一个付款汇总项目清单&lt;/h4&gt;
&lt;p&gt;比如小计，任何折扣，运费，税金和总计&lt;/p&gt;

&lt;h4 id=&quot;运输方式是特殊付款汇总项目&quot;&gt;运输方式是特殊付款汇总项目&lt;/h4&gt;
&lt;p&gt;发货方式包括标准发货、次日发货，成本，所以有一个detail属性&lt;/p&gt;

&lt;h4 id=&quot;支持的支付方式&quot;&gt;支持的支付方式&lt;/h4&gt;
&lt;p&gt;supportedNetworks 数组表示支持的支付方式。merchantCapabilities比特表示协议(3DS/EMV)&lt;/p&gt;

&lt;h4 id=&quot;物流发票信息&quot;&gt;物流、发票信息&lt;/h4&gt;
&lt;p&gt;requiredBillingAddressFields和requiredShippingAddressFields&lt;/p&gt;

&lt;h4 id=&quot;附加信息&quot;&gt;附加信息&lt;/h4&gt;
&lt;p&gt;applicationData  存储其他支付相关信息&lt;/p&gt;

&lt;h3 id=&quot;授权支付&quot;&gt;授权支付&lt;/h3&gt;
&lt;p&gt;支付授权2个功能：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;让用户填写或选择发票、物流信息。   会回调app，比如更新费用&lt;/li&gt;
  &lt;li&gt;用户授权支付订单。  会回调app，支付令牌&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;app回调更新物流价格&quot;&gt;app回调更新物流、价格&lt;/h4&gt;

&lt;h4 id=&quot;创建支付令牌&quot;&gt;创建支付令牌&lt;/h4&gt;
&lt;p&gt;用户授权时，苹果服务器会创建支付令牌， 回调app时，app可以将令牌和其他信息发往商户server&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;框架将支付请求发给 Secure Element， 获取令牌化的支付卡号&lt;/li&gt;
  &lt;li&gt;Secure Element将卡、商加密，返回框架， 框架将其发往苹果server&lt;/li&gt;
  &lt;li&gt;苹果server用商户证书加密该数据，&lt;/li&gt;
  &lt;li&gt;回调app时，将信息传递给商户server&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;订单确认&quot;&gt;订单确认&lt;/h4&gt;

&lt;h3 id=&quot;支付&quot;&gt;支付&lt;/h3&gt;
&lt;p&gt;支付步骤：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;将付款信息及其他信息发送到商户server&lt;/li&gt;
  &lt;li&gt;验证付款数据的散列和签名&lt;/li&gt;
  &lt;li&gt;解密加密的付款数据&lt;/li&gt;
  &lt;li&gt;将支付数据提交给支付处理网络&lt;/li&gt;
  &lt;li&gt;将订单提交给您的订单跟踪系统&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;6其他渠道&quot;&gt;6.其他渠道&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://zh.wikipedia.org/wiki/Stripe&quot;&gt;Stripe&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/PingPlusPlus&quot;&gt;Ping++&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/beecloud&quot;&gt;BeeCloud&lt;/a&gt;
    &lt;h3 id=&quot;功能&quot;&gt;功能&lt;/h3&gt;
  &lt;/li&gt;
  &lt;li&gt;支付方式
    &lt;ul&gt;
      &lt;li&gt;手机app （iOS/Android/H5）&lt;/li&gt;
      &lt;li&gt;PC网页&lt;/li&gt;
      &lt;li&gt;QR扫码&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;支付场景
    &lt;ul&gt;
      &lt;li&gt;支付&lt;/li&gt;
      &lt;li&gt;查询&lt;/li&gt;
      &lt;li&gt;退款&lt;/li&gt;
      &lt;li&gt;红包&lt;/li&gt;
      &lt;li&gt;企业付款&lt;/li&gt;
      &lt;li&gt;账户系统（余额、优惠券）&lt;/li&gt;
      &lt;li&gt;订阅支付（定时自动扣款）&lt;/li&gt;
      &lt;li&gt;分期支付&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;开发
    &lt;ul&gt;
      &lt;li&gt;SDK&lt;/li&gt;
      &lt;li&gt;Live&amp;amp;Sandbox&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;特性&quot;&gt;特性&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;服务稳定&lt;/li&gt;
  &lt;li&gt;支持参数安全&lt;/li&gt;
  &lt;li&gt;客户端SDK安全可靠&lt;/li&gt;
&lt;/ul&gt;</content><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><category term="Appley Pay" /><category term="PassKit" /><summary type="html">对照</summary></entry><entry><title type="html">JAVA300集视频教程</title><link href="https://zerodollar.github.io/lang/sxt_gaoqi_java_300/" rel="alternate" type="text/html" title="JAVA300集视频教程" /><published>2017-12-11T00:00:00+08:00</published><updated>2017-12-11T00:00:00+08:00</updated><id>https://zerodollar.github.io/lang/sxt_gaoqi_java_300</id><content type="html" xml:base="https://zerodollar.github.io/lang/sxt_gaoqi_java_300/">&lt;p&gt;北京尚学堂高淇出品，面向大学生教授java基础知识，比较老，主要是Java6、7&lt;/p&gt;

&lt;h2 id=&quot;1如何学习java&quot;&gt;1.如何学习JAVA&lt;/h2&gt;
&lt;p&gt;学习习惯：内存结构／JDK源码
java：服务器／安卓
手把手，代码一行码出来
工具先了解常见功能，不常见的用到再说。80-20法则&lt;/p&gt;

&lt;h2 id=&quot;2java三版本区别&quot;&gt;2.JAVA三版本区别&lt;/h2&gt;
&lt;p&gt;JAVAEE Enterprise Edition 企业版，开发服务器端应用，非常广泛
JAVASE Standard Edition标准版，开发个人计算机上应用，较少
JAVAME Micro Edition 微型版，消费性电子产品，消亡中，被安卓取代，和安卓没有任何关系，安卓用JAVA写&lt;/p&gt;

&lt;h2 id=&quot;3jdk下载安装&quot;&gt;3.JDK下载安装&lt;/h2&gt;
&lt;p&gt;JDK包含JRE，JRE包含JVM，JVM跨平台
配置PATH、JAVA_HOME， 不用再配置CLASS_PATH了，1.5后JVM自动找&lt;/p&gt;
&lt;h2 id=&quot;4helloworld&quot;&gt;4.HelloWorld&lt;/h2&gt;
&lt;p&gt;类名和文件名一致，首字母大写。javac编译生成class字节码文件，java执行&lt;/p&gt;
&lt;h2 id=&quot;5helloworld深化&quot;&gt;5.HelloWorld深化&lt;/h2&gt;
&lt;p&gt;大小写敏感，一个源文件可以有多个class，至多只能有一个public的类声明（与文件名一致），其它类的个数不限，每个类生成独立的字节码文件。
&lt;code class=&quot;highlighter-rouge&quot;&gt;//单行注释&lt;/code&gt;，&lt;code class=&quot;highlighter-rouge&quot;&gt;/*多行注释*/&lt;/code&gt;
UTF8编码乱码，可以转换为ANSI编码&lt;/p&gt;

&lt;h2 id=&quot;6各种字符集关系&quot;&gt;6.各种字符集关系&lt;/h2&gt;
&lt;p&gt;标识符支持字母／_/$&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ISO8859-1  西欧字符集&lt;/li&gt;
  &lt;li&gt;BIG5   台湾大五码，繁体汉字&lt;/li&gt;
  &lt;li&gt;GB2312 最早的简体字符&lt;/li&gt;
  &lt;li&gt;GBK    GB2312的扩展，可以表示繁体中文&lt;/li&gt;
  &lt;li&gt;GB18030   最新的GBK扩展，所有非手持／嵌入设备强制实行标准，可以表示汉字／维吾尔／藏文等中华民族字符&lt;/li&gt;
  &lt;li&gt;Unicode（UTF-8，UTF-16） 国际通用字符集&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;7整形类型&quot;&gt;7.整形类型&lt;/h2&gt;
&lt;p&gt;byte/short/int/long/BigInteger/BigDecimal   0b二 0八  0x十六
float/double
char
boolean
Integer.toBinaryString(int)&lt;br /&gt;
Integer.toOctalString(int)&lt;br /&gt;
Integer.toHexString(int)&lt;/p&gt;

&lt;h2 id=&quot;8浮点误差&quot;&gt;8.浮点误差&lt;/h2&gt;
&lt;p&gt;浮点有误差，不能直接比较，精确可以用BigDecimal&lt;/p&gt;
&lt;h2 id=&quot;9char-字符串&quot;&gt;9.char 字符串&lt;/h2&gt;
&lt;p&gt;char 类型用来表示在Unicode编码表中的字符，可以大于255
‘a’／’中’／’\u0061’&lt;/p&gt;

&lt;h2 id=&quot;10类型提升问题&quot;&gt;10.类型提升问题&lt;/h2&gt;
&lt;p&gt;自动／强制转换，注意溢出&lt;/p&gt;

&lt;h2 id=&quot;11jdk7特性&quot;&gt;11.JDK7特性&lt;/h2&gt;
&lt;p&gt;整形支持下划线分隔&lt;/p&gt;
&lt;h2 id=&quot;12变量&quot;&gt;12.变量&lt;/h2&gt;
&lt;p&gt;变量是最基本存储单元：变量名／变量类型／作用域&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;实例变量／成员变量／属性&lt;/li&gt;
  &lt;li&gt;局部变量，初始化后才能用&lt;/li&gt;
  &lt;li&gt;Final常量只能初始化一次&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;命名：变量／方法首字母小写驼峰，类名首字母大写驼峰，常量下划线分隔大写&lt;/p&gt;
&lt;h2 id=&quot;13-算术运算符&quot;&gt;13. 算术运算符&lt;/h2&gt;
&lt;p&gt;浮点数也可以取余%
instanceof 对象是否是特定类的一个实例&lt;/p&gt;
&lt;h2 id=&quot;14字符串连接&quot;&gt;14.字符串连接&lt;/h2&gt;
&lt;p&gt;4+“5”&lt;/p&gt;
&lt;h2 id=&quot;15eclipse开发环境&quot;&gt;15.eclipse开发环境&lt;/h2&gt;
&lt;p&gt;开源、基于Java的可扩展开发平台
包视图／控制台／大纲视图outline&lt;/p&gt;
&lt;h2 id=&quot;16eclipse运行程序&quot;&gt;16.eclipse运行程序&lt;/h2&gt;
&lt;p&gt;设置断点，Debug as调试，通过Debug／Java视图切换&lt;/p&gt;
&lt;h2 id=&quot;17if&quot;&gt;17.if&lt;/h2&gt;
&lt;h2 id=&quot;18switch&quot;&gt;18.switch&lt;/h2&gt;
&lt;p&gt;case穿透&lt;/p&gt;
&lt;h2 id=&quot;19增强switch&quot;&gt;19.增强switch&lt;/h2&gt;
&lt;p&gt;支持String&lt;/p&gt;
&lt;h2 id=&quot;20while&quot;&gt;20.while&lt;/h2&gt;

&lt;h2 id=&quot;21for&quot;&gt;21.for&lt;/h2&gt;
&lt;h2 id=&quot;22练习&quot;&gt;22.练习&lt;/h2&gt;
&lt;p&gt;遇到问题，先想能干，再简化，补充调整&lt;/p&gt;
&lt;h2 id=&quot;23带标签的breakcontinue&quot;&gt;23.带标签的break／continue&lt;/h2&gt;
&lt;p&gt;goto保留字但无功能&lt;/p&gt;
&lt;h2 id=&quot;24方法&quot;&gt;24.方法&lt;/h2&gt;
&lt;p&gt;功能块，一个方法只完成1个功能。
基本类型传递的是该数据值本身。
引用类型传递的是对象的引用，而不是对象本身。
JAVA中只有值传递。&lt;/p&gt;
&lt;h2 id=&quot;25递归&quot;&gt;25.递归&lt;/h2&gt;
&lt;p&gt;递归结构包括两个部分：
    1.递归头。解答：什么时候不调用自身方法。如果没有头，将陷入死循环。
    2.递归体。解答：什么时候需要调用自身方法。&lt;/p&gt;
&lt;h2 id=&quot;26api文档--相当于字典用时查不用背&quot;&gt;26.API文档 – 相当于字典，用时查，不用背&lt;/h2&gt;
&lt;p&gt;包-&amp;gt;接口／类 -&amp;gt; 具体说明
不要使用默认包。
com.pa和com.pa.pb是2个独立的包
java.lang／awt／net/io/util
package 解决类之间的重名问题&lt;/p&gt;

&lt;p&gt;export -&amp;gt; Java -&amp;gt; Javadoc  文档代码统一&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;@Author 作者  默认是计算机用户名&lt;/li&gt;
  &lt;li&gt;@version 版本&lt;/li&gt;
  &lt;li&gt;@param  参数&lt;/li&gt;
  &lt;li&gt;@return  返回值的含义&lt;/li&gt;
  &lt;li&gt;@throws 抛出异常描述&lt;/li&gt;
  &lt;li&gt;@deprecated 废弃。建议用户不再使用该方法
    &lt;h2 id=&quot;27键盘输入&quot;&gt;27.键盘输入&lt;/h2&gt;
    &lt;p&gt;Scanner&lt;/p&gt;
    &lt;h2 id=&quot;28面向对象01-和面向过程的本质区别&quot;&gt;28.面向对象01 和面向过程的本质区别&lt;/h2&gt;
  &lt;/li&gt;
  &lt;li&gt;类：
    &lt;ul&gt;
      &lt;li&gt;完全抽象：接口&lt;/li&gt;
      &lt;li&gt;抽象+实行：抽象类&lt;/li&gt;
      &lt;li&gt;管理：package／import／JDK中包&lt;/li&gt;
      &lt;li&gt;包含：属性／方法／构造方法／重载&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;对象：
    &lt;ul&gt;
      &lt;li&gt;引用类型&lt;/li&gt;
      &lt;li&gt;this／static&lt;/li&gt;
      &lt;li&gt;内存结构&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;三大特征：
    &lt;ul&gt;
      &lt;li&gt;封装：public／private／protected&lt;/li&gt;
      &lt;li&gt;继承：Object/super/重写／组合&lt;/li&gt;
      &lt;li&gt;多态&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;29面向对象的思维&quot;&gt;29.面向对象的思维&lt;/h2&gt;
&lt;p&gt;面向过程的思维模式是简单的线性思维，思考问题首先陷入第一步做什么、第二步做什么的细节中。&lt;/p&gt;

&lt;p&gt;面向对象的思维模式说白了就是分类思维模式。思考问题首先会解决问题需要哪些分类，然后对这些分类进行单独思考。最后，才对某个分类下的细节进行面向过程的思索。&lt;/p&gt;

&lt;p&gt;老毛的分类。&lt;/p&gt;
&lt;h2 id=&quot;30类和对象的关系&quot;&gt;30.类和对象的关系&lt;/h2&gt;
&lt;p&gt;以类的方式组织代码，以对象的组织(封装)数据。
对象是具体的事物。
类，是抽象的，是对对象的抽象。是抽出象的部分。&lt;/p&gt;
&lt;h2 id=&quot;3132程序运行的内存分析&quot;&gt;31/32.程序运行的内存分析&lt;/h2&gt;
&lt;p&gt;堆（new对象）、栈（局部变量）、方法区（也是堆，包括代码、static变量、常量池）
java中，除了基本数据类型之外的其他类型称之为引用类型。
java中的对象是通过引用来操作的。
属性的默认初始化：如果不对其初始化，Java使用默认的值对其初始化。&lt;/p&gt;
&lt;h2 id=&quot;33jvm内存管理&quot;&gt;33.JVM内存管理&lt;/h2&gt;
&lt;p&gt;JAVA的内存管理实际上指的就是对象的管理，其中包括对象空间的分配和释放。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1.程序员无权调用垃圾回收器。&lt;/li&gt;
  &lt;li&gt;2.程序员可以通过System.gc()。通知GC运行，但是JAVA规范并不能保证立刻运行。&lt;/li&gt;
  &lt;li&gt;3.finalize方法，是JAVA提供给程序员用来释放对象或资源的方法，但是尽量少用。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;34构造方法&quot;&gt;34.构造方法&lt;/h2&gt;
&lt;h2 id=&quot;35方法重载&quot;&gt;35.方法重载&lt;/h2&gt;
&lt;p&gt;类中可以定义有相同的名字，但参数不同的多个方法。调用匹配离得最近的类型。&lt;/p&gt;
&lt;h2 id=&quot;36static&quot;&gt;36.Static&lt;/h2&gt;
&lt;p&gt;类的公用变量，属于类，被该类的所有实例共享，在类被载入时被显式初始化，该类的所有对象共享&lt;/p&gt;
&lt;h2 id=&quot;37this&quot;&gt;37.this&lt;/h2&gt;
&lt;p&gt;普通方法中，this总是指向调用该方法的对象。
构造方法中，this总是指向正要初始化的对象。&lt;/p&gt;
&lt;h2 id=&quot;38继承&quot;&gt;38.继承&lt;/h2&gt;
&lt;p&gt;继承的本质在于抽象。继承是对某一批类的抽象。&lt;/p&gt;
&lt;h2 id=&quot;39方法的重写override&quot;&gt;39.方法的重写（override）&lt;/h2&gt;
&lt;p&gt;重写方法必须和被重写方法具有相同方法名称、参数列表和返回类型。
重写方法不能使用比被重写方法更严格的访问权限。&lt;/p&gt;
&lt;h2 id=&quot;40object类&quot;&gt;40.Object类&lt;/h2&gt;
&lt;p&gt;所有Java类的根基类，提供：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;toString方法，默认&lt;code class=&quot;highlighter-rouge&quot;&gt;getClass().getName() + &quot;@&quot; + Integer.toHexString(hashCode())&lt;/code&gt;，可以重写&lt;/li&gt;
  &lt;li&gt;equals方法，对象是否相等&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;41继承&quot;&gt;41.继承&lt;/h2&gt;
&lt;p&gt;super是直接父类对象的引用。除了Object类之外其他所有类的构造方法第一句总是super(…)，编译器会默认添加。&lt;/p&gt;
&lt;h2 id=&quot;42组合&quot;&gt;42.组合&lt;/h2&gt;
&lt;p&gt;has-a关系：使用组合&lt;/p&gt;
&lt;h2 id=&quot;43-final&quot;&gt;43. final&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;修饰变量
    被final修饰的变量不可改变。即初始化一次后，就不能再次被赋值！即，变为常量！&lt;/li&gt;
  &lt;li&gt;修饰方法：
    被final修饰的方法不可以被子类重写！&lt;/li&gt;
  &lt;li&gt;修饰类：
    被final修饰的类不能被继承!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;44封装隐藏&quot;&gt;44.封装、隐藏&lt;/h2&gt;
&lt;p&gt;encapsulation 需要让用户知道的暴露出来，不需要让用户了解的全部隐藏起来。
白话：该露的露，该藏的藏
专业：高内聚，低耦合
低耦合便于调用者调用，高内聚便于修改内部代码，提高可维护性。可进行数据完整性检测，保证数据的有效性。&lt;/p&gt;
&lt;h2 id=&quot;45多态&quot;&gt;45.多态&lt;/h2&gt;
&lt;p&gt;polymorphism
编译时类型（模糊一点，一般是一个父类）由声明时的类型决定。
运行时类型（运行时，具体是哪个子类就是哪个子类）由实际对应的对象类型决定。
多态：如果编译时类型和运行时类型不一致，就会造成多态。
静态绑定：在编译期完成，可以提高代码执行速度。
动态绑定：通过对象调用的方法，采用动态绑定机制。除final类、方法，static方法外都是动态绑定，是慢的主要原因。
多态的存在要有3个必要条件：要有继承，要有方法重写，父类引用指向子类对象
子类的对象可以当作基类的对象来使用称作向上转型（upcasting），反之称为向下转型（downcasting）&lt;/p&gt;
&lt;h2 id=&quot;4647多态内存分析&quot;&gt;46/47.多态内存分析&lt;/h2&gt;
&lt;h2 id=&quot;48抽象类&quot;&gt;48.抽象类&lt;/h2&gt;
&lt;h2 id=&quot;49接口&quot;&gt;49.接口&lt;/h2&gt;
&lt;p&gt;从接口的实现者角度看，接口定义了可以向外部提供的服务。
从接口的调用者角度看，接口定义了实现者能提供那些服务。&lt;/p&gt;

&lt;p&gt;https://www.bwh1.net/pwreset.php
https://www.bwh1.net/pwreset.php?key=9bfebab34c204c2572912c9919f9d49e&lt;/p&gt;
&lt;h2 id=&quot;50回调的实现&quot;&gt;50.回调的实现&lt;/h2&gt;
&lt;p&gt;CallBack   Hook函数  模板方法
调用注入的对象的方法（该方法支持多态）&lt;/p&gt;
&lt;h2 id=&quot;51内部类&quot;&gt;51.内部类&lt;/h2&gt;
&lt;p&gt;组合
内部类提供了更好的封装。只能让外部类直接访问，不允许同一个包中的其他类直接访问。
内部类可以直接访问外部类的私有属性，内部类被当成其外部类的成员。 但外部类不能访问内部类的内部属性。&lt;/p&gt;

&lt;p&gt;内部类在只为所在外部类提供服务的情况下优先使用。
类文件：外部类$内部类.class&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;非静态内部类
 OuterObject.new Inner()
 外部类名.this.变量名&lt;/li&gt;
  &lt;li&gt;静态内部类
 一个静态内部类对象存在，并不一定存在对应的外部类对象。
 new  OuterClass.Inner()&lt;/li&gt;
  &lt;li&gt;匿名内部类
 适合那种只需要使用一次的类.比如：键盘监听操作等&lt;/li&gt;
  &lt;li&gt;局部内部类
 定义在方法内部。
    &lt;h2 id=&quot;5253数组&quot;&gt;52/53.数组&lt;/h2&gt;
    &lt;p&gt;array是对象，元素类似对象的成员变量&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;默认初始化   int[] a = new int[4]&lt;/li&gt;
  &lt;li&gt;动态初始化   a[0] = 1&lt;/li&gt;
  &lt;li&gt;静态初始化   int[] a = {1,2,3,4}
    &lt;h2 id=&quot;5455-string-分析-jdk源码&quot;&gt;54/55. String 分析 （JDK源码）&lt;/h2&gt;
    &lt;p&gt;循环 str+=’c’  会导致创建很多临时对象&lt;/p&gt;
    &lt;h2 id=&quot;565758-可变字符序列对比扩容&quot;&gt;56/57/58. 可变字符序列对比、扩容&lt;/h2&gt;
    &lt;p&gt;StringBuffer 线程安全，效率低
StringBuilder 线程不安全，效率高
通过return this实现方法链&lt;/p&gt;
    &lt;h2 id=&quot;59数组_模拟arraylist容器的底层实现&quot;&gt;59.数组_模拟ArrayList容器的底层实现&lt;/h2&gt;
    &lt;h2 id=&quot;606162多维数组矩阵运算jdk的array方法增强的for循环&quot;&gt;60/61/62.多维数组，矩阵运算,JDK的Array方法，增强的for循环&lt;/h2&gt;
    &lt;h2 id=&quot;63包装类&quot;&gt;63.包装类&lt;/h2&gt;
    &lt;p&gt;基本类型转换为对象，比如Byte、Boolean、Integer、Character。。。&lt;/p&gt;
    &lt;h2 id=&quot;64auto-boxingunboxing缓存处理&quot;&gt;64.auto-boxing/unboxing/缓存处理&lt;/h2&gt;
    &lt;p&gt;auto-boxing  基本类型-&amp;gt;对象
unboxing     对象-&amp;gt;基本类型
缓存[-128,127]范围内数值缓存，按照简单类型处理&lt;/p&gt;
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Integer a=123;
Integer b=123;
System.out.println(a==b)  //输出的是true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;h2 id=&quot;65时间date相关类&quot;&gt;65.时间Date相关类&lt;/h2&gt;
    &lt;p&gt;java.util
Timezone
Date      特定的瞬间，精确到毫秒
Calendar  日期计算
GregorianCalendar  公历
DateFormat
SimpleDateFormat&lt;/p&gt;
    &lt;h2 id=&quot;66dateformat和simpledateformat类&quot;&gt;66.DateFormat和SimpleDateFormat类 &lt;/h2&gt;
    &lt;p&gt;G 公元前后
y年M月w年周W月周d月天D年天E周天F月周a上下午Hk24时hK12时m分s秒S毫秒zZ时区
SimpleDateFormat.format(Date) 转成String&lt;/p&gt;
    &lt;h2 id=&quot;676869时刻日期计算calendar日历类&quot;&gt;67/68/69.时刻、日期计算Calendar 日历类，&lt;/h2&gt;
    &lt;p&gt;注意一月为0、周日为1
可视化日历： 能，先做简单，后想办法解决问题&lt;/p&gt;
    &lt;h2 id=&quot;7071file类递归&quot;&gt;70/71.File类、递归&lt;/h2&gt;
    &lt;p&gt;以pathname为路径创建File对象，File(File,String)&lt;/p&gt;
    &lt;h2 id=&quot;727374异常异常处理&quot;&gt;72/73/74.异常、异常处理&lt;/h2&gt;
    &lt;p&gt;设计良好的程序应该在异常发生时提供处理这些错误的方法，使得程序不会因为异常的发生而终断或产生不可预见的结果。 
没有异常，逻辑代码和错误处理代码混在一起.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Error类
描述了Java运行时系统内部错误和资源耗尽错误。这类错误是我们无法控制的。&lt;/li&gt;
  &lt;li&gt;RuntimeException
一定是你的问题，可以不捕获，因为小心点这些异常是可以避免的。&lt;/li&gt;
  &lt;li&gt;Checked Exception
不是RuntimeException，通常由外界因素造成的，为了预防这些异常产生时，造成程序的中断或得到不正确的结果，一定要去做异常的处理。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;异常处理方法：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;try-catch  &lt;br /&gt;
执行顺序：执行try，catch ， 给返回值赋值； 执行finally；return&lt;/li&gt;
  &lt;li&gt;再把异常Throws出去。&lt;/li&gt;
  &lt;li&gt;手动抛出异常，throw子句
    &lt;h2 id=&quot;7576自定义异常&quot;&gt;75/76.自定义异常&lt;/h2&gt;
    &lt;p&gt;从Exception类或者它的子类派生一个子类即可 &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;1.要避免使用异常处理代替错误处理，这样会降低程序的清晰性，并且效率低下。 使用异常机制建议&lt;/li&gt;
  &lt;li&gt;2.处理异常不可以代替简单测试— 只在异常情况下使用异常机制 &lt;/li&gt;
  &lt;li&gt;3.不要进行小粒度的异常处理—应该将整个任务包装在一个Try语句块中 &lt;/li&gt;
  &lt;li&gt;4.异常往往在高层处理
    &lt;h2 id=&quot;77坐标&quot;&gt;77.坐标&lt;/h2&gt;
    &lt;h2 id=&quot;7879图片加载实现动画&quot;&gt;78/79.图片加载、实现动画&lt;/h2&gt;
    &lt;p&gt;URL u = GameUtil.class.getClassLoader().getResource(path);  
BufferedImage img =ImageIO.read(u);
Graphics g.drawImage(img,x,y,null)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;启动线程完成重画，坐标持续变化&lt;/p&gt;
&lt;h2 id=&quot;80818283移动游戏项目&quot;&gt;80/81/82/83.移动，游戏项目&lt;/h2&gt;
&lt;p&gt;判断边界，修改方向，变化坐标&lt;/p&gt;
&lt;h2 id=&quot;84858687star类太阳系&quot;&gt;84/85/86/87.Star类,太阳系&lt;/h2&gt;
&lt;h2 id=&quot;8897飞机射击&quot;&gt;88~97.飞机射击&lt;/h2&gt;
&lt;p&gt;键盘监听&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class KeyMonitor extends KeyAdapter
addKeyListener(new KeyMonitor());
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;awt简单，需要使用双缓冲解决闪烁问题， 新版本swing默认支持双缓冲&lt;/p&gt;

&lt;h2 id=&quot;98-课程复习对前面的知识的一个回顾&quot;&gt;98. 课程复习，对前面的知识的一个回顾&lt;/h2&gt;
&lt;h2 id=&quot;99100-容器&quot;&gt;99/100. 容器&lt;/h2&gt;
&lt;p&gt;Collection
LinkedList、ArrayList 线程不安全，效率低
Vector 线程安全，效率低&lt;/p&gt;
&lt;h2 id=&quot;101104-非泛型的arraylistlinkedlist实现&quot;&gt;101~104 非泛型的ArrayList/LinkedList实现&lt;/h2&gt;
&lt;p&gt;Q：transient关键字能实现什么？
A：当对象被序列化时（写入字节序列到目标文件）时，transient阻止实例中那些用此关键字声明的变量持久化；当对象被反序列化时（从源文件读取字节序列进行重构），这样的实例变量值不会被持久化和恢复。&lt;/p&gt;
&lt;h2 id=&quot;105107-非泛型的maphashmaphashtable实现&quot;&gt;105~107 非泛型的Map/HashMap/HashTable实现&lt;/h2&gt;
&lt;p&gt;HashTable线程安全、效率低  HashMap效率高&lt;/p&gt;
&lt;h2 id=&quot;108--equalshashcode分析&quot;&gt;108  equals/hashcode分析&lt;/h2&gt;
&lt;p&gt;可以通过IDE辅助生成equals代码
equals相等，则hashcode必相等。 反之不一定。&lt;/p&gt;
&lt;h2 id=&quot;109-listmap源码分析&quot;&gt;109 List/Map源码分析&lt;/h2&gt;
&lt;p&gt;List在node时，根据index决定从first、last开始检索&lt;/p&gt;
&lt;h2 id=&quot;110111-sethashset实现&quot;&gt;110~111 Set/HashSet实现&lt;/h2&gt;
&lt;h2 id=&quot;112-javabean&quot;&gt;112 JavaBean&lt;/h2&gt;
&lt;p&gt;JavaBean 实体类，存储数据：表/类、字段/私有属性、数据/测试类
只有属性和get、set方法&lt;/p&gt;
&lt;h2 id=&quot;113-使用一个map保存一条表记录&quot;&gt;113 使用一个Map保存一条表记录&lt;/h2&gt;
&lt;h2 id=&quot;114115-迭代器遍历listsetmap&quot;&gt;114~115 迭代器遍历List、Set、Map&lt;/h2&gt;
&lt;h2 id=&quot;116-自定义泛型泛型类泛型接口泛型方法&quot;&gt;116 自定义泛型、泛型类、泛型接口、泛型方法&lt;/h2&gt;
&lt;p&gt;类型转换错误运行时错误，需要instanceof检查类型是否对
泛型在编译时检查，安全（检查）、省心（自动转换）
T类型、KV键值、E元素、？不确定， 只能是引用类型(不能基本类型）
泛型类T不能使用静态属性、静态方法：运行时绑定，静态在编译时确定&lt;/p&gt;

&lt;p&gt;泛型方法：  修饰 &lt;T&gt; 返回类型，只能访问对象信息、不能修改。&lt;/T&gt;&lt;/p&gt;
&lt;h2 id=&quot;117-泛型擦除&quot;&gt;117 泛型擦除&lt;/h2&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Father&amp;lt;T&amp;gt;
class child extends Father&amp;lt;String&amp;gt;
class child2&amp;lt;T,T1&amp;gt; extends Father&amp;lt;T&amp;gt;
class child3&amp;lt;T1&amp;gt; extends Father  父类泛型擦除 T是Object
class child4 extends Father      子、父类都擦除
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;不可以子类擦除、父类不擦除。
方法中T由父类定， 属性在父类中由父类定、子类中由子类定
编译器告警：指定T为Object。 擦除不会进行类型检查。
泛型没有多态，声明类型、方法使用&amp;lt;？ extends/super 父类&amp;gt;： 类型不定、使用时确定
没有泛型数组&lt;/p&gt;
&lt;h2 id=&quot;117-jdkfa泛型&quot;&gt;117 jdkfa泛型&lt;/h2&gt;
&lt;h2 id=&quot;118-iterator&quot;&gt;118 iterator&lt;/h2&gt;
&lt;p&gt;implements Iterator&lt;T&gt;
增强for使用java.lang.Iterable接口&lt;/T&gt;&lt;/p&gt;
&lt;h2 id=&quot;119121--hashmap存储&quot;&gt;119~121  HashMap存储&lt;/h2&gt;
&lt;h2 id=&quot;122123-冒泡排序&quot;&gt;122~123 冒泡排序&lt;/h2&gt;
&lt;p&gt;print中计算pirnt(“  “+(1+2)+” “)&lt;/p&gt;
&lt;h2 id=&quot;124126-comparable接口---comparator对象&quot;&gt;124~126 Comparable接口   Comparator对象&lt;/h2&gt;
&lt;p&gt;public int compareTo(Object obj);
Comparator比较器独立于实体的比较接口（比如实体无法扩展/多比较方法）
public int compare(Object o1, Object o2)
新版java建议使用lamda表达式
jdk提供Collections类&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class NewsItem implements java.lang.Comparable&amp;lt;NewsItem&amp;gt;{
       @Override
       public int compareTo(NewsItem o) {...}
}
Collections.sort(news);

public class GoodsPriceComp implements java.util.Comparator&amp;lt;Goods&amp;gt;{
       @Override
       public int compare(Goods o1, Goods o2) {...}
}
Collections.sort(list,new GoodsPriceComp());
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;127-treesettreemap&quot;&gt;127 TreeSet/TreeMap&lt;/h2&gt;
&lt;p&gt;TreeSet：元素不可以重复，元素可以排序，添加数据时自动进行排序，更改不影响顺序，TreeSet存储数据尽量不要修改（重复、顺序不对）
空构造使用Comparable接口，否则构造传入Comparator对象(可以是匿名内部类）
可以将节点中成员修改成final&lt;/p&gt;

&lt;p&gt;TreeMap的Key可以排序：使用Comparable接口或Comparator对象&lt;/p&gt;
&lt;h2 id=&quot;128-collections工具类常见方法&quot;&gt;128 Collections工具类常见方法&lt;/h2&gt;
&lt;p&gt;binarySearch、sort、reverse、shuffle洗牌、swap、&lt;/p&gt;
&lt;h2 id=&quot;129-自定义堆栈&quot;&gt;129 自定义堆栈&lt;/h2&gt;
&lt;p&gt;队列单向Queue,双向Deque： 异常/返回值， 增/删/取， 首/尾&lt;/p&gt;
&lt;h2 id=&quot;130-enumeration接口&quot;&gt;130 Enumeration接口&lt;/h2&gt;
&lt;p&gt;1.5前使用，之后使用增强版Iterator
hasMoreElement、nextElement&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Vector的elements&lt;/li&gt;
  &lt;li&gt;StringTokenizer子类&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;131-hashtable&quot;&gt;131 Hashtable&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;主要：Hashtable线程安全，同步，效率低下  &lt;br /&gt;
       HashMap线程不安全，非同步，效率相对高。&lt;/li&gt;
  &lt;li&gt;父类：Hashtable 是Dictionary,HashMap是AbstractMap&lt;/li&gt;
  &lt;li&gt;null:Hashtable键与值不能为null
        HashMap键最多一个null,值可以多个null.
HashTable子类Properties，读写资源配置文件（.property/.xml），键与值只能为字符串&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不给src，只给字节码，在bin目录下
类相对路径   xxx.class.getResourceAsStream(“/com/….”) ““表示bin，类所在的根路径
Thread.currentThread().getContextClassLoader().getResourceAsStream(“/com/….”)&lt;/p&gt;
&lt;h2 id=&quot;132-weakhashmapidentityhashmap与enummap&quot;&gt;132 WeakHashMap、IdentityHashMap与EnumMap&lt;/h2&gt;
&lt;p&gt;引用的分类：（强，软，弱，虚）：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Strong强：gc不回收，比如常量池对象&lt;/li&gt;
  &lt;li&gt;Soft软：gc可能回收，内存不足时回收&lt;/li&gt;
  &lt;li&gt;Weak弱：gc立即回收&lt;/li&gt;
  &lt;li&gt;Phantom虚：跟踪回收状态，不单独使用，与引用队列联合使用&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IdentityHashMap中key只比较地址
EnumMap中key是Enum类型&lt;/p&gt;

&lt;h2 id=&quot;133-容器同步控制只读控制&quot;&gt;133 容器同步控制、只读控制&lt;/h2&gt;
&lt;p&gt;collections.synchronizedXXX()
c.emptyXxx()       和EMPTY_xxx配合，调用者不需要判空，类似OptionXxxx
c.singletonXxx()   只包含一个元素
c.unmodifiableXxx()  只读&lt;/p&gt;
&lt;h2 id=&quot;134135-google的guava-只读约束&quot;&gt;134~135 google的Guava 只读、约束&lt;/h2&gt;
&lt;p&gt;Guava的collection &lt;br /&gt;
函数编程
ImmutableList 只读链表
Collection2.filter用Predicate
Collection2.transform用Function，Function支持组合&lt;/p&gt;

&lt;p&gt;Constraint约束：非空、长度验证
集合计算：Sets.intersection/difference/union&lt;/p&gt;
&lt;h2 id=&quot;136137-multisetmultimapbimap&quot;&gt;136~137 MultiSet,MultiMap,BiMap&lt;/h2&gt;
&lt;p&gt;Multiset 元素可以重复出现,count(E) 计数
实现有HashMultiset/TreeMultiset/LinkedHashMultiset/ConcurrentHashMultiset/ImmutableMultiset&lt;/p&gt;

&lt;p&gt;Multimap  一个键映射到多个值
BiMap  键值都不能重复
Table  双键的MAP  Table&amp;lt;rowkey, colkey, val&amp;gt;
   rowKeySet()返回”行”的集合Set&lt;R&gt;&lt;/R&gt;&lt;/p&gt;

&lt;h2 id=&quot;138--apache-commons-collections---和guava非常类似&quot;&gt;138  Apache Commons Collections   和guava非常类似&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;函数式编程 之 Predicate 断言
 封装条件或判别式  if..else替代
  1、 new EqualPredicate&lt;类型&gt;(值) 
     EqualPredicate.equalPredicate(值);
  2、NotNullPredicate.INSTANCE 
  3、UniquePredicate.uniquePredicate()
  4、自定义
     new Predicate() +evaluate  
    PredicateUtils.allPredicate  andPredicate anyPredicate
    PredicatedXxx.predicatedXxx(容器,判断)&lt;/类型&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;解耦，业务处理与判断进行分类
 函数式编程 Transformer 类型转化
 1、new Transformer() +transform
 2、SwitchTransformer   类似switch/Predicate/Transformer
 CollectionUtils.collect(容器,转换器)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;139-闭包&quot;&gt;139 闭包&lt;/h2&gt;
&lt;p&gt;封装特定的业务功能&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt; 1、Closure&lt;T&gt; 实现接口 execute(T)修改T对象, collections.forAllOn(容器，闭包）
- 2、IfClosure  IfClosure.ifClosure(断言,功能1,功能2)
- 3、WhileClosure WhileClosure.whileClosure(断言,功能,标识) 
- 4、ChainedClosure.chainedClosure(功能列表);
CollectionUtils.forAllDo(容器,功能类对象);
&lt;/T&gt;    &lt;h2 id=&quot;140-交集并集差集&quot;&gt;140 交集，并集，差集&lt;/h2&gt;
  &lt;/li&gt;
  &lt;li&gt;1、并集 CollectionUtils.union();&lt;/li&gt;
  &lt;li&gt;2、交集 CollectionUtils.intersection();
  CollectionUtils.retainAll();&lt;/li&gt;
  &lt;li&gt;3、差集
   CollectionUtils.subtract();
   &lt;/li&gt;
  &lt;li&gt;1、循环队列:CircularFifoQueue&lt;/li&gt;
  &lt;li&gt;2、只读队列:不可改变队列  UnmodifiableQueue&lt;/li&gt;
  &lt;li&gt;3、断言队列:PredicatedQueue.predicatedQueue()&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;141-对迭代器的扩展&quot;&gt;141 对迭代器的扩展&lt;/h2&gt;
&lt;p&gt;1、MapIterator 以后不再使用map.keySet.iterator访问
  IterableMap  HashedMap
 2、UniqueFilterIterator 去重迭代器 
 3、FilterIterator 自定义过滤 +Predicate
 4、LoopingIterator 循环迭代器
 5、ArrayListIterator 数组迭代器&lt;/p&gt;

&lt;p&gt;双向Map 要求键与值都不能重复
 BidiMap  inverseBidiMap()
 1、DualTreeBidiMap :有序
 2、DualHashBidiMap :无序&lt;/p&gt;

&lt;p&gt;Bag 包 允许重复， 支持getcount
 1、HashBag 无序
 2、TreeBag 有序&lt;/p&gt;
&lt;h2 id=&quot;142-集合&quot;&gt;142 集合&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;1，一张图                                                  
Collection-&amp;gt;Set/List -&amp;gt; HashSet/LinkedList/ArrayList
Map-&amp;gt;HashMap&lt;/li&gt;
  &lt;li&gt;3，三个知识点：
    &lt;ul&gt;
      &lt;li&gt;1）迭代器
            1）Itarator接口
                boolean hasNext();
                   next();
                boolean remove();
            2)foreach:java.lang.Iterable+iterator();&lt;/li&gt;
      &lt;li&gt;2）比较器:
            1)实体类可以排序java.lang.Comparable+compareTo
            2)排序比较器（解耦，多种排序规则）Comparator+compare
                list+Collection.sort();
                TreeSet
                TreeMap&lt;/li&gt;
      &lt;li&gt;3）泛型：&amp;lt;&amp;gt;
            泛型类，泛型方法，泛型接口，泛型的擦除，通配符？extends,super,泛型的嵌套&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;6.六个接口
       Collection ,Set, List,Map,Iterator,Comparable     - 9,九常用类：增删查+遍历
    &lt;ul&gt;
      &lt;li&gt;1）ArrayList&lt;/li&gt;
      &lt;li&gt;2)LinkedList&lt;/li&gt;
      &lt;li&gt;3)HashSet&lt;/li&gt;
      &lt;li&gt;4)TreeMap&lt;/li&gt;
      &lt;li&gt;5)hashMap&lt;/li&gt;
      &lt;li&gt;6)Properties&lt;/li&gt;
      &lt;li&gt;7)Hashtable&lt;/li&gt;
      &lt;li&gt;8)Stack:栈&lt;/li&gt;
      &lt;li&gt;9）Collections:工具类。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;143145-io入门之file类&quot;&gt;143~145 IO入门之File类&lt;/h2&gt;
&lt;p&gt;pathSeparator、separator
getName() 文件名、路径名
getPath()路径名
getAbsoluteFile() 绝对路径所对应的File对象
getAbsolutePath() 绝对路径名
getParent() 父目录 ,相对路径的父目录，可能为null 如. 删除本身后的结果
2、判断信息
exists()
canWrite()
canRead()
isFile()
isDirectory()
isAbsolute()：消除平台差异，ie以盘符开头，其他以/开头
3、长度 字节数  不能读取文件夹的长度
length()
4、创建、删除
createNewFile() 不存在创建新文件,存在返回false
delete() 删除文件
static createTempFile(前缀3个字节长，后缀默认.temp) 默认临时空间
staticcreateTempFile(前缀3个字节长，后缀默认.temp,目录)
deleteOnExit() 退出虚拟机删除,常用于删除临时文件
5、操作目录
mkdir() 创建目录，必须确保 父目录存在，如果不存在，创建失败
mkdirs() 创建目录，如果父目录链不存在一同创建
list() 文件|目录 名字符串形式
listFiles()
static listRoots() 根路径&lt;/p&gt;

&lt;h2 id=&quot;146io流&quot;&gt;146  IO流&lt;/h2&gt;
&lt;p&gt;二进制 字节流：InputStream、OutputStream  一切文件
文本 字符流：Reader、Writer             纯文本
节点流：包裹源头，
处理流：增强功能、提高性能&lt;/p&gt;
&lt;h2 id=&quot;147-文件读写追加&quot;&gt;147 文件读写追加&lt;/h2&gt;
&lt;p&gt;1、建立联系   File对象
       2、选择流     文件输入流  InputStream FileInputStream
       3、操作  : byte[] car =new byte[1024];  +read+读取大小
              输出
       4、释放资源 :关闭&lt;/p&gt;

&lt;h2 id=&quot;148-文件拷贝&quot;&gt;148 文件拷贝&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;1、建立联系   File对象   源头 目的地&lt;/li&gt;
  &lt;li&gt;2、选择流     &lt;br /&gt;
文件输入流  InputStream FileInputStream
文件输出流  OutputStream FileOutputStream&lt;/li&gt;
  &lt;li&gt;3、操作  :  拷贝&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;byte[] flush =new byte[1024];     
int len =0;
while(-1!=(len=输入流.read(flush))){  
  输出流.write(flush,0,len)
}
输出流.flush
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;4、释放资源 :关闭 两个流&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;149150-文件夹拷贝工具-健壮性&quot;&gt;149~150 文件夹拷贝、工具， 健壮性&lt;/h2&gt;
&lt;p&gt;1、文件 赋值  copyFile
2、文件 创建 mkdirs()
3、递归查找子孙级&lt;/p&gt;
&lt;h2 id=&quot;151-字符流只能处理纯文本&quot;&gt;151 字符流,只能处理纯文本&lt;/h2&gt;
&lt;p&gt;FileReader
FileWriter(File, 追加模式)&lt;/p&gt;
&lt;h2 id=&quot;152154-处理流&quot;&gt;152~154 处理流&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;缓冲流：
    &lt;ul&gt;
      &lt;li&gt;字节缓冲流  &lt;br /&gt;
BufferedInputStream
BufferedOutputStream&lt;/li&gt;
      &lt;li&gt;字符缓冲流  &lt;br /&gt;
BufferedReader.readLine
BufferedWriter.newLine&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;转换流:
    &lt;ul&gt;
      &lt;li&gt;字节流转为字符流:  处理乱码(编码集、解码集)  &lt;br /&gt;
编码：字符-&amp;gt;二进制  解码：二进制-&amp;gt;字符
乱码：编解码字符集不一致，  长度丢失、字节缺少， 
InputStreamReader(字节输入流,”解码集”)
OutputStreamWriter(字符输出流,”编码集”)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##155 流总结
步骤： 创建源 选择流 操作(读取|写出)释放
节点流:离数据源|程序最近的流
处理流:装饰模式 提高性能增强功能&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1、 字节流:可以处理一切(纯文本、音频、视频等)
    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;1)、输入流
InputStream  FileInputStream ByteArrayInputStream
操作:read(字节数组)&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;a)、中间容器 byte[] flush=new byte[长度]&lt;/li&gt;
          &lt;li&gt;b)、接收长度 int len =0;&lt;/li&gt;
          &lt;li&gt;c)、循环读取while(-1!=(len=流.read(flush))){}&lt;/li&gt;
          &lt;li&gt;d)、操作:输出、拷贝&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;2)、输出流 &lt;br /&gt;
OutputStream FileOutputStream ByteArrayOutputStream
操作:write(字节数组,0,长度)  输出&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;2、 字符流:只能处理纯文本 1)、输入流:Reader FileReader 操作:read(字符数组)
a)、中间容器 char[] flush=new char[长度] b)、接收长度 int len =0; c)、循环读取while(-1!=(len=流.read(flush))){} d)、操作:输出、拷贝 2）、输出流:Writer FileWriter
操作:write(字符数组,0,长度)  输出
1、 转换流:解码与编码字符集问题
1)、输入流:InputStreamReader 解码
2)、输出流:OutputStreamWriter—&amp;gt;编码&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2、缓冲流:提高性能    1)、输入流:BufferedInputStream BufferedReader    2)、输出流:BufferedOutputStream BufferedWriter&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;3、处理数据+类型 1)、基本+字符串：必须存在才能读取 读取与写出顺序一致
a)、输入流:DataInputStream readXxx
b)、输出流:DataOutputStream writeXxx 2）、引用类型:Serializable transient    a)、反序列化:ObjectInputStream readObject    b)、序列化:ObjectOutputStream writeObject&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;4、打印流: PrintStream &lt;/li&gt;
  &lt;li&gt;5、System.in out err  setIn setOut 以下流使用新增方法不能发生多态 1、ByteArrayOutputStream:  toByteArray() 2、BufferedReader: readLine() 3、BufferedWriter:newLine() 4、DataInputStream DataOutputStream 5、ObjectInputStream ObjectOutputStream 6、PrintStream &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##159 对象处理流&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;1、基本类型+String  保留数据+类型  &lt;br /&gt;
  输入流:DataInputStream    readXxx
  输出流:DataOutputStream  writeXxx&lt;/li&gt;
  &lt;li&gt;2、引用类型 (对象) 保留数据+类型  &lt;br /&gt;
反序列化 输入流:ObjectInputStream  readObject() 
序列化  输出流:ObjectOutputStream  writeObject()
注意:
1)、先序列化后反序列化；反序列化顺序必须与序列化一致
2)、不是所有的对象都可以序列化， java.io.Serializable
不是所有的属性都需要序列化，transient&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;160-关闭&quot;&gt;160 关闭&lt;/h2&gt;
&lt;p&gt;1.7以后版本支持：   try(自动关闭的资源){}&lt;/p&gt;
&lt;h2 id=&quot;161-打印流&quot;&gt;161 打印流&lt;/h2&gt;
&lt;p&gt;PrintStream  system.in
Scanner  system.out/err
System.setOut(PrintStream)
FileDescriptor.in/out/err&lt;/p&gt;
&lt;h2 id=&quot;162-io流模式-装饰&quot;&gt;162 IO流模式： 装饰&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;依赖：形参，局部变量&lt;/li&gt;
  &lt;li&gt;关联：属性，构造注入
    &lt;ul&gt;
      &lt;li&gt;聚合：属性 整体与部分 不一致的生命周期 人与手&lt;/li&gt;
      &lt;li&gt;组合: 属性 整体与部分 一致的生命周期 人与大脑&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;继承：父子类&lt;/li&gt;
  &lt;li&gt;实现：接口、实现类
    &lt;h2 id=&quot;163-超长文件夹&quot;&gt;163 超长文件夹&lt;/h2&gt;
  &lt;/li&gt;
  &lt;li&gt;不要把父目录拷贝到子目录当中
dst.getAbsolute().contains()&lt;/li&gt;
  &lt;li&gt;robocopy 删除超长目录
    &lt;h2 id=&quot;164167-randomaccessfile-文件分割合并&quot;&gt;164~167 RandomAccessFile 文件分割、合并&lt;/h2&gt;
    &lt;p&gt;多个流加入vector，作为SequenceInputStream的构造，多个流合并&lt;/p&gt;
    &lt;h2 id=&quot;168-io总结&quot;&gt;168 IO总结&lt;/h2&gt;
    &lt;h2 id=&quot;169173-多线程&quot;&gt;169~173 多线程&lt;/h2&gt;
    &lt;p&gt;main主线程，gc线程，异常线程
调用start方法，不是run方法（阻塞、串行）&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;静态代理 设计模式
 - 1、真实角色
 - 2、代理角色： 持有真实角色的引用（构造注入）
 - 3、二者 实现相同的接口
 
一、继承Thread + run() 启动:创建子类对象+对象.start() 二、实现Runnable +run() 启动:使用静态代理   1、创建真实角色   2、创建代理角色Thread(真实角色引用）x   3、代理角色.start() 推荐使用接口: 1、避免单继承局限性 2、便于共享资源，一个真实角色传递给多个thread
三、实现Callable&lt;T&gt;接口
有返回值、可以抛出异常,但使用代码麻烦
ExecutorService  ser=Executors.newFixedThreadPool(xx);
Future&lt;T&gt; result1 =ser.submit(Callable&lt;T&gt; a) ;
a.setFlag(false);
result1.get();
ser.shutdownNow();&lt;/T&gt;&lt;/T&gt;&lt;/T&gt;&lt;/p&gt;
&lt;h2 id=&quot;174177-线程状态&quot;&gt;174~177 线程状态&lt;/h2&gt;
&lt;p&gt;创建、就绪、阻塞、运行、终止 
不可以stop（废弃),通过flag通知
join :合并线程，等待对应线程的终止
yield:暂停自己的线程 静态方法
sleep:休眠，不释放锁， 与时间相关、模拟延时
isAlive/setName/getName/setPriority概率、没有先后顺序&lt;/p&gt;
&lt;h2 id=&quot;178181-同步与锁&quot;&gt;178~181 同步与锁&lt;/h2&gt;
&lt;p&gt;同步、并发：多个线程访问同一个资源
加锁  synchronized方法
synchronized块(引用类型|this|类.class){…}  注意锁定范围、锁定资源
同步:并发 多个线程访问同一份资源 确保资源安全 –&amp;gt;线程安全&lt;/p&gt;

&lt;p&gt;死锁:过多的同步容易造成死锁
   相同顺序锁定
   生产者、消费者模式， 信号灯法：  wait会释放锁&lt;/p&gt;

&lt;h2 id=&quot;182183-任务调度&quot;&gt;182~183 任务调度&lt;/h2&gt;
&lt;p&gt;Time定时器类
TimeTask定时任务类
JUC  QUARTZ&lt;/p&gt;
&lt;h2 id=&quot;184194-网络编程聊天室&quot;&gt;184~194 网络编程、聊天室&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;InetAddress 地址、DNS &lt;br /&gt;
getHostAddress/getHostName&lt;/li&gt;
  &lt;li&gt;InetSocketAddress 包含端口
getAddress/getHostName/getPort&lt;/li&gt;
  &lt;li&gt;URL
绝对路径、相对路径  getProtocol/getHost/getFile/getPath/getQuery/openStream&lt;/li&gt;
  &lt;li&gt;TCP
服务端ServerSocket  客户端Socket   getOutputStream/getInputStream&lt;/li&gt;
  &lt;li&gt;UDP
都用DatagramSocket，服务端、客户端的DatagramPacket不同
    &lt;h2 id=&quot;195207-http-server&quot;&gt;195~207 HTTP server&lt;/h2&gt;
    &lt;p&gt;httpwatch  firebug
 StringTokenizer
 java.net.URLDecoder
 反射：Obj.getClass/类.class/Class.forName(“完整类名”)
 XML：DOM/SAX/DOM4J/JDOM
 getResourceAsStream&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;208210-注解反射读取注解&quot;&gt;208~210 注解，反射读取注解&lt;/h2&gt;
&lt;p&gt;JDK5引入，对程序做解释，被其他程序读取
package/class/method/field 上添加&lt;/p&gt;

&lt;h2 id=&quot;211214-反射&quot;&gt;211~214 反射&lt;/h2&gt;
&lt;p&gt;动态语言： 程序运行时，可以改变程序结构或变量类型
运行时动态加载、探知、编译器未知的类
getFields 获取public，  getDeclareFields获取所有的
可以访问私有变量、方法， setAccessable
支持获取泛型的具体类型&lt;/p&gt;

&lt;h2 id=&quot;215-javascript脚本引擎&quot;&gt;215 javaScript脚本引擎&lt;/h2&gt;
&lt;h2 id=&quot;216217-javassist-字节码操作&quot;&gt;216~217 javassist 字节码操作&lt;/h2&gt;
&lt;p&gt;反射：性能低于字节码操作
字节码操作：动态生成类、改变类（增删改属性、方法）&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;BCEL&lt;/li&gt;
  &lt;li&gt;ASM  需要JVM指令&lt;/li&gt;
  &lt;li&gt;CGLIB 基于ASM&lt;/li&gt;
  &lt;li&gt;javassist：支持bytecode、source级别&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;XJAD反编译
导入外部jar包
增加方法、修改方法，在反射中调用增加的方法
这样可以实现 AOP、动态代理
##219 JVM核心机制
类加载过程&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;加载：class字节码到内存，静态数据转换成方法区运行时数据结构，堆中生成Class对象，作为方法区类数据的访问入口&lt;/li&gt;
  &lt;li&gt;链接：类的二进制代码合并到JVM的运行态
    &lt;ul&gt;
      &lt;li&gt;验证：确保符合规范、没有安全问题&lt;/li&gt;
      &lt;li&gt;准备：为类变量（static）分配内存、设置类变量初始值，方法区中分配&lt;/li&gt;
      &lt;li&gt;解析：VM常量池内的符号引用替换为直接引用（包括类名、方法名、变量名、常量值）&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;初始化：
    &lt;ul&gt;
      &lt;li&gt;执行类构造器clinit：类变量自动赋值、静态语句块&lt;/li&gt;
      &lt;li&gt;初始化化父类&lt;/li&gt;
      &lt;li&gt;clinit多线程安全&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;栈:   函数栈
堆：  java.lang.Class对象， 具体类对象
方法区（堆）：类运行时数据，静态变量、静态方法、常量池（类名、常量）、类代码&lt;/p&gt;

&lt;p&gt;父类静态块、子类静态块、main、父类构造、子类构造
被动引用不会初始化：比如final常量，数组定义类引用，仅使用声明静态域的类&lt;/p&gt;

&lt;h2 id=&quot;220222-类加载器&quot;&gt;220~222 类加载器&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;引导类加载器（bootstrap class loader);
java.lang.ClassLoader:加载类，加载资源（比如图片、配置文件）&lt;/li&gt;
  &lt;li&gt;扩展类加载器(extensions class loader);
sun.misc.Launcher$ExtClassLoader&lt;/li&gt;
  &lt;li&gt;应用类加载器(application class loader);
sun.misc.Launcher$AppClassLoader&lt;/li&gt;
  &lt;li&gt;自定义类加载器(从java.lang.ClassLoader);
同类+同加载器  就是同一个类&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;依次组合， 
双亲委托： 先父类加载、再自己加载， 最终导致都是从引导类开始。 安全机制：防止自定义类和语言内置的类冲突。
##223 线程上下文类加载器
线程上下文类加载器：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;一个类及其关联类应该由同一个加载器加载&lt;/li&gt;
  &lt;li&gt;接口（ext）、实现（app）不同厂商提供，&lt;/li&gt;
  &lt;li&gt;可选的加载器：应用、当前、当前线程类加载器
Tomcat类加载：app独立，为了安全， 先子类、再父类
OSGI：Open Service Gateway Initative 面向java的动态模块系统，比如Eclipse，每个模块有一个自己的类加载器，使用其他模块由对应模块导出
    Equinox 一个OSGI实现&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;224225-内部类&quot;&gt;224~225 内部类&lt;/h2&gt;
&lt;p&gt;Swing:AWT的基础上构建的一套新的图形界面系统
SWT:Standard WidgetToolkit,IBM构建的一个新的GUI库,解决AWT和swingw问题
AWT:Abstract Window Toolkit（抽象窗口工具包）,Sun不推荐使用的工具集&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;静态内部类：包含静态、非静态成员，不能调用外部类普通成员、方法&lt;/li&gt;
  &lt;li&gt;成员内部类：使用外部类所有成员，仅供外部类使用。先创建外部类对象、再通过之创建内部类对象。不能有静态成员&lt;/li&gt;
  &lt;li&gt;方法/局部内部类：不能有静态成员， 不可以引用方法中的非final变量（栈、堆对象生命周期不一致）&lt;/li&gt;
  &lt;li&gt;匿名内部类：
new InterfaceOrClass(){…};
使用方式： 继承式，接口式、参数式&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;226228-单例模式&quot;&gt;226~228 单例模式&lt;/h2&gt;
&lt;p&gt;保证一个类只能产生一个对象&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;饿汉式（线程安全，调用效率高，但是不能延迟加载）
private static CC obj= new CC(); &lt;/li&gt;
  &lt;li&gt;懒汉式（线程安全，调用效率不高，但是可以延迟加载） 
public static  synchronized CC getInstance&lt;/li&gt;
  &lt;li&gt;双重检测锁式（JVM内部原因[优化、模型]，偶尔出错，不建议用）&lt;/li&gt;
  &lt;li&gt;静态内部类（线程安全，调用效率高，可以延时加载）
private static class CCInstance {
     private static final CC obj = new CC();
}&lt;/li&gt;
  &lt;li&gt;枚举单例（枚举天然单例，线程安全，效率高，无延迟加载，无反射、序列化漏洞）
public enum CC{
INSTANCE;
public void operation(){…}
}&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;常见场景：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;windows任务管理器&lt;/li&gt;
  &lt;li&gt;回收站&lt;/li&gt;
  &lt;li&gt;读取配置文件的类&lt;/li&gt;
  &lt;li&gt;计数器&lt;/li&gt;
  &lt;li&gt;日志应用&lt;/li&gt;
  &lt;li&gt;Servlet&lt;/li&gt;
  &lt;li&gt;SpringMVC的控制器对象&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;破解单例（不包含枚举）&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;反射
 私有构造中判断obj不为null时，抛出异常&lt;/li&gt;
  &lt;li&gt;反序列化
 private Object  readResolve(){return instance;}&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;多线程测试辅助类 CountDownLatch
 UML插件：
 http://download.eclipse.org/release/helios
 AmaterasUML
 http://marketplace.eclipse.org/search/site/uml?page=1
 http://www.umlet.com/umlet_14_2/com.umlet.plugin-14.2.zip&lt;/p&gt;

&lt;h2 id=&quot;229231-工厂模式&quot;&gt;229~231 工厂模式&lt;/h2&gt;
&lt;p&gt;oop设计原则
ocp:对源码关闭，对扩展开发原则
dip:依赖翻转原则
迪米特法则：&lt;/p&gt;

&lt;p&gt;简单工厂：单个工厂，违反开闭原则， 都是静态方法，又叫静态工厂方法
工厂方法：工厂接口，多个具体工厂
抽象工厂：多个具体工厂， 每个工厂生产产品族–多个产品接口&lt;/p&gt;

&lt;p&gt;##232 建造者模式
Builder：子组件单独构造
Director：装配子组件成复杂的对象&lt;/p&gt;

&lt;p&gt;##233~234 原型模式、克隆、拷贝
当使用New关键字实例化对象的时候，很复杂，可以考虑原型模式来实现！
再则就是New对象比较耗时,克隆（clone）比较节省时间！
 implements Cloneable   –》 Object.clone()浅克隆
 也可以使用序列化、反序列化实现。&lt;/p&gt;

&lt;h2 id=&quot;235-适配器模式&quot;&gt;235 适配器模式&lt;/h2&gt;
&lt;p&gt;Target 目标接口
Adaptee 需要（被）适配的类，
Adapter  适配器，通过继承或组合Adaptee实现Target接口&lt;/p&gt;

&lt;h2 id=&quot;236238-代理模式&quot;&gt;236~238 代理模式&lt;/h2&gt;
&lt;p&gt;安全、远程、延迟加载
静态代理
动态代理 dynamic proxy，代理类不需要写、由工具自动生成&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;JDK自带
  java.lang.reflect.Proxy/InvocationHandler
  可以在handler的invoke中集中控制&lt;/li&gt;
  &lt;li&gt;javaassist字节码操作&lt;/li&gt;
  &lt;li&gt;CGLIB&lt;/li&gt;
  &lt;li&gt;ASM（底层指令，可维护性差）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;拦截器、连接池关闭处理、AOP（日志、声明式事务处理）、AspectJ&lt;/p&gt;

&lt;p&gt;##239 组合模式
树形结构表示部分、整体关系
GUI的组件、xml解析、Junit单元测试框架&lt;/p&gt;

&lt;h2 id=&quot;240-装饰模式decorator包装器wrapper桥接模式&quot;&gt;240 装饰模式Decorator、包装器Wrapper、桥接模式&lt;/h2&gt;
&lt;p&gt;动态的为一个对象增加新的功能， 继承会导致类数量膨胀
IO流、Swing图形界面、request&amp;amp;response
桥接模式解决多继承问题：对象自身沿多个维度变化&lt;/p&gt;
&lt;h2 id=&quot;241-门面模式外观模式&quot;&gt;241 门面模式、外观模式&lt;/h2&gt;
&lt;p&gt;核心：为了系统提供统一的入口，封装子系统的复杂性，便于客户端调用&lt;/p&gt;
&lt;h2 id=&quot;242-flyweight-享元模式&quot;&gt;242 FlyWeight 享元模式&lt;/h2&gt;
&lt;p&gt;共享的方式高效地支持大量细粒度对象的重用，比如围棋子
内部状态：可以共享，不会随环境变化而变化
外部状态：不可以共享，会随着环境变化而改变
线程池、DB连接池&lt;/p&gt;

&lt;h2 id=&quot;243-责任链模式-chain-of-responsibility&quot;&gt;243 责任链模式 chain of responsibility&lt;/h2&gt;
&lt;p&gt;同一类请求的对象连成一条链，所提交的请求将沿着链传递，链上的对象逐个判断是否有能力处理该请求，如果能则处理，如果不能则传递给链上的下一个对象。&lt;/p&gt;

&lt;p&gt;异常机制、servlet过滤器链式处理、struct2拦截器调用&lt;/p&gt;
&lt;h2 id=&quot;244-迭代器模式&quot;&gt;244 迭代器模式&lt;/h2&gt;
&lt;p&gt;提供一种遍历聚合对象的方式，又称游标、cursor&lt;/p&gt;
&lt;h2 id=&quot;245-中介者模式mediator&quot;&gt;245 中介者模式（Mediator&lt;/h2&gt;
&lt;p&gt;中介、协调作用： 比如中台，网状-&amp;gt;星型&lt;/p&gt;
&lt;h2 id=&quot;246-命令模式command--使用概率低&quot;&gt;246 命令模式（command）  使用概率低&lt;/h2&gt;
&lt;p&gt;将一个请求封装为一个对象，从而使我们可用不同的请求对客户进行参数化；对请求进行处理（排队、记录请求日志、撤销），也称之为：动作Action模式，事务transaction模式。
事务机制、action调用、命令撤销与恢复&lt;/p&gt;
&lt;h2 id=&quot;247-解释器模式interpreter--访问者模式-visitor-使用概率极其低&quot;&gt;247 解释器模式Interpreter  访问者模式 Visitor 使用概率极其低&lt;/h2&gt;
&lt;p&gt;开发一种新语言用： EL、正则表达式、SQL、数学表达式
尽量不用，可以考虑使用Groovy/js引擎&lt;/p&gt;

&lt;p&gt;存储在一个集合中的对象，类型不同，可以使用访问者对象来访问。
XML解析、编译器设计、复杂集合对象处理&lt;/p&gt;
&lt;h2 id=&quot;248-策略模式-strategy&quot;&gt;248 策略模式 strategy&lt;/h2&gt;
&lt;p&gt;算法剥离，通过配置等方法注入&lt;/p&gt;
&lt;h2 id=&quot;249-模板方法模式template-method&quot;&gt;249 模板方法模式（template method）&lt;/h2&gt;
&lt;p&gt;固定流程，子类覆盖特定步骤&lt;/p&gt;
&lt;h2 id=&quot;250-状态模式state&quot;&gt;250 状态模式（State）&lt;/h2&gt;
&lt;p&gt;用于解决系统中复杂对象状态转换以及不同状态下行为的封装问题
一个ConcreteState封装一个状态对应的行为
Context完成状态切换&lt;/p&gt;
&lt;h2 id=&quot;251252-观察者模式observer&quot;&gt;251~252 观察者模式（Observer）&lt;/h2&gt;
&lt;p&gt;广播机制：用于1:N的通知, 通知方式：推、拉
多个订阅者、客户称为观察者Observer，订阅内容称为目标Object
java.util.Observable/Observer&lt;/p&gt;
&lt;h2 id=&quot;253-备忘录模式memento--纪念章&quot;&gt;253 备忘录模式（memento）  纪念章&lt;/h2&gt;
&lt;p&gt;保存某个对象内部状态的拷贝，这样以后就可以将该对象恢复到原先的状态。
源发器类Originator
备忘录类Memento
负责人类CareTake
将备忘录压栈，将多个备忘录对象，序列化和持久化。&lt;/p&gt;

&lt;h2 id=&quot;254262-正则表达式&quot;&gt;254~262 正则表达式&lt;/h2&gt;
&lt;p&gt;RegexBuddy
.不包含换行，[\s\S]包含换行  \b单词边界  多行定位\A\Z   \1反向引用
（?:非捕获组表达式）  (?=后面匹配)  (?&amp;lt;=前面匹配)  (?!后面不匹配) (?&amp;lt;!前面不匹配)
默认贪婪模式，?表示非贪婪模式
Pattern.compile(r,int).matcher(string)/find()/group(int)/replaceAll()/split&lt;/p&gt;
&lt;h2 id=&quot;263276-jdbc&quot;&gt;263~276 JDBC&lt;/h2&gt;
&lt;p&gt;Mysql的客户端软件Navicat&lt;/p&gt;

&lt;p&gt;Driver/DriverManager/Connection
Statement/PrepareStatement/CallableStatement
ResultSet&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;CLOB/BLOB/时间
    &lt;ul&gt;
      &lt;li&gt;java.sql.Date/Time/Timestamp&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;批处理&lt;/li&gt;
  &lt;li&gt;事务处理  ：原子、一致、隔离、持久
-读取未提交（Read Uncommitted）
-读取已提交（Read Committed）默认
  -可重复读（Repeatable Read）
  -序列化（Serializable）
properties存储JDBC连接信息
    &lt;h2 id=&quot;277300-orm简单框架设计&quot;&gt;277~300 ORM简单框架设计&lt;/h2&gt;
    &lt;p&gt;一条记录封装到数组、Map、JavaBean
Hibernate、myBatis的简化版
联合表查询结果使用xxxVO的bean来对应。
空构造便于给反射newInstance使用
模板方法+回调接口+匿名内部类
工厂+克隆
export  JAR file  导出jar包
export  Javadoc   导出API文档&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><category term="初级" /><category term="Java" /><summary type="html">北京尚学堂高淇出品，面向大学生教授java基础知识，比较老，主要是Java6、7</summary></entry><entry><title type="html">github上的静态博客方法</title><link href="https://zerodollar.github.io/tools/github_pages/" rel="alternate" type="text/html" title="github上的静态博客方法" /><published>2017-04-10T00:00:00+08:00</published><updated>2017-04-10T00:00:00+08:00</updated><id>https://zerodollar.github.io/tools/github_pages</id><content type="html" xml:base="https://zerodollar.github.io/tools/github_pages/">&lt;p&gt;如何使用minimal-mistakes框架方便地在github上部署静态博客。&lt;/p&gt;

&lt;h2 id=&quot;选型&quot;&gt;选型&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;手工搭建  &lt;br /&gt;
参考&lt;a href=&quot;https://pages.github.com&quot;&gt;github pages说明&lt;/a&gt;、&lt;a href=&quot;https://help.github.com/categories/github-pages-basics/&quot;&gt;教程&lt;/a&gt;, 写html&lt;/li&gt;
  &lt;li&gt;使用博客框架
    &lt;ul&gt;
      &lt;li&gt;github&lt;br /&gt;
参考&lt;a href=&quot;http://blog.csdn.net/renfufei/article/details/37725057/&quot;&gt;自动页面生成器&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;hexo&lt;br /&gt;
 支持Markdown，使用Nodejs速度快，缺点：本地将markdown转换为html&lt;/li&gt;
      &lt;li&gt;jekyll&lt;br /&gt;
支持Markdown在线编辑，使用Ruby。bundle会监控文件修改自动更新。&lt;a href=&quot;http://blog.csdn.net/on_1y/article/details/19259435#t8&quot;&gt;这个教程&lt;/a&gt;不错&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;开发好的pages框架&lt;br /&gt;
jekyll系的&lt;a href=&quot;https://mmistakes.github.io/minimal-mistakes&quot;&gt;minimal-mistakes&lt;/a&gt;,&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;使用步骤&quot;&gt;使用步骤&lt;/h2&gt;
&lt;h3 id=&quot;安装&quot;&gt;安装&lt;/h3&gt;
&lt;p&gt;将&lt;a href=&quot;https://mmistakes.github.io/minimal-mistakes&quot;&gt;minimal-mistakes&lt;/a&gt; fork到自己用户名zerodollar.github.io， git clone 到本地，进入本地目录&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd zerodollar.github.io
sudo gem install jekyll bundler
bundle install
bundle exec jekyll serve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;公网访问&lt;a href=&quot;https://zerodollar.github.io&quot;&gt;https://zerodollar.github.io&lt;/a&gt;，本地访问&lt;a href=&quot;http://127.0.0.1:4000&quot;&gt;http://127.0.0.1:4000&lt;/a&gt;&lt;br /&gt;
安装gem组件时，有错误查看对应组件帮助，比如&lt;a href=&quot;http://www.nokogiri.org/tutorials/installing_nokogiri.html&quot;&gt;nokogiri&lt;/a&gt;编译失败&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install libxml2
bundle config build.nokogiri --use-system-libraries   --with-xml2-include=$(brew --prefix libxml2)/include/libxml2
bundle install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;目录结构参考&lt;a href=&quot;https://mmistakes.github.io/minimal-mistakes/docs/structure/&quot;&gt;Structure&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;配置minimal-mistakes&quot;&gt;配置minimal-mistakes&lt;/h3&gt;
&lt;p&gt;参考&lt;a href=&quot;https://mmistakes.github.io/minimal-mistakes/docs/configuration/&quot;&gt;配置&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;定制私有信息&lt;br /&gt;
locale 语言、title  主题、name、description、repository、author信息等&lt;/li&gt;
  &lt;li&gt;打开搜索 （主页右上角)
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;search: true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;导航 
修改navigation.yml， 注意url部分要在_config.yml的collections进行配置，否则访问时找不到url。&lt;/li&gt;
  &lt;li&gt;评论系统&lt;br /&gt;
业界老大disqus被墙，翻墙有教程。Disqus去&lt;a href=&quot;https://disqus.com&quot;&gt;Disqus官方网站&lt;/a&gt; 注册账号，在setting中选择add disqus to site，填写 Site URL，Site Name，Site Shortname。在&lt;名字&gt;.disqus.com中setting/advanced的Trusted Domains添加域名。  
样例使用了staticman_v2，这是一个支持github和jekyll的非常好用的静态博客评论，评论和博客在一个站点上。  
参考[STATICMAN指导](https://staticman.net/docs/index.html)
&lt;/名字&gt;    &lt;ul&gt;
      &lt;li&gt;github配置&lt;br /&gt;
博客项目Settings/Collaborators添加staticmanapp，访问https://api.staticman.net/v2/connect/zerodollar/zerodollar.github.io/， 生效请求。&lt;/li&gt;
      &lt;li&gt;jekyll配置&lt;br /&gt;
staticman.yml（staticman会读取该文件）中path修改成_data/comments目录下，并建立_data/comments目录。&lt;br /&gt;
moderation: false 表示不需要审批自动提交&lt;br /&gt;
comments: true
注意repository配置，否则可能返回错误GITHUB_READING_FILE&lt;/li&gt;
      &lt;li&gt;reCaptcha
防止机器攻击。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;RSS订阅
访问&lt;a href=&quot;https://feedburner.google.com&quot;&gt;&lt;/a&gt;Burn a feed right this instant&lt;/li&gt;
  &lt;li&gt;分享&lt;br /&gt;
百度分享 ？&lt;/li&gt;
  &lt;li&gt;自动生成分类目录&lt;br /&gt;
参考Breadcrumb
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mv docs/_pages/  .
rm _pages/about.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;删除多余文件
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rm -fr .editorconfig .gitattributes .github 
rm -fr  ./docs ./test CHANGELOG.md 
rm -fr  README.md screenshot*png
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;升级
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git remote add upstream https://github.com/mmistakes/minimal-mistakes.git
git pull upstream master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;jekyll原理&quot;&gt;Jekyll原理&lt;/h2&gt;
&lt;p&gt;参考&lt;a href=&quot;http://jekyllcn.com/docs/structure/&quot;&gt;Jekyll中国&lt;/a&gt;，是将纯文本转换为静态博客网站，核心就是一个Ruby实现的文本转换引擎：任何标记语言（比如Markdown），Jekyll套入布局中，最终生成静态页面。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;文件/ 目录&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;_config.yml&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;http://jekyllcn.com/docs/configuration/&quot;&gt;配置数据&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;_drafts&lt;/td&gt;
      &lt;td&gt;草稿，未发布的文章， –drafts选项支持预览&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;_includes&lt;/td&gt;
      &lt;td&gt;用于重用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;_layouts&lt;/td&gt;
      &lt;td&gt;用于布局&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;_posts&lt;/td&gt;
      &lt;td&gt;文章YEAR-MONTH-DAY-title.md&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;_data&lt;/td&gt;
      &lt;td&gt;预置的网站数据&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;_site&lt;/td&gt;
      &lt;td&gt;转换好后的页面&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.html&lt;br /&gt;.markdown&lt;br /&gt;.md&lt;br /&gt;.textile&lt;/td&gt;
      &lt;td&gt;含义yaml头信息，都会被转换&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;其他文件&lt;/td&gt;
      &lt;td&gt;拷贝到_site中&lt;br /&gt;assets中文件引用:&lt;code class=&quot;highlighter-rouge&quot;&gt;[下载 PDF](https://zerodollar.github.io/assets/xxx.pdf)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;头信息：设置预定义、自定义的变量，在文档中用Liquid标签来访问这些变量&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;变量名称&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;layout&lt;/td&gt;
      &lt;td&gt;使用_layouts下的对应模板文件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;permalink&lt;/td&gt;
      &lt;td&gt;修改默认的URL：/year/month/day/title.html&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;published&lt;/td&gt;
      &lt;td&gt;不展示&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;xxx&lt;/td&gt;
      &lt;td&gt;自定义变量，模板通过引用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;date&lt;/td&gt;
      &lt;td&gt;覆盖文件名中日期&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;category&lt;br /&gt;categories&lt;/td&gt;
      &lt;td&gt;除了文件夹分类，指定其他的1~n个分类属性&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;tags&lt;/td&gt;
      &lt;td&gt;类似categories&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;excerpt_separator，文章第一次匹配前部分为摘要
集合Collections，除了文章特性，还有特有的属性和命名空间&lt;/p&gt;</content><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><category term="github博客" /><category term="jekyll" /><summary type="html">如何使用minimal-mistakes框架方便地在github上部署静态博客。</summary></entry><entry><title type="html">尝试开发Mall系统</title><link href="https://zerodollar.github.io/lang/mall-dev/" rel="alternate" type="text/html" title="尝试开发Mall系统" /><published>2017-02-15T00:00:00+08:00</published><updated>2017-02-15T00:00:00+08:00</updated><id>https://zerodollar.github.io/lang/mall-dev</id><content type="html" xml:base="https://zerodollar.github.io/lang/mall-dev/">&lt;p&gt;尝试开发mall系统，简单想法。&lt;/p&gt;

&lt;h2 id=&quot;1-动静分离&quot;&gt;1. 动静分离&lt;/h2&gt;
&lt;p&gt;动静分离是将网站静态资源（HTML，JavaScript，CSS，img等文件）与后台应用分开部署，提高用户访问静态代码的速度，降低对后台应用访问。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;静态资源部署至CDN上&lt;br /&gt;
项目中的JavaScript,CSS以及img文件都是存放在CDN服务器上，将HTML文件一起存放到CDN上之后&lt;/li&gt;
  &lt;li&gt;后端API提供数据&lt;br /&gt;
后端应用提供API，根据前端的请求进行处理，并将处理结果通过JSON格式返回至前端。&lt;/li&gt;
  &lt;li&gt;前后端域名
    &lt;ul&gt;
      &lt;li&gt;相同域名&lt;br /&gt;
  用户请求api时可以避免跨域所带来的问题，相对开发更为快速，工作量也相对小一些。&lt;/li&gt;
      &lt;li&gt;不同域名&lt;br /&gt;
  兼容跨域请求的情况,JSONP 或 CORS（需要浏览器支持）&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;优点&lt;br /&gt;
api接口服务化;
前后端开发并行；
减轻后端服务器压力，提高静态资源访问速度&lt;/li&gt;
  &lt;li&gt;缺点&lt;br /&gt;
开发量变大
前后端交流成本升高
不利于网站SEO&lt;/li&gt;
  &lt;li&gt;结论&lt;br /&gt;
小项目，有扩展可能，采用： 相同域名， nginx处理静态，go提供API。&lt;br /&gt;
初始状态：user –&amp;gt; nginx –&amp;gt; mall-api –&amp;gt; mysql&lt;br /&gt;
升级版本：user –&amp;gt; CDN／ haproxy  –&amp;gt; nginx(多个)  –&amp;gt; mall-api(多个) –&amp;gt; redis集群 –&amp;gt; mysql-proxy —&amp;gt; mysql master/slave(多个)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2go实现api&quot;&gt;2.GO实现API&lt;/h2&gt;
&lt;p&gt;使用beego框架生成api&lt;/p&gt;
&lt;h3 id=&quot;21-生成api&quot;&gt;2.1 生成api&lt;/h3&gt;
&lt;p&gt;考虑用docker容器安装， 参考 &lt;a href=&quot;https://zerodollar.github.io/tools/docker&quot;&gt;docker笔记&lt;/a&gt; 启动mysql
将建表语句文件放在&lt;a href=&quot;https://zerodollar.github.io/assets/sql/mall.sql&quot;&gt;$HOME/docker/mall.sql&lt;/a&gt;中，执行建表SYS_MENU_INF, 创建mall-api&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -it --link malldb:mysql -v $HOME/docker:/home/ --rm mysql:8.0 sh -c 'exec mysql -h&quot;172.17.0.2&quot; -P3306 -uroot -prootpw mall &amp;lt;/home/mall.sql'

cd $GOPATH/src/github.com/zerodollar
bee api mall-api -tables=&quot;SYS_MENU_INF&quot; -driver=mysql -conn=&quot;root:rootpw@tcp(127.0.0.1:3306)/mall&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;生成的文件结构是&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mall-api
├── conf
│   └── app.conf
├── controllers
│   └── SYS_MENU_INF.go    对应表Post／GetOne／GetAll／Put／Delete
├── main.go
├── models
│   └── SYS_MENU_INF.go     表对应的结构
├── routers
│   └── router.go           路由 /v1/SYS_MENU_INF
└── tests
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;22-测试访问&quot;&gt;2.2 测试访问&lt;/h3&gt;
&lt;p&gt;插入预置数据到SYS_MENU_INF表中，以bee方式启动，可以监控文件变动自动编译、重启
注意检查conf/app.conf中EnableDocs = true&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd $GOPATH/src/github.com/zerodollar/mall-api
bee run watchall -gendoc=true -downdoc=true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;打开浏览器访问http://localhost:8080/v1/SYS_MENU_INF/ , 会以json返回所有记录&lt;/p&gt;

&lt;h3 id=&quot;23测试api文档&quot;&gt;2.3测试API文档&lt;/h3&gt;
&lt;p&gt;访问API文档 http://localhost:8080/swagger/,
如果要支持中文，修改mall-api/swagger/index.html,打开对应的lang注释, 重新访问就是中文了&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;script src='lang/translator.js' type='text/javascript'&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src='lang/zh-cn.js' type='text/javascript'&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;24-生成docker镜像&quot;&gt;2.4 生成docker镜像&lt;/h3&gt;
&lt;p&gt;构建linux运行包生成镜像，但docker hub只支持一个仓库,无法再push&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export GOOS=linux
go build 
cp mall-api ~/docker
docker build -f Dockerfile.mall-api -t z29759/mall-api .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;文件~/docker/Dockerfile.mall-api&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FROM scratch
ADD ./mall-api  /home/mall-api
ADD ./conf/app.conf /home/conf/app.conf
ENTRYPOINT [&quot;/home/mall-api&quot; ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;25-启动镜像&quot;&gt;2.5 启动镜像&lt;/h3&gt;
&lt;p&gt;启动镜像，访问&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export MYSQLIP=`docker inspect malldb|jq &quot;.[0].NetworkSettings.IPAddress&quot;|sed 's/&quot;//g'`
docker run -p 8080:8080   --name mallapi --link malldb:mysql -d z29759/mall-api  -db &quot;root:rootpw@tcp($MYSQLIP:3306)/mall&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;3前端&quot;&gt;3.前端&lt;/h2&gt;
&lt;p&gt;前台用 Angular2.0＋TypeScript 做js框架，使用AdminLTE做css框架&lt;/p&gt;
&lt;h3 id=&quot;使用angular-cli脚手架&quot;&gt;使用angular-cli脚手架&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo npm config set registry https://registry.npm.taobao.org
sudo npm install -g typescript typings  angular-cli@latest
ng completion 1&amp;gt;&amp;gt; ~/.oh-my-zsh/custom/zjy.zsh
ng new mall-cli  --style less
cd mall-cli
npm start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;引入-admin-lte&quot;&gt;引入 Admin-LTE&lt;/h3&gt;
&lt;p&gt;angular-cli.json 的 apps -&amp;gt; scripts -&amp;gt;添加&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        &quot;../node_modules/jquery/dist/jquery.js&quot;,
        &quot;../node_modules/bootstrap/dist/js/bootstrap.js&quot;,
        &quot;../node_modules/admin-lte/dist/js/app.js&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;package.json中dependencies增加&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;admin-lte&quot;: &quot;^2.3.8&quot;,
&quot;bootstrap&quot;: &quot;^3.3.7&quot;,
&quot;jquery&quot;: &quot;^3.1.1&quot;,
&quot;font-awesome&quot;: &quot;^4.7.0&quot;,
&quot;angular2-toaster&quot;: &quot;^1.0.2&quot;,
&quot;ng2-translate&quot;: &quot;^4.2.0&quot;,
&quot;ionicons&quot;: &quot;^3.0.0&quot;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;安装依赖插件&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;支持用户&quot;&gt;支持用户&lt;/h3&gt;
&lt;p&gt;用户模型定义／服务定义&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ng g class models/user
ng g s services/user
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;定义currentUser: ReplaySubject&lt;User&gt; ，表示User会缓存&lt;/User&gt;&lt;/p&gt;
&lt;h3 id=&quot;添加转换-service&quot;&gt;添加转换 Service&lt;/h3&gt;
&lt;p&gt;引用了use的语言设置，再设置translate&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ng g s services/translate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;assets/i18n/en.json  多语言
assets/img/   图片·
fonts   字体&lt;/p&gt;
&lt;h3 id=&quot;添加主页-components&quot;&gt;添加主页 components&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd  src/app
ng g c  pages/home
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;app-header     导航条
app-menu-aside 左侧边栏
div中router-outlet 页面内容
app-footer     脚注
app-aside      右侧边栏&lt;/p&gt;
&lt;h3 id=&quot;设置图标&quot;&gt;设置图标&lt;/h3&gt;
&lt;p&gt;fa-circle-o  类似的是从这里获取的：    http://fontawesome.io/icons/&lt;/p&gt;

&lt;h3 id=&quot;跨域&quot;&gt;跨域&lt;/h3&gt;
&lt;p&gt;参考&lt;a href=&quot;http://stackoverflow.com/questions/28216342/how-to-set-acces-control-allow-origin-in-beego-framework&quot;&gt;Stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;beego.InsertFilter(&quot;*&quot;, beego.BeforeRouter,cors.Allow(&amp;amp;cors.Options{
 AllowOrigins: []string{&quot;https://*.foo.com&quot;},
 AllowMethods: []string{&quot;PUT&quot;, &quot;PATCH&quot;},
 AllowHeaders: []string{&quot;Origin&quot;},
 ExposeHeaders: []string{&quot;Content-Length&quot;},
 AllowCredentials: true,
 }))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;参考&lt;a href=&quot;http://www.cnblogs.com/lrj567/p/6141209.html&quot;&gt;vue跨域&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; func (c *BaseController) AllowCross() {
    c.Ctx.ResponseWriter.Header().Set(&quot;Access-Control-Allow-Origin&quot;, &quot;http://localhost:8080&quot;)       //允许访问源
    c.Ctx.ResponseWriter.Header().Set(&quot;Access-Control-Allow-Methods&quot;, &quot;POST, GET, PUT, OPTIONS&quot;)    //允许post访问
    c.Ctx.ResponseWriter.Header().Set(&quot;Access-Control-Allow-Headers&quot;, &quot;Content-Type,Authorization&quot;) //header的类型
    c.Ctx.ResponseWriter.Header().Set(&quot;Access-Control-Max-Age&quot;, &quot;1728000&quot;)
    c.Ctx.ResponseWriter.Header().Set(&quot;Access-Control-Allow-Credentials&quot;, &quot;true&quot;)
    c.Ctx.ResponseWriter.Header().Set(&quot;content-type&quot;, &quot;application/json&quot;) //返回数据格式是json
}
beego.NSNamespace(&quot;/*&quot;,
            //Options用于跨域复杂请求预检
            beego.NSRouter(&quot;/*&quot;, &amp;amp;v1.BaseController{}, &quot;options:Options&quot;),
        ),
        func (c *BaseController) Options() {
    c.AllowCross() //允许跨域
    c.Data[&quot;json&quot;] = map[string]interface{}{&quot;status&quot;: 200, &quot;message&quot;: &quot;ok&quot;, &quot;moreinfo&quot;: &quot;&quot;}
    c.ServeJSON()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Refused to set unsafe header “Origin”&lt;br /&gt;
客户端的Header不需要设置Origin&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;4mysql-读写分离&quot;&gt;4.MySQL 读写分离&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jianshu.com/p/000dfd9bc3cf&quot;&gt;MySQL读写分离&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;应用层实现&lt;br /&gt;
Sprint JDBC／mhBatis／Hibernate访问数据库时配置多数据源，组件会将请求分流到不同的数据源&lt;br /&gt;
一个MasterDataSource，更新数据时用&lt;br /&gt;
一个SlaveDataSource，查询数据时用，如果有多个从，集成AbstractRoutingDataSource自己实现算法
不需要底层复杂的配置／性能较好，对应用侵入比较强／不利于扩展&lt;/li&gt;
  &lt;li&gt;代理实现&lt;br /&gt;
应用层和数据库集群间添加一个代理服务。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/xiaoyao8903/article/details/53244724&quot;&gt;MySql读写分离，及数据库高可用负载均衡的实现&lt;/a&gt;&lt;br /&gt;
proxy代理client和mysql服务，根据sql操作路由到master／或slave
实现读写分离的工具有很多，阿里巴巴的cobar/360的atlas/go写的kingshard&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;1.读写分离。&lt;/li&gt;
  &lt;li&gt;2.跨节点分表。&lt;/li&gt;
  &lt;li&gt;3.客户端IP访问控制。&lt;/li&gt;
  &lt;li&gt;4.平滑上线DB或下线DB，前端应用无感知。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;5各模块启动命令&quot;&gt;5.各模块启动命令&lt;/h2&gt;
&lt;h3 id=&quot;mysql&quot;&gt;mysql&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd mysql
docker  build -t zerodollar/mysql .
docker ps |grep malldb|awk '{print $1}'|xargs docker stop
docker ps -a|grep malldb|awk '{print $1}'|xargs docker rm
docker run --name malldb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootpw -v `pwd`/malldb_volume:/var/lib/mysql -d zerodollar/mysql
export MYSQLIP=`docker inspect --format  malldb`
docker run -it --link malldb:mysql -v `pwd`:/home/ --rm zerodollar/mysql sh -c &quot;exec mysql -h$MYSQLIP -P3306 -uroot -prootpw &amp;lt;/home/mall.sql&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果有仓库，直接push后run
没有，打包&lt;code class=&quot;highlighter-rouge&quot;&gt;tar czvf mysql.tar.gz --exclude mysql/malldb_volume mysql&lt;/code&gt;，上传aws后解压重复上面命令&lt;/p&gt;

&lt;h3 id=&quot;mall-api&quot;&gt;mall-api&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd mall-api/docker
export GOOS=&quot;linux&quot;
go build ..
cp -r ../conf .
docker build -t zerodollar/mall-api .
docker ps |grep mall-api|awk '{print $1}'|xargs docker stop
docker ps -a|grep mall-api|awk '{print $1}'|xargs docker rm
export MYSQLIP=`docker inspect --format  malldb`
export MYHOSTIP=`ifconfig en0|grep -w inet|awk '{print $2}'`
docker run -p 8080:8080  -e GOPATH=/ -e &quot;TRUST_URL=http://$MYHOSTIP&quot; --name mallapi --link malldb:zerodollar/mysql -d zerodollar/mall-api  -db &quot;root:rootpw@tcp($MYSQLIP:3306)/mall&quot;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果有仓库，直接push后run
没有，打包&lt;code class=&quot;highlighter-rouge&quot;&gt;tar czvf mall-api.tar.gz docker&lt;/code&gt;，上传aws后解压重复上面命令
开发态简单,&lt;code class=&quot;highlighter-rouge&quot;&gt;bee run&lt;/code&gt;可以监控代码改动&lt;/p&gt;

&lt;h3 id=&quot;mall-cli&quot;&gt;mall-cli&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd mall-api
rm -fr docker/dist
ng build -prod --aot=true  --output-path docker/dist
cd docker
docker build -t zerodollar/mall-cli .
docker ps |grep mall-cli|awk '{print $1}'|xargs docker stop
docker ps -a|grep mall-cli|awk '{print $1}'|xargs docker rm
docker run -p 80:80 -p 443:443 -d -t --name mall-cli zerodollar/mall-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果有仓库，直接push后run
没有，打包&lt;code class=&quot;highlighter-rouge&quot;&gt;tar czvf mall-cli.tar.gz docker&lt;/code&gt;，上传aws后解压重复上面命令
开发态简单，&lt;code class=&quot;highlighter-rouge&quot;&gt;npm start&lt;/code&gt;可以监控代码改动&lt;/p&gt;

&lt;h3 id=&quot;aws&quot;&gt;aws&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;配置默认用户ec2-user使用docker&lt;br /&gt;
通过ssh登陆aws虚拟机，配置ec2-user免sudo使用docker
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -i your_certi.pem  ec2-user@ec2****compute.amazonaws.com
sudo passwd root    #可以修改root密码
sudo systemctl  start  docker.service   #root启动docker服务
sudo usermod -a -G docker  ec2-user     #加入docker组方法1
sudo gpasswd -a ec2-user docker         #加入docker组方法2
sudo service docker restart        #重启docker服务
newgrp - docker                    #切换当前会话组为docker
groups                             #查看ec2-user用户属于组docker users
docker ps                          #跨域使用了
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;创建docker仓库&lt;br /&gt;
aws管理台登陆，启用EC2 Container Service，创建存储库 mall-api，按查看推送命令得到具体指导&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;升级aws cli&lt;br /&gt;
系统自带的aws不支持aws ecr,需要升级
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget  https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
sudo python get-pip.py
sudo pip install --upgrade awscli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;配置aws cli&lt;br /&gt;
我的安全凭证 &amp;gt; 访问密钥（访问密钥 ID 和私有访问密钥） &amp;gt; 创建访问密钥 ，需要立刻下载，后面不能再查看／下载，  访问密钥(Access Key ID),私有访问密钥(Secret Access Key)
推送命令显示&lt;code class=&quot;highlighter-rouge&quot;&gt;aws ecr get-login --region us-west-2&lt;/code&gt; 得到Default region name为us-west-2
参考aws的官方文档，配置客户端：
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aws configure
aws ecr get-login --region us-west-2  #拷贝输出信息并执行，成功后凭证保存在~/.docker/config.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;升级docker版本&lt;br /&gt;
docker 版本低，可能报&lt;code class=&quot;highlighter-rouge&quot;&gt;Error response from daemon: Cannot find child for ...&lt;/code&gt;,  升级到最新版本
由于安装的是suse，参考&lt;a href=&quot;https://docs.docker.com/engine/installation/linux/suse/&quot;&gt;docker官方文档&lt;/a&gt;升级
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ service docker stop
$ sudo zypper addrepo     https://yum.dockerproject.org/repo/main/opensuse/13.2/     docker-main
$ sudo  zypper refresh
$ zypper search -s --match-exact -t package docker-engine
$ sudo zypper install docker-engine-&amp;lt;VERSION_STRING&amp;gt;
$ sudo service docker start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;上传gz包&lt;br /&gt;
由于镜像较大，上传gz报到aws，在其上作镜像非常快
将3个gz包上传aws，&lt;code class=&quot;highlighter-rouge&quot;&gt;sftp -i your_certi.pem  ec2-user@ec2****compute.amazonaws.com&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;导入镜像&lt;br /&gt;
简单docker load&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;启动
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export AWS=920063008583.dkr.ecr.us-west-2.amazonaws.com
#启动mysql
docker run --name malldb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootpw -v ~/malldb_volume:/var/lib/mysql -d $AWS/mysql
export MYSQLIP=`docker inspect --format  malldb`
docker run -it --link malldb:${AWS}/mysql -v `pwd`:/home/ --rm ${AWS}/mysql sh -c &quot;exec mysql -h$MYSQLIP -P3306 -uroot -prootpw &amp;lt;/home/mall.sql&quot;
export MYSQLIP=`docker inspect --format  malldb`
docker run -p 8080:8080  -e GOPATH=/  --name mallapi --link malldb:$AWS/mysql -d $AWS/mall-api  -db &quot;root:rootpw@tcp($MYSQLIP:3306)/mall&quot;  
docker run -p 80:80 -p 443:443 -d -t --name mall-cli $AWS/mall-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;之后就可以通过&lt;code class=&quot;highlighter-rouge&quot;&gt;http://ec2-&amp;lt;IP&amp;gt;.us-west-2.compute.amazonaws.com/&lt;/code&gt;访问了&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;faq&quot;&gt;FAQ&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;报错：service: no such service docker
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl unmask docker.service
systemctl unmask docker.socket
systemctl start docker.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><category term="javascript" /><summary type="html">尝试开发mall系统，简单想法。</summary></entry><entry><title type="html">Docker学习</title><link href="https://zerodollar.github.io/tools/docker/" rel="alternate" type="text/html" title="Docker学习" /><published>2017-01-15T00:00:00+08:00</published><updated>2017-01-15T00:00:00+08:00</updated><id>https://zerodollar.github.io/tools/docker</id><content type="html" xml:base="https://zerodollar.github.io/tools/docker/">&lt;p&gt;Docker 学习过程&lt;/p&gt;

&lt;h2 id=&quot;1实践&quot;&gt;1.实践&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.docker.org.cn/book/docker/what-is-docker-16.html&quot;&gt;Docker入门&lt;/a&gt;，参考&lt;a href=&quot;https://docs.docker.com/engine/getstarted/step_one/&quot;&gt;官方入门&lt;/a&gt;，&lt;a href=&quot;http://yuedu.baidu.com/ebook/d817967416fc700abb68fca1?pn=1&amp;amp;rf=http%3A%2F%2Fdockone.io%2Farticle%2F233&quot;&gt;Docker 入门实战&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mac&lt;a href=&quot;https://download.docker.com/mac/stable/Docker.dmg&quot;&gt;下载&lt;/a&gt;,双击打开，将Docker拖到Applications中完成安装，再启动Docker,右上角看到鲸鱼&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#安装
docker version    #同时显示client和server的版本号
docker info       #Containers／Images／Storage／Registry等信息
docker run hello-world  ＃运行hello-world，没有image会自动下载，name是随机起的，退出后会留有一个Stopped状态的Containers，此时image是不能删除的
docker run -d -p 80:80 --name webserver nginx  #此时web可以访问
docker images  #已经安装的image
docker ps       #正在运行的进程，可以看到nginx
docker ps -a  #可以看到所有进程，包括已经退出的
docker stop webserver  #停止，webserver前面的name，ps中可以看到
docker start webserver #启动，webserver是前面指定的name
docker rm   #删除container，全部删除后对应的image才可以删除
docker rmi  #删除不用的image

docker search learn/tutorial  #查找image
docker pull learn/tutorial    #获取对应的image，镜像基于ubuntu系统
docker run learn/tutorial echo &quot;hello word&quot;  #在镜像中执行echo命令
docker run learn/tutorial apt-get install -y ping  #安装ping命令
docker commit 698 learn/ping #提交容器修改，698是容器ID，后面是name
docker run lean/ping ping www.google.com #新镜像可以ping
docker inspect  1cc  #检查镜像／容器，1cc是镜像ID或容器ID
docker push learn/ping  #发布镜像


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;2-入门资料&quot;&gt;2. 入门资料&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.open-open.com/lib/view/open1423703640748.html&quot;&gt;学习笔记&lt;/a&gt; 
&lt;a href=&quot;http://yuedu.baidu.com/ebook/d817967416fc700abb68fca1?pn=1&amp;amp;rf=http%3A%2F%2Fdockone.io%2Farticle%2F233&quot;&gt;《Docker入门实战》&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;3加速器&quot;&gt;3.加速器&lt;/h2&gt;
&lt;p&gt;下载mysql，指定8.0，不是latest。latest镜像会不断更新。&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker  pull mysql:8.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;国内比较慢，点击桌面顶栏的 docker 图标，选择 Preferences ，在 Advanced 标签下的 Registry mirrors 列表中加入加速器地址，比如&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://4cc89515.m.daocloud.io
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;点击 Apply &amp;amp; Restart 按钮使设置生效。 再试试速度。&lt;/p&gt;
&lt;h2 id=&quot;4-制作镜像&quot;&gt;4. 制作镜像&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir ~/docker;cd ~/docker
export GOOS=linux
go build zerodollar.go        # fmt.Println(&quot;vim-go at &quot;, os.Getenv(&quot;HOME&quot;))
cat Dockerfile
    FROM scratch
    ADD  ./zerodollar  /home/zerodollar
    CMD [&quot;/home/zerodollar&quot;]
docker build -t z29759/zerodollar .
docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    z29759/zerodollar   latest              31f39c2b0a14        8 minutes ago        1.646 MB
docker tag z29759/zerodollar:latest z29759/zerodollar:1
docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    z29759/zerodollar   1                   31f39c2b0a14        8 minutes ago        1.646 MB
    z29759/zerodollar   latest              31f39c2b0a14        8 minutes ago        1.646 MB
docker login -u z29759
docker push z29759/zerodollar:1
docker rmi --force 31
docker run z29759/zerodollar:1
    Status: Downloaded newer image for z29759/zerodollar:1
    vim-go at  /
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果报 &lt;code class=&quot;highlighter-rouge&quot;&gt;unauthorized: authentication required&lt;/code&gt;, 将~/.docker/config.json中的url修改成”https://index.docker.io/v1/”&lt;/p&gt;

&lt;h2 id=&quot;5启动mysql并访问&quot;&gt;5.启动mysql并访问&lt;/h2&gt;
&lt;p&gt;还有一个优化版本mysql/mysql-server，开发方便还是用mysql了，参考&lt;a href=&quot;https://hub.docker.com/_/mysql/&quot;&gt;官方文档&lt;/a&gt;如何启动／连接&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run --name malldb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootpw -v $HOME/workspace/mall/malldb_volume:/var/lib/mysql -d mysql:8.0 
docker cp  容器ID:/etc/mysql/mysql.cnf my.txt
docker exec -it malldb bash     #本容器交互式访问
/# mysql -u root -prootpw               
mysql&amp;gt; create database mall DEFAULT CHARACTER SET utf8;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;设置mysql支持utf8, 容器中拷贝出的配置文件my.txt中添加以下配置：&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;拷贝该文件到容器（原因是容器中没有vim）&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker cp my.txt 容器ID:/etc/mysql/mysql.cnf
docker stop  容器ID
docker start 容器ID
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;查看最后10行日志&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker logs --tail 10 malldb            
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;另外容器访问malldb ,首先查询mysql服务容器的ip地址，赋值给MYSQLIP。 同时-p将3306映射到宿主机的3306，也可用访问。&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export MYSQLIP=`docker inspect malldb|jq &quot;.[0].NetworkSettings.IPAddress&quot;`
export MYSQLIP=`docker inspect --format  malldb`
docker run -it --link malldb:mysql --rm mysql:8.0 sh -c 'exec mysql -h&quot;$MYSQLIP&quot; -P3306 -uroot -prootpw'    
&amp;gt; show variables like '%char%';   #查看编码
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;查看mount点&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker inspect malldb|jq &quot;.[0].Mounts&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果后面有mallapi的程序需要访问mysql，可用这样启动&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run --name mallapi --link malldb:mysql -d z29759/mallapi:1   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;直接进入容器内部&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nsenter --target `docker inspect --format   3002e553d996` --mount --uts --ipc --net --pid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><category term="docker" /><summary type="html">Docker 学习过程</summary></entry><entry><title type="html">AdminLTE了解</title><link href="https://zerodollar.github.io/lang/AdminLTE/" rel="alternate" type="text/html" title="AdminLTE了解" /><published>2017-01-15T00:00:00+08:00</published><updated>2017-01-15T00:00:00+08:00</updated><id>https://zerodollar.github.io/lang/AdminLTE</id><content type="html" xml:base="https://zerodollar.github.io/lang/AdminLTE/">&lt;p&gt;AdminLTE初步了解&lt;/p&gt;

&lt;h2 id=&quot;下载&quot;&gt;下载&lt;/h2&gt;
&lt;p&gt;参考&lt;a href=&quot;https://almsaeedstudio.com/themes/AdminLTE/documentation/index.html&quot;&gt;说明&lt;/a&gt;，安装版本不可以修改LESS文件，源码版本可以修改，但需要LESS编译器。&lt;/p&gt;

&lt;p&gt;有关&lt;a href=&quot;http://lesscss.cn&quot;&gt;LESS&lt;/a&gt;，是一门 CSS 预处理语言，它扩展了 CSS 语言，增加了变量、Mixin、函数等特性，使 CSS 更易维护和扩展。
&lt;code class=&quot;highlighter-rouge&quot;&gt;lessc styles.less styles.css&lt;/code&gt; 编译less为css&lt;/p&gt;

&lt;p&gt;基于bootstrap3和jQuery1.11以及其它一些插件，建议：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;要熟悉bootstrap3，所有组件修改适配AdminLTE&lt;/li&gt;
  &lt;li&gt;浏览主题绑定的页面&lt;/li&gt;
  &lt;li&gt;文档&lt;/li&gt;
  &lt;li&gt;使用LESS构建&lt;/li&gt;
  &lt;li&gt;github上issue／MR／贡献&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;布局&quot;&gt;布局&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Wrapper &lt;code class=&quot;highlighter-rouge&quot;&gt;.wrapper&lt;/code&gt;. A div that wraps the whole site.&lt;/li&gt;
  &lt;li&gt;Main Header &lt;code class=&quot;highlighter-rouge&quot;&gt;.main-header&lt;/code&gt;. Contains the logo and navbar.&lt;/li&gt;
  &lt;li&gt;Sidebar &lt;code class=&quot;highlighter-rouge&quot;&gt;.sidebar-wrapper&lt;/code&gt;. Contains the user panel and sidebar menu.&lt;/li&gt;
  &lt;li&gt;Content &lt;code class=&quot;highlighter-rouge&quot;&gt;.content-wrapper&lt;/code&gt;. Contains the page header and content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;布局选项&quot;&gt;布局选项&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Fixed: &lt;code class=&quot;highlighter-rouge&quot;&gt;.fixed&lt;/code&gt; 固定header and sidebar.&lt;/li&gt;
  &lt;li&gt;Collapsed Sidebar: &lt;code class=&quot;highlighter-rouge&quot;&gt;.sidebar-collapse&lt;/code&gt; 加载时折叠sidebar&lt;/li&gt;
  &lt;li&gt;Boxed Layout: &lt;code class=&quot;highlighter-rouge&quot;&gt;.layout-boxed&lt;/code&gt; 固定布局到1250px.&lt;/li&gt;
  &lt;li&gt;Top Navigation &lt;code class=&quot;highlighter-rouge&quot;&gt;.layout-top-nav&lt;/code&gt; 去除sidebar，top navbar有链接.
    &lt;h3 id=&quot;皮肤&quot;&gt;皮肤&lt;/h3&gt;
    &lt;p&gt;dist/css/skins    比如skin-blue-light&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;修改adminlte&quot;&gt;修改AdminLTE&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;修改app.js的$.AdminLTE.options&lt;/li&gt;
  &lt;li&gt;加载app.js前定义变量AdminLTEOptions&lt;/li&gt;
  &lt;li&gt;Main Header 例子增加导航／logo&lt;/li&gt;
  &lt;li&gt;Sidebar   左侧的工具栏&lt;/li&gt;
  &lt;li&gt;Control Sidebar   右侧的工具栏，可以覆盖／隐藏
&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;button class=&quot;btn btn-default&quot; data-toggle=&quot;control-sidebar&quot;&amp;gt;Toggle Right Sidebar&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Info Box 信息提示／支持进度&lt;/li&gt;
  &lt;li&gt;Box&lt;/li&gt;
  &lt;li&gt;Direct Chat&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;目录说明&quot;&gt;目录说明&lt;/h2&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dist      
bootstrap
plugins＝》fastclick／sparkline／jvectormap／slimScroll／chartjs／

.
├── Gruntfile.js  前端工作流Grunt配置
├── LICENSE
├── README.md
├── bootstrap    保存bootstrap的css／img/js
├── bower.json   
├── build        编译Less脚本
├── changelog.md
├── composer.json
├── dist         保存AdminLTE的css／img/js
├── documentation
├── index.html   例子
├── index2.html  例子2
├── package.json 包依赖
├── pages       预制页面：login.html/404.html
├── plugins     依赖的插件jQuery／chartjs ......
└── starter.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><category term="javascript" /><summary type="html">AdminLTE初步了解</summary></entry><entry><title type="html">MAC 快捷键</title><link href="https://zerodollar.github.io/tools/Mac-key/" rel="alternate" type="text/html" title="MAC 快捷键" /><published>2017-01-15T00:00:00+08:00</published><updated>2017-01-15T00:00:00+08:00</updated><id>https://zerodollar.github.io/tools/Mac-key</id><content type="html" xml:base="https://zerodollar.github.io/tools/Mac-key/">&lt;p&gt;OS X El Capitan  10.11.6  验证MAC快捷键
如果记不住，用鼠标，左上角菜单中有对应快捷键
系统的快捷键在：⌘＋space，键盘／快捷键&lt;/p&gt;

&lt;h2 id=&quot;1通用的&quot;&gt;1.通用的&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;分类&lt;/th&gt;
      &lt;th&gt;快捷键&lt;/th&gt;
      &lt;th&gt;功能&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;窗口&lt;/td&gt;
      &lt;td&gt;Command + tab&lt;/td&gt;
      &lt;td&gt;向后切换窗口&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + shift +tab&lt;/td&gt;
      &lt;td&gt;向前切换窗口&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + control + f&lt;/td&gt;
      &lt;td&gt;全屏&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + h&lt;/td&gt;
      &lt;td&gt;隐藏当前正在运行的应用程序窗口&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + w&lt;/td&gt;
      &lt;td&gt;退出一个标签窗口&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + q&lt;/td&gt;
      &lt;td&gt;退出最前面程序（看左上角）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + space&lt;/td&gt;
      &lt;td&gt;热点搜索 Spotlight&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;fn+F11&lt;/td&gt;
      &lt;td&gt;显示桌面&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + Option +D&lt;/td&gt;
      &lt;td&gt;显示／隐藏Docker&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;编辑&lt;/td&gt;
      &lt;td&gt;fn＋delete&lt;/td&gt;
      &lt;td&gt;向后删除&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Control + Space&lt;/td&gt;
      &lt;td&gt;切换输入法&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;caps lock&lt;/td&gt;
      &lt;td&gt;英文切换大小写／中文切换为输入英文&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + a&lt;/td&gt;
      &lt;td&gt;全选 select&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + c&lt;/td&gt;
      &lt;td&gt;拷贝 copy&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + f&lt;/td&gt;
      &lt;td&gt;查找 find&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + s&lt;/td&gt;
      &lt;td&gt;保存 save&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + shift ＋s&lt;/td&gt;
      &lt;td&gt;另存为 save as&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + v&lt;/td&gt;
      &lt;td&gt;粘贴&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + x&lt;/td&gt;
      &lt;td&gt;剪切 cut&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + z&lt;/td&gt;
      &lt;td&gt;撤销 undo&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + shift ＋ z&lt;/td&gt;
      &lt;td&gt;重做 redo，撤销的逆操作&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;跳转&lt;/td&gt;
      &lt;td&gt;单击&lt;/td&gt;
      &lt;td&gt;光标跳到该处&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;上/下/左/右&lt;/td&gt;
      &lt;td&gt;小范围内移动&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + 右&lt;/td&gt;
      &lt;td&gt;行尾&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + 左&lt;/td&gt;
      &lt;td&gt;行首&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + 上&lt;/td&gt;
      &lt;td&gt;页首 home&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + 下&lt;/td&gt;
      &lt;td&gt;页尾 end&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;fn ＋ 上&lt;/td&gt;
      &lt;td&gt;向上滚动一页（Page Up）　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;fn ＋ 下&lt;/td&gt;
      &lt;td&gt;向下滚动一页（Page Down）　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;fn ＋ 左&lt;/td&gt;
      &lt;td&gt;滚动至文稿开头（Home）　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;fn ＋ 右&lt;/td&gt;
      &lt;td&gt;滚动至文稿末尾（End）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Option ＋ 上&lt;/td&gt;
      &lt;td&gt;本行首，或上一行首　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Option ＋ 下&lt;/td&gt;
      &lt;td&gt;本行尾，或下一行尾　　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Option ＋ 左&lt;/td&gt;
      &lt;td&gt;上一单词开头　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Option ＋ 右&lt;/td&gt;
      &lt;td&gt;下一单词结尾&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Control + A&lt;/td&gt;
      &lt;td&gt;行首／段落首&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;选择&lt;/td&gt;
      &lt;td&gt;shift + 单击&lt;/td&gt;
      &lt;td&gt;选中光标到单击处文本&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command ＋ shift + 右&lt;/td&gt;
      &lt;td&gt;选择光标到行尾处&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command ＋ shift + 左&lt;/td&gt;
      &lt;td&gt;选择光标到行首&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command ＋ shift + 上&lt;/td&gt;
      &lt;td&gt;选择光标到页首&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command ＋ shift + 下&lt;/td&gt;
      &lt;td&gt;选择光标到页尾&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;浏览&lt;/td&gt;
      &lt;td&gt;双指上下拖动&lt;/td&gt;
      &lt;td&gt;页面上下浏览&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;截图&lt;/td&gt;
      &lt;td&gt;Command + shift + 3&lt;/td&gt;
      &lt;td&gt;截取全屏到文件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + shift + Control + 3&lt;/td&gt;
      &lt;td&gt;截取全屏到剪贴板　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + shift + 4&lt;/td&gt;
      &lt;td&gt;截取指定区域到文件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + shift + 4 + Space&lt;/td&gt;
      &lt;td&gt;截取一个窗口到文件　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + shift + Control + 4&lt;/td&gt;
      &lt;td&gt;截取指定屏幕到剪贴板&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + shift + Control + 4 + Space&lt;/td&gt;
      &lt;td&gt;截取一个窗口到剪贴板&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;系统&lt;/td&gt;
      &lt;td&gt;电源 5秒&lt;/td&gt;
      &lt;td&gt;强制关机&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + Option + Control + 电源&lt;/td&gt;
      &lt;td&gt;退出所有应用程序&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + Option + esc&lt;/td&gt;
      &lt;td&gt;打开强制退出窗口&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;.&lt;/td&gt;
      &lt;td&gt;Command + F5&lt;/td&gt;
      &lt;td&gt;打开／关闭voice over 语音朗读&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;2safari浏览器&quot;&gt;2.safari浏览器&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;快捷键&lt;/th&gt;
      &lt;th&gt;功能&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Control + Tab&lt;/td&gt;
      &lt;td&gt;转向下一个标签页　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Control + shift + Tab&lt;/td&gt;
      &lt;td&gt;转向上一个标签页　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + l&lt;/td&gt;
      &lt;td&gt;光标直接跳至地址栏　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + r&lt;/td&gt;
      &lt;td&gt;刷新　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + t&lt;/td&gt;
      &lt;td&gt;打开新页签&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + +/=&lt;/td&gt;
      &lt;td&gt;放大页面　　&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + -/_&lt;/td&gt;
      &lt;td&gt;缩小页面&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + 1..9&lt;/td&gt;
      &lt;td&gt;跳到第＊个标签页&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Space&lt;/td&gt;
      &lt;td&gt;翻页&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;3finder&quot;&gt;3.Finder&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;快捷键&lt;/th&gt;
      &lt;th&gt;功能&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;return&lt;/td&gt;
      &lt;td&gt;重命名文件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;space&lt;/td&gt;
      &lt;td&gt;预览文件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + o&lt;/td&gt;
      &lt;td&gt;打开文件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + delete&lt;/td&gt;
      &lt;td&gt;删除到废纸篓&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + shift＋delete&lt;/td&gt;
      &lt;td&gt;清空废纸篓&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + 右&lt;/td&gt;
      &lt;td&gt;展开目录&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + 左&lt;/td&gt;
      &lt;td&gt;折叠目录&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + 上&lt;/td&gt;
      &lt;td&gt;跳到父目录&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Command + 下&lt;/td&gt;
      &lt;td&gt;跳到子目录&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;4iterm2&quot;&gt;4.iTerm2&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;快捷键&lt;/th&gt;
      &lt;th&gt;功能&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Command +1..9&lt;/td&gt;
      &lt;td&gt;选择指定窗口&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</content><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><category term="MAC" /><summary type="html">OS X El Capitan 10.11.6 验证MAC快捷键 如果记不住，用鼠标，左上角菜单中有对应快捷键 系统的快捷键在：⌘＋space，键盘／快捷键</summary></entry><entry><title type="html">MAC下shell配置</title><link href="https://zerodollar.github.io/tools/developer_env/" rel="alternate" type="text/html" title="MAC下shell配置" /><published>2017-01-15T00:00:00+08:00</published><updated>2017-01-15T00:00:00+08:00</updated><id>https://zerodollar.github.io/tools/developer_env</id><content type="html" xml:base="https://zerodollar.github.io/tools/developer_env/">&lt;p&gt;While there is a shell, there is a way.&lt;/p&gt;

&lt;h2 id=&quot;1配置使用zsh&quot;&gt;1.配置使用zsh&lt;/h2&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install zsh  zsh-completions
sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
chsh &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /bin/zsh
brew install git osx autojump 
autoload &lt;span class=&quot;nt&quot;&gt;-U&lt;/span&gt; zmv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;编辑自定义的zsh配置  .oh-my-zsh/custom/zjy.zsh&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;git osx autojump&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#设置特定后缀名文件打开方式&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;open -b com.apple.safari &quot;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;history&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HISTSIZE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;200  &lt;span class=&quot;c&quot;&gt;#历史纪录条目数量&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SAVEHIST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;200  &lt;span class=&quot;c&quot;&gt;#注销后保存的历史纪录条目数量&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#设置go相关的环境变量&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOPATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/workspace/gosrc
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;.:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;:/usr/local/go/bin:&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/tool:&lt;span class=&quot;nv&quot;&gt;$GOPATH&lt;/span&gt;/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;2配置vim和go&quot;&gt;2.配置vim和go&lt;/h2&gt;
&lt;p&gt;主要用于golang开发，参考&lt;a href=&quot;https://github.com/fatih/vim-go&quot;&gt;vim-go&lt;/a&gt;安装，参考&lt;a href=&quot;https://github.com/fatih/vim-go-tutorial&quot;&gt;vim-go教学&lt;/a&gt;利用，使用vim-plug做包管理器&lt;/p&gt;
&lt;h3 id=&quot;安装vimgo&quot;&gt;安装vim/go&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew link lua
brew install vim --with-lua  #如果已安装brew unlink vim卸载
brew install go


#安装包管理器vim-plug／vim-go
curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
git clone https://github.com/fatih/vim-go.git ~/.vim/plugged/vim-go
go get github.com/fatih/vim-go-tutorial
cp $GOPATH/src/github.com/fatih/vim-go-tutorial/vimrc ~/.vimrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;安装go组件&quot;&gt;安装go组件&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:GoInstallBinaries   
:GoUpdateBinaries
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;安装neocomplete&quot;&gt;安装&lt;a href=&quot;https://github.com/Shougo/neocomplete.vim&quot;&gt;neocomplete&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;自动完成, &amp;lt;C-n&amp;gt; &amp;lt;C-p&amp;gt;  上下选择补齐项，TAB确认&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/Shougo/neocomplete.vim.git ~/.vim/plugged/neocomplete

#添加配置到 ~/.vimrc
Plug 'Shougo/neocomplete'

let g:neocomplete#enable_at_startup = 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;修改go模版增加&quot;&gt;修改go模版增加&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~/.vim/plugged/vim-go/templates／hello_world.go  
func must(err error) {
       	if err != nil {
       		panic(err)
       	}
}
func StartTime(name string) func() {
    t := time.Now()
    log.Println(&quot;entering:&quot;, name, &quot;started&quot;)
    return func() {
        d := time.Now().Sub(t)
        log.Println(&quot;leaving:&quot;, name, &quot;took&quot;, d)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;安装tagbar显示函数窗口&quot;&gt;安装&lt;a href=&quot;https://github.com/majutsushi/tagbar.git&quot;&gt;tagbar&lt;/a&gt;显示函数窗口&lt;/h3&gt;
&lt;p&gt;默认的ctags，不是tagbar要求的Exuberant ctags 5.5，配置时要指定目录&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install ctags --HEAD

git clone https://github.com/majutsushi/tagbar.git    ~/.vim/plugged/tagbar

#添加配置到 ~/.vimrc
Plug 'majutsushi/tagbar'

&quot;nmap &amp;lt;Leader&amp;gt;tb :TagbarToggle&amp;lt;CR&amp;gt;
let g:tagbar_ctags_bin='/usr/local/bin/ctags' 
let g:tagbar_width=30	
map &amp;lt;F3&amp;gt; :Tagbar&amp;lt;CR&amp;gt;
autocmd BufReadPost *.go,*.cpp,*.c,*.h,*.hpp,*.cc,*.cxx call tagbar#autoopen() 	&quot;如果是c/go语言的程序的话，tagbar自动开启
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;安装nerdtree浏览文件系统的树形资源管理&quot;&gt;安装&lt;a href=&quot;https://github.com/scrooloose/nerdtree&quot;&gt;NERDTree&lt;/a&gt;浏览文件系统的树形资源管理&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/scrooloose/nerdtree.git ~/.vim/plugged/nerdtree

#添加配置到 ~/.vimrc
Plug 'scrooloose/nerdtree'

let NERDTreeWinPos='left'
let NERDTreeWinSize=30
map &amp;lt;F2&amp;gt; :NERDTreeToggle&amp;lt;CR&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;安装状态栏-使用了airline提供更多状态栏支持&quot;&gt;安装状态栏 ，使用了Airline提供更多状态栏支持&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;安装markdown预览工具&quot;&gt;安装Markdown预览工具&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm -g install instant-markdown-d
~/.vimrc 添加Plug 'suan/vim-instant-markdown'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;安装插件&quot;&gt;安装插件&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;vim -c PlugInstall  &lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;安装beego等模块&quot;&gt;安装beego等模块&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;go get github.com/astaxie/beego
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;常用快捷键&quot;&gt;常用快捷键&lt;/h3&gt;
&lt;p&gt;参考 ~/.vimrc中配置&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;功能键&lt;/th&gt;
      &lt;th&gt;快捷键&lt;/th&gt;
      &lt;th&gt;功能&lt;/th&gt;
      &lt;th&gt; &lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoRun&lt;/td&gt;
      &lt;td&gt;&amp;lt;leader&amp;gt;r&lt;/td&gt;
      &lt;td&gt;运行&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoBuild&lt;/td&gt;
      &lt;td&gt;&amp;lt;leader&amp;gt;b&lt;/td&gt;
      &lt;td&gt;编译有错误跳转 &amp;lt;C-n&amp;gt; :cnext和&amp;lt;C-m&amp;gt; :cprevious&lt;br /&gt;关闭错误 &amp;lt;leader&amp;gt;a  :cclose&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoTest&lt;/td&gt;
      &lt;td&gt;&amp;lt;leader&amp;gt;t&lt;/td&gt;
      &lt;td&gt;测试&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoDoc&lt;/td&gt;
      &lt;td&gt;&amp;lt;leader&amp;gt;d&lt;/td&gt;
      &lt;td&gt;生成文档&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoCoverage&lt;/td&gt;
      &lt;td&gt;&amp;lt;leader&amp;gt;c&lt;/td&gt;
      &lt;td&gt;覆盖率&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoAlternate&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;切换文件，:A  :AV :AS  :AT&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoMetaLinter&lt;/td&gt;
      &lt;td&gt;&amp;lt;leader&amp;gt;l&lt;/td&gt;
      &lt;td&gt;同时运行go vet／golint／errcheck&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoDef&lt;/td&gt;
      &lt;td&gt;&amp;lt;C-t&amp;gt; &amp;lt;C-]&amp;gt;&lt;/td&gt;
      &lt;td&gt;跳转到定义处， &amp;lt;leader&amp;gt;v 垂直窗口&amp;lt;leader&amp;gt;s  水平窗口&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;&amp;lt;C-o&amp;gt;&lt;/td&gt;
      &lt;td&gt;返回上次光标处&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoDecls&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;本文件中调用该函数的地方&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoDeclsDir&lt;/td&gt;
      &lt;td&gt;&amp;lt;C-g&amp;gt;&lt;/td&gt;
      &lt;td&gt;本目录中调用该函数的地方&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoCallers&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoReferrers&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;调用该变量的地方&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoChannelPeers&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;该channel相关的地方&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoFiles&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;本包包含的文件&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoDeps&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;依赖的包&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoRename&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;修改变量名&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoFreevars&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;重构函数&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:GoImpl&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;为一个结构实现接口&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;]]&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;跳到后一个函数&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;[[&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;跳到前一个函数&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;&amp;lt;C-W-c&amp;gt;&lt;/td&gt;
      &lt;td&gt;关闭当前窗口， q／o&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;&amp;lt;C-W-hjkl&amp;gt;&lt;/td&gt;
      &lt;td&gt;窗口间切换&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:TagbarToggle&lt;/td&gt;
      &lt;td&gt;F3&lt;/td&gt;
      &lt;td&gt;打开类窗口&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;:NERDTreeToggle&lt;/td&gt;
      &lt;td&gt;F2&lt;/td&gt;
      &lt;td&gt;打开文件浏览窗口&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;a-z/”0/”+&lt;/td&gt;
      &lt;td&gt;有名寄存器／拷贝寄存器／系统剪贴板&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;:bp/:bn&lt;/td&gt;
      &lt;td&gt;同一个窗口中多个文件切换&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;3安装npm和nodejs&quot;&gt;3.安装npm和nodejs&lt;/h2&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install npm      #3.x.x更高版本
brew install nodejs   #v4.x.x更高版本
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;默认npm版本不够，从https://nodejs.org/en/download/ 下载最新版本nodejs，目前内含node 6.9.2,npm 3.10.9&lt;/p&gt;

&lt;h2 id=&quot;4安装vs-code&quot;&gt;4.安装VS code&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://code.visualstudio.com&quot;&gt;官方下载&lt;/a&gt;
安装插件&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Go语法 publisher:”lukehoban”&lt;/li&gt;
  &lt;li&gt;jslint&lt;/li&gt;
  &lt;li&gt;TypeScript Import&lt;/li&gt;
  &lt;li&gt;TSLint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;常用的快捷键：
⇧⌥F  格式化
⌘⇧P  命令面板&lt;/p&gt;

&lt;p&gt;如果只要用go，liteIDE也不错&lt;/p&gt;

&lt;h2 id=&quot;5安装angular开发环境&quot;&gt;5.安装angular开发环境&lt;/h2&gt;
&lt;p&gt;参考&lt;a href=&quot;https://angular.cn/docs/ts/latest/guide/setup.html&quot;&gt;搭建本地开发环境&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/angular/quickstart.git quickstart
cd quickstart
rm -rf .git   #不需要提交代码
npm install  #包括tsc编译器／lite-server
npm start   #ts编译器和server都是watch模式
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果没有异常，会自动打开浏览器访问3000端口&lt;/p&gt;

&lt;p&gt;用VS code打开目录quickstart开始开发&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;TypeScript
    &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; npm install -g typescript
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;TypeScript 编译器，名称叫 tsc.编译后的是同名的js文件，默认是ES3&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;6-go-多版本管理&quot;&gt;6. Go 多版本管理&lt;/h2&gt;
&lt;h3 id=&quot;下载go的pkg安装&quot;&gt;下载go的pkg安装&lt;/h3&gt;
&lt;p&gt;会在/usr/local/bin/目录。这种方式删除有点困难,找到路径删除&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pkgutil --pkgs | grep -i go    #找到包名com.googlecode.go
pkgutil --files com.googlecode.go  #找到2个路径/usr/local/go &amp;amp;/etc/paths.d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;或者使用工具&lt;a href=&quot;https://www.corecode.io/uninstallpkg/&quot;&gt;uninstallpkg&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;brew安装&quot;&gt;brew安装&lt;/h3&gt;
&lt;p&gt;会在/usr/local/Cellar/go/版本号。&lt;/p&gt;
&lt;h3 id=&quot;多个版本可以考虑用gvm安装&quot;&gt;多个版本可以考虑用gvm安装&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;zsh &amp;lt; &amp;lt;(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
source ~/.gvm/scripts/gvm
gvm listall  #访问https://go.googlesource.com/go/查看可用版本
gvm install 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;附录其它命令简单参考&quot;&gt;附录：其它命令简单参考&lt;/h2&gt;
&lt;h3 id=&quot;curl&quot;&gt;curl&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-X POST url -d '{key}&quot; 
-H &quot;User-Agent: ...&quot;  url
--user &quot;username:password&quot;  url
-L -c cookies url
-L -b cookies url
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;grep&quot;&gt;grep&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-n -E &quot;regular expressio&quot;
-C n  匹配＋前后n行
-B n  匹配＋前n行
-A n  匹配＋后n行
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;json访问利器jq&quot;&gt;JSON访问利器jq&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install jq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>ZeroDollar</name><email>z29759@gmail.com</email></author><category term="MAC" /><summary type="html">While there is a shell, there is a way.</summary></entry></feed>