﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-java随记</title><link>http://www.blogjava.net/fool/</link><description>坚持就是胜利!</description><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 18:59:41 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 18:59:41 GMT</pubDate><ttl>60</ttl><item><title>DDD小结</title><link>http://www.blogjava.net/fool/archive/2019/07/08/434108.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 08 Jul 2019 08:49:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2019/07/08/434108.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/434108.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2019/07/08/434108.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/434108.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/434108.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 充血与贫血模型&nbsp;不去具体讲概念，感兴趣的可以网上自己去找找理解一下。1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还记得初学Java时那个动物对象的例子吗？public class Dog {&nbsp;&nbsp;&nbsp;&nbsp; private int age;&nbsp;&nbsp;&nbsp; private String c...&nbsp;&nbsp;<a href='http://www.blogjava.net/fool/archive/2019/07/08/434108.html'>阅读全文</a><img src ="http://www.blogjava.net/fool/aggbug/434108.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2019-07-08 16:49 <a href="http://www.blogjava.net/fool/archive/2019/07/08/434108.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>优秀代码赏析</title><link>http://www.blogjava.net/fool/archive/2019/07/06/434083.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Sat, 06 Jul 2019 04:06:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2019/07/06/434083.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/434083.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2019/07/06/434083.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/434083.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/434083.html</trackback:ping><description><![CDATA[<div>看开源的源代码，看到一个有意思的实现 。<br />/*</div><div>&nbsp;* Copyright 2019 IBM All Rights Reserved.</div><div>&nbsp;*</div><div>&nbsp;* SPDX-License-Identifier: Apache-2.0</div><div>&nbsp;*/</div><div></div><div>package org.hyperledger.fabric.gateway;</div><div></div><div>import org.hyperledger.fabric.gateway.impl.AllCommitStrategy;</div><div>import org.hyperledger.fabric.gateway.impl.AnyCommitStrategy;</div><div>import org.hyperledger.fabric.gateway.impl.CommitHandlerImpl;</div><div>import org.hyperledger.fabric.gateway.impl.CommitStrategy;</div><div>import org.hyperledger.fabric.gateway.impl.NoOpCommitHandler;</div><div>import org.hyperledger.fabric.gateway.spi.CommitHandler;</div><div>import org.hyperledger.fabric.gateway.spi.CommitHandlerFactory;</div><div>import org.hyperledger.fabric.sdk.Peer;</div><div>import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;</div><div></div><div>import java.util.Collection;</div><div></div><div>/**</div><div>&nbsp;* Default commit handler implementations. Instances can be referenced directly or looked up by name, for example</div><div>&nbsp;* {@code DefaultCommitHandlers.valueOf("NONE")}.</div><div>&nbsp;*/</div><div>public enum DefaultCommitHandlers implements CommitHandlerFactory {</div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Do not wait for any commit events to be received from peers after submitting a transaction.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; NONE((transactionId, network) -&gt; NoOpCommitHandler.INSTANCE),</div><div></div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Wait to receive commit events from all currently responding peers in the user's organization after submitting</div><div>&nbsp; &nbsp; &nbsp;* a transaction.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; MSPID_SCOPE_ALLFORTX((transactionId, network) -&gt; {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Collection&lt;Peer&gt; peers = getPeersForOrganization(network);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitStrategy strategy = new AllCommitStrategy(peers);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return handler;</div><div>&nbsp; &nbsp; }),</div><div></div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Wait to receive commit events from all currently responding peers in the network after submitting a transaction.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; NETWORK_SCOPE_ALLFORTX((transactionId, network) -&gt; {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Collection&lt;Peer&gt; peers = network.getChannel().getPeers();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitStrategy strategy = new AllCommitStrategy(peers);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return handler;</div><div>&nbsp; &nbsp; }),</div><div></div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Wait to receive a commit event from any currently responding peer in the user's organization after submitting</div><div>&nbsp; &nbsp; &nbsp;* a transaction.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; MSPID_SCOPE_ANYFORTX((transactionId, network) -&gt; {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Collection&lt;Peer&gt; peers = getPeersForOrganization(network);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitStrategy strategy = new AnyCommitStrategy(peers);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return handler;</div><div>&nbsp; &nbsp; }),</div><div></div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Wait to receive a commit event from any currently responding peer in the network after submitting a transaction.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; NETWORK_SCOPE_ANYFORTX((transactionId, network) -&gt; {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Collection&lt;Peer&gt; peers = network.getChannel().getPeers();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitStrategy strategy = new AnyCommitStrategy(peers);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return handler;</div><div>&nbsp; &nbsp; });</div><div></div><div>&nbsp; &nbsp; private final CommitHandlerFactory factory;</div><div></div><div>&nbsp; &nbsp; DefaultCommitHandlers(CommitHandlerFactory factory) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; this.factory = factory;</div><div>&nbsp; &nbsp; }</div><div></div><div>&nbsp; &nbsp; private static Collection&lt;Peer&gt; getPeersForOrganization(Network network) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; String mspId = network.getGateway().getIdentity().getMspId();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; try {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return network.getChannel().getPeersForOrganization(mspId);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; } catch (InvalidArgumentException e) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // This should never happen as mspId should not be null</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new RuntimeException(e);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; }</div><div><br /><div>&nbsp; &nbsp;//CommitHandlerFactory 接口定义 的方法，这里是其实现&nbsp;</div></div><div>&nbsp; &nbsp; public CommitHandler create(String transactionId, Network network) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return factory.create(transactionId, network);</div><div>&nbsp; &nbsp; }</div><div>}<br /><br />先看看enum类的构造函数<br /><div>&nbsp; &nbsp; DefaultCommitHandlers(CommitHandlerFactory factory) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; this.factory = factory;</div><div>&nbsp; &nbsp; }</div>需要一个 CommitHandlerFactory 是个接口，同时 enum类本身也实现了这个接口。<br />再来看调用过程&nbsp;<br /><div>CommitHandlerFactory commitHandlerFactory = DefaultCommitHandlers.MSPID_SCOPE_ALLFORTX;</div><div></div></div><div>这里会调用CommitHandlerFactory 构造函数，其传入参数是 <br />(transactionId, network) -&gt; {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Collection&lt;Peer&gt; peers = network.getChannel().getPeers();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitStrategy strategy = new AllCommitStrategy(peers);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return handler;</div><div>&nbsp; &nbsp; }<br />它是lamdba写法，看看构造函数需要一个&nbsp;CommitHandlerFactory 接口，这个lamdba 函数其实就是CommitHandlerFactory 的实现。<br />这样MSPID_SCOPE_ALLFORTX 枚举类型就有了一个&nbsp;&nbsp;CommitHandlerFactory实现类的引用。<br /><br />再看create调用。<br /><div>CommitHandler commitHandler = commitHandlerFactory.create(transactionId, network);<br />这里enum类的create方法会执行， return factory.create(transactionId, network);<br />返回一个 CommitHandler .这里才会真正执行那个 lamdba定义的函数。<br />到这里只看到lamdb应用。。。<br />再分析一下create ,枚举类里的每个枚举变量都会实现一个这个方法。这里可以看到它其实是一个工厂类。<br />它创造的产品是CommitHandler ,其具体实现是CommitHandlerImpl类。<br />这里巧妙的使用一个enum当工厂类的实现。整个代码用了工厂模式加策略模式的实现。<br />优点：得宜于lamdb的应用，减少了具体工厂类的实现。<br />缺点：工厂模式可以实现不改动程序创建产品。那么这里如果要增一个产品，对这个enum类需要再添加一个枚举变量。<br />这个enum类有改动。<br /><br /><br /></div></div><img src ="http://www.blogjava.net/fool/aggbug/434083.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2019-07-06 12:06 <a href="http://www.blogjava.net/fool/archive/2019/07/06/434083.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个DDD示例代码</title><link>http://www.blogjava.net/fool/archive/2019/06/27/433990.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Thu, 27 Jun 2019 09:09:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2019/06/27/433990.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433990.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2019/06/27/433990.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433990.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433990.html</trackback:ping><description><![CDATA[<div>github上的一个java版的DDD实现的示例代码.&nbsp;学习DDD时看一下还是不错的。<br />https://github.com/daoqidelv/community-ddd-demo.git<br />作者不是俺！</div><img src ="http://www.blogjava.net/fool/aggbug/433990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2019-06-27 17:09 <a href="http://www.blogjava.net/fool/archive/2019/06/27/433990.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Fabric 1.1源代码分析(4) msp初始化过程</title><link>http://www.blogjava.net/fool/archive/2018/06/25/433286.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 25 Jun 2018 01:00:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2018/06/25/433286.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433286.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2018/06/25/433286.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433286.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433286.html</trackback:ping><description><![CDATA[<div>
<p style="box-sizing: border-box; outline: 0px; padding: 0px; margin: 0px 0px 16px; font-size: 16px; color: #4f4f4f; line-height: 26px; text-align: justify; word-break: break-all; font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun; background-color: #ffffff;"><span style="font-size: 10pt;">&nbsp;(MSP)是一个提供虚拟成员操作的管理框架的组件。</span><br style="font-size: 12pt;" />
<span style="font-size: 12pt;"></span><span style="font-size: 10pt;">MSP抽取出签发和验证证书以及用户认证背后的所有加密机制和协议。 MSP可以定义自己的身份概念，以及这些身份管理的规则（身份验证）和身份验证（签名生成和验证）。</span></p>
1、MSP接口定义</div>
<div></div>
<div>// MSP is the minimal Membership Service Provider Interface to be implemented</div>
<div>// to accommodate peer functionality</div>
<div>//最基本成员服务接口 其实现在mspimp.go文件中</div>
<div>type MSP interface {</div>
<div></div>
<div>// IdentityDeserializer interface needs to be implemented by MSP</div>
<div>IdentityDeserializer</div>
<div></div>
<div>// Setup the MSP instance according to configuration information</div>
<div>Setup(config *msp.MSPConfig) error</div>
<div></div>
<div>// GetVersion returns the version of this MSP</div>
<div>GetVersion() MSPVersion</div>
<div></div>
<div>// GetType returns the provider type</div>
<div>GetType() ProviderType</div>
<div></div>
<div>// GetIdentifier returns the provider identifier</div>
<div>GetIdentifier() (string, error)</div>
<div></div>
<div>// GetSigningIdentity returns a signing identity corresponding to the provided identifier</div>
<div>GetSigningIdentity(identifier *IdentityIdentifier) (SigningIdentity, error)</div>
<div></div>
<div>// GetDefaultSigningIdentity returns the default signing identity</div>
<div>GetDefaultSigningIdentity() (SigningIdentity, error)</div>
<div></div>
<div>// GetTLSRootCerts returns the TLS root certificates for this MSP</div>
<div>GetTLSRootCerts() [][]byte</div>
<div></div>
<div>// GetTLSIntermediateCerts returns the TLS intermediate root certificates for this MSP</div>
<div>GetTLSIntermediateCerts() [][]byte</div>
<div></div>
<div>// Validate checks whether the supplied identity is valid</div>
<div>Validate(id Identity) error</div>
<div></div>
<div>// SatisfiesPrincipal checks whether the identity matches</div>
<div>// the description supplied in MSPPrincipal. The check may</div>
<div>// involve a byte-by-byte comparison (if the principal is</div>
<div>// a serialized identity) or may require MSP validation</div>
<div>SatisfiesPrincipal(id Identity, principal *msp.MSPPrincipal) error</div>
<div>}</div>
<div></div>
<div>2、 BCCSP接口定义 BCCSP是加、解密及签名服务。 bccp.go文件中默认实现是sw/impl.go .</div>
<div>支持ecdsa、rsa以及aes算法 BCCSP的实现包括:</div>
<div>1,[sw]目录为the software-based implementation of the BCCSP，即基于软件的BCCSP实现，通过调用go原生支持的密码算法实现，并提供keystore来保存密钥</div>
<div>2,[pkcs11]目录，为bccsp的pkcs11实现，通过调用pkcs11接口实现相关加密操作，，密码保存在pkcs11通过pin口令保护的数据库或者硬件设备中。</div>
<div>type BCCSP interface {</div>
<div>&nbsp; &nbsp; KeyGen(opts KeyGenOpts) (k Key, err error) //生成Key</div>
<div>&nbsp; &nbsp; KeyDeriv(k Key, opts KeyDerivOpts) (dk Key, err error) //派生Key</div>
<div>&nbsp; &nbsp; KeyImport(raw interface{}, opts KeyImportOpts) (k Key, err error) //导入Key</div>
<div>&nbsp; &nbsp; GetKey(ski []byte) (k Key, err error) //获取Key</div>
<div>&nbsp; &nbsp; Hash(msg []byte, opts HashOpts) (hash []byte, err error) //哈希msg</div>
<div>&nbsp; &nbsp; GetHash(opts HashOpts) (h hash.Hash, err error) //获取哈希实例</div>
<div>&nbsp; &nbsp; Sign(k Key, digest []byte, opts SignerOpts) (signature []byte, err error) //签名</div>
<div>&nbsp; &nbsp; Verify(k Key, signature, digest []byte, opts SignerOpts) (valid bool, err error) //校验签名</div>
<div>&nbsp; &nbsp; Encrypt(k Key, plaintext []byte, opts EncrypterOpts) (ciphertext []byte, err error) //加密</div>
<div>&nbsp; &nbsp; Decrypt(k Key, ciphertext []byte, opts DecrypterOpts) (plaintext []byte, err error) //解密</div>
<div>}</div>
<div>//代码在bccsp/bccsp.go</div>
<div>3、KeyStore接口（密钥存储）定义如下： 其实现是bccsp/sw/fileks.go</div>
<div></div>
<div>type KeyStore interface {</div>
<div>&nbsp; &nbsp; ReadOnly() bool //密钥库是否只读，只读时StoreKey将失败</div>
<div>&nbsp; &nbsp; GetKey(ski []byte) (k Key, err error) //如果SKI通过，返回Key.从相关文件中加载&nbsp;</div>
<div>　　StoreKey(k Key) (err error) //将Key存储到密钥库中 sw实现是写入相关文件</div>
<div>}</div>
<div>//代码在bccsp/keystore.go</div>
<div>bccsp/sw/fileks.go中 StoreKey的实现 可见相关key写入文件</div>
<div>func (ks *fileBasedKeyStore) StoreKey(k bccsp.Key) (err error) {</div>
<div><span style="white-space:pre">	</span>if ks.readOnly {</div>
<div><span style="white-space:pre"> </span>return errors.New("Read only KeyStore.")</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>if k == nil {</div>
<div><span style="white-space:pre"> </span>return errors.New("Invalid key. It must be different from nil.")</div>
<div><span style="white-space:pre">	</span>}</div>
<div><span style="white-space:pre">	</span>switch k.(type) {</div>
<div><span style="white-space:pre">	</span>case *ecdsaPrivateKey:</div>
<div><span style="white-space:pre"> </span>kk := k.(*ecdsaPrivateKey)</div>
<div></div>
<div><span style="white-space:pre"> </span>err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>return fmt.Errorf("Failed storing ECDSA private key [%s]", err)</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>case *ecdsaPublicKey:</div>
<div><span style="white-space:pre"> </span>kk := k.(*ecdsaPublicKey)</div>
<div></div>
<div><span style="white-space:pre"> </span>err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>return fmt.Errorf("Failed storing ECDSA public key [%s]", err)</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>case *rsaPrivateKey:</div>
<div><span style="white-space:pre"> </span>kk := k.(*rsaPrivateKey)</div>
<div></div>
<div><span style="white-space:pre"> </span>err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>return fmt.Errorf("Failed storing RSA private key [%s]", err)</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>case *rsaPublicKey:</div>
<div><span style="white-space:pre"> </span>kk := k.(*rsaPublicKey)</div>
<div></div>
<div><span style="white-space:pre"> </span>err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>return fmt.Errorf("Failed storing RSA public key [%s]", err)</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>case *aesPrivateKey:</div>
<div><span style="white-space:pre"> </span>kk := k.(*aesPrivateKey)</div>
<div></div>
<div><span style="white-space:pre"> </span>err = ks.storeKey(hex.EncodeToString(k.SKI()), kk.privKey)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>return fmt.Errorf("Failed storing AES key [%s]", err)</div>
<div><span style="white-space:pre"> </span>}</div>
<div>4、mspconfig的初始化流程图</div>
<div></div>
<div><img src="http://www.blogjava.net/images/blogjava_net/fool/mspinit.png" border="0" alt="" /></div>
<div></div>
<div>其中getMspConfig方法比较重要.也一目了然，加载相关证书存入byte[].最终串行化成json</div>
<div>func getMspConfig(dir string, ID string, sigid *msp.SigningIdentityInfo) (*msp.MSPConfig, error) {</div>
<div><span style="white-space:pre">	</span>///data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/cacerts</div>
<div><span style="white-space:pre">	</span>cacertDir := filepath.Join(dir, cacerts)</div>
<div><span style="white-space:pre">	</span>///data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/admincerts</div>
<div><span style="white-space:pre">	</span>admincertDir := filepath.Join(dir, admincerts)</div>
<div></div>
<div><span style="white-space:pre">	</span>// //data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/ntermediatecerts</div>
<div><span style="white-space:pre">	</span>intermediatecertsDir := filepath.Join(dir, intermediatecerts)</div>
<div><span style="white-space:pre">	</span>///data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/crls</div>
<div><span style="white-space:pre">	</span>crlsDir := filepath.Join(dir, crlsfolder)</div>
<div><span style="white-space:pre">	</span>configFile := filepath.Join(dir, configfilename)</div>
<div><span style="white-space:pre">	</span>///data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/tlscacerts</div>
<div><span style="white-space:pre">	</span>tlscacertDir := filepath.Join(dir, tlscacerts)</div>
<div><span style="white-space:pre">	</span>tlsintermediatecertsDir := filepath.Join(dir, tlsintermediatecerts)</div>
<div></div>
<div><span style="white-space:pre">	</span>cacerts, err := getPemMaterialFromDir(cacertDir)</div>
<div><span style="white-space:pre">	</span>if err != nil || len(cacerts) == 0 {</div>
<div><span style="white-space:pre"> </span>return nil, errors.WithMessage(err, fmt.Sprintf("could not load a valid ca certificate from directory %s", cacertDir))</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>admincert, err := getPemMaterialFromDir(admincertDir)</div>
<div><span style="white-space:pre">	</span>if err != nil || len(admincert) == 0 {</div>
<div><span style="white-space:pre"> </span>return nil, errors.WithMessage(err, fmt.Sprintf("could not load a valid admin certificate from directory %s", admincertDir))</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>intermediatecerts, err := getPemMaterialFromDir(intermediatecertsDir)</div>
<div><span style="white-space:pre">	</span>if os.IsNotExist(err) {</div>
<div><span style="white-space:pre"> </span>mspLogger.Debugf("Intermediate certs folder not found at [%s]. Skipping. [%s]", intermediatecertsDir, err)</div>
<div><span style="white-space:pre">	</span>} else if err != nil {</div>
<div><span style="white-space:pre"> </span>return nil, errors.WithMessage(err, fmt.Sprintf("failed loading intermediate ca certs at [%s]", intermediatecertsDir))</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>tlsCACerts, err := getPemMaterialFromDir(tlscacertDir)</div>
<div><span style="white-space:pre">	</span>tlsIntermediateCerts := [][]byte{}</div>
<div><span style="white-space:pre">	</span>if os.IsNotExist(err) {</div>
<div><span style="white-space:pre"> </span>mspLogger.Debugf("TLS CA certs folder not found at [%s]. Skipping and ignoring TLS intermediate CA folder. [%s]", tlsintermediatecertsDir, err)</div>
<div><span style="white-space:pre">	</span>} else if err != nil {</div>
<div><span style="white-space:pre"> </span>return nil, errors.WithMessage(err, fmt.Sprintf("failed loading TLS ca certs at [%s]", tlsintermediatecertsDir))</div>
<div><span style="white-space:pre">	</span>} else if len(tlsCACerts) != 0 {</div>
<div><span style="white-space:pre"> </span>tlsIntermediateCerts, err = getPemMaterialFromDir(tlsintermediatecertsDir)</div>
<div><span style="white-space:pre"> </span>if os.IsNotExist(err) {</div>
<div><span style="white-space:pre"> </span>mspLogger.Debugf("TLS intermediate certs folder not found at [%s]. Skipping. [%s]", tlsintermediatecertsDir, err)</div>
<div><span style="white-space:pre"> </span>} else if err != nil {</div>
<div><span style="white-space:pre"> </span>return nil, errors.WithMessage(err, fmt.Sprintf("failed loading TLS intermediate ca certs at [%s]", tlsintermediatecertsDir))</div>
<div><span style="white-space:pre"> </span>}</div>
<div><span style="white-space:pre">	</span>} else {</div>
<div><span style="white-space:pre"> </span>mspLogger.Debugf("TLS CA certs folder at [%s] is empty. Skipping.", tlsintermediatecertsDir)</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>crls, err := getPemMaterialFromDir(crlsDir)</div>
<div><span style="white-space:pre">	</span>if os.IsNotExist(err) {</div>
<div><span style="white-space:pre"> </span>mspLogger.Debugf("crls folder not found at [%s]. Skipping. [%s]", crlsDir, err)</div>
<div><span style="white-space:pre">	</span>} else if err != nil {</div>
<div><span style="white-space:pre"> </span>return nil, errors.WithMessage(err, fmt.Sprintf("failed loading crls at [%s]", crlsDir))</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// Load configuration file</div>
<div><span style="white-space:pre">	</span>// if the configuration file is there then load it</div>
<div><span style="white-space:pre">	</span>// otherwise skip it</div>
<div><span style="white-space:pre">	</span>//加载配置文件&nbsp; ../msp/config.yaml 存在就加载，不存在就跳过</div>
<div><span style="white-space:pre">	</span>var ouis []*msp.FabricOUIdentifier</div>
<div><span style="white-space:pre">	</span>var nodeOUs *msp.FabricNodeOUs</div>
<div><span style="white-space:pre">	</span>_, err = os.Stat(configFile)</div>
<div><span style="white-space:pre">	</span>if err == nil {</div>
<div><span style="white-space:pre"> </span>// load the file, if there is a failure in loading it then</div>
<div><span style="white-space:pre"> </span>// return an error</div>
<div><span style="white-space:pre"> </span>raw, err := ioutil.ReadFile(configFile)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>return nil, errors.Wrapf(err, "failed loading configuration file at [%s]", configFile)</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre"> </span>configuration := Configuration{}</div>
<div><span style="white-space:pre"> </span>err = yaml.Unmarshal(raw, &amp;configuration)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>return nil, errors.Wrapf(err, "failed unmarshalling configuration file at [%s]", configFile)</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre"> </span>// Prepare OrganizationalUnitIdentifiers</div>
<div><span style="white-space:pre"> </span>if len(configuration.OrganizationalUnitIdentifiers) &gt; 0 {</div>
<div><span style="white-space:pre"> </span>for _, ouID := range configuration.OrganizationalUnitIdentifiers {</div>
<div><span style="white-space:pre"> </span>f := filepath.Join(dir, ouID.Certificate)</div>
<div><span style="white-space:pre"> </span>raw, err = readFile(f)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>return nil, errors.Wrapf(err, "failed loading OrganizationalUnit certificate at [%s]", f)</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre"> </span>oui := &amp;msp.FabricOUIdentifier{</div>
<div><span style="white-space:pre"> </span>Certificate:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raw,</div>
<div><span style="white-space:pre"> </span>OrganizationalUnitIdentifier: ouID.OrganizationalUnitIdentifier,</div>
<div><span style="white-space:pre"> </span>}</div>
<div><span style="white-space:pre"> </span>ouis = append(ouis, oui)</div>
<div><span style="white-space:pre"> </span>}</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre"> </span>// Prepare NodeOUs</div>
<div><span style="white-space:pre"> </span>if configuration.NodeOUs != nil &amp;&amp; configuration.NodeOUs.Enable {</div>
<div><span style="white-space:pre"> </span>mspLogger.Info("Loading NodeOUs")</div>
<div><span style="white-space:pre"> </span>if configuration.NodeOUs.ClientOUIdentifier == nil || len(configuration.NodeOUs.ClientOUIdentifier.OrganizationalUnitIdentifier) == 0 {</div>
<div><span style="white-space:pre"> </span>return nil, errors.New("Failed loading NodeOUs. ClientOU must be different from nil.")</div>
<div><span style="white-space:pre"> </span>}</div>
<div><span style="white-space:pre"> </span>if configuration.NodeOUs.PeerOUIdentifier == nil || len(configuration.NodeOUs.PeerOUIdentifier.OrganizationalUnitIdentifier) == 0 {</div>
<div><span style="white-space:pre"> </span>return nil, errors.New("Failed loading NodeOUs. PeerOU must be different from nil.")</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre"> </span>nodeOUs = &amp;msp.FabricNodeOUs{</div>
<div><span style="white-space:pre"> </span>Enable:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;configuration.NodeOUs.Enable,</div>
<div><span style="white-space:pre"> </span>ClientOUIdentifier: &amp;msp.FabricOUIdentifier{OrganizationalUnitIdentifier: configuration.NodeOUs.ClientOUIdentifier.OrganizationalUnitIdentifier},</div>
<div><span style="white-space:pre"> </span>PeerOUIdentifier:&nbsp; &nbsp;&amp;msp.FabricOUIdentifier{OrganizationalUnitIdentifier: configuration.NodeOUs.PeerOUIdentifier.OrganizationalUnitIdentifier},</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre"> </span>// Read certificates, if defined</div>
<div></div>
<div><span style="white-space:pre"> </span>// ClientOU</div>
<div><span style="white-space:pre"> </span>f := filepath.Join(dir, configuration.NodeOUs.ClientOUIdentifier.Certificate)</div>
<div><span style="white-space:pre"> </span>raw, err = readFile(f)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>mspLogger.Infof("Failed loading ClientOU certificate at [%s]: [%s]", f, err)</div>
<div><span style="white-space:pre"> </span>} else {</div>
<div><span style="white-space:pre"> </span>nodeOUs.ClientOUIdentifier.Certificate = raw</div>
<div><span style="white-space:pre"> </span>}</div>
<div></div>
<div><span style="white-space:pre"> </span>// PeerOU</div>
<div><span style="white-space:pre"> </span>f = filepath.Join(dir, configuration.NodeOUs.PeerOUIdentifier.Certificate)</div>
<div><span style="white-space:pre"> </span>raw, err = readFile(f)</div>
<div><span style="white-space:pre"> </span>if err != nil {</div>
<div><span style="white-space:pre"> </span>mspLogger.Debugf("Failed loading PeerOU certificate at [%s]: [%s]", f, err)</div>
<div><span style="white-space:pre"> </span>} else {</div>
<div><span style="white-space:pre"> </span>nodeOUs.PeerOUIdentifier.Certificate = raw</div>
<div><span style="white-space:pre"> </span>}</div>
<div><span style="white-space:pre"> </span>}</div>
<div><span style="white-space:pre">	</span>} else {</div>
<div><span style="white-space:pre"> </span>mspLogger.Debugf("MSP configuration file not found at [%s]: [%s]", configFile, err)</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// Set FabricCryptoConfig</div>
<div><span style="white-space:pre">	</span>cryptoConfig := &amp;msp.FabricCryptoConfig{</div>
<div><span style="white-space:pre"> </span>SignatureHashFamily:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bccsp.SHA2,</div>
<div><span style="white-space:pre"> </span>IdentityIdentifierHashFunction: bccsp.SHA256,</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// Compose FabricMSPConfig</div>
<div><span style="white-space:pre">	</span>fmspconf := &amp;msp.FabricMSPConfig{</div>
<div><span style="white-space:pre"> </span>Admins:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; admincert,</div>
<div><span style="white-space:pre"> </span>RootCerts:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cacerts,</div>
<div><span style="white-space:pre"> </span>IntermediateCerts: intermediatecerts,</div>
<div><span style="white-space:pre"> </span>SigningIdentity:&nbsp; &nbsp;sigid,</div>
<div><span style="white-space:pre"> </span>Name:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ID,</div>
<div><span style="white-space:pre"> </span>OrganizationalUnitIdentifiers: ouis,</div>
<div><span style="white-space:pre"> </span>RevocationList:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; crls,</div>
<div><span style="white-space:pre"> </span>CryptoConfig:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cryptoConfig,</div>
<div><span style="white-space:pre"> </span>TlsRootCerts:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tlsCACerts,</div>
<div><span style="white-space:pre"> </span>TlsIntermediateCerts:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tlsIntermediateCerts,</div>
<div><span style="white-space:pre"> </span>FabricNodeOUs:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nodeOUs,</div>
<div><span style="white-space:pre">	</span>}</div>
<div>&nbsp; &nbsp; //串行化成json格式的byte[]&nbsp;</div>
<div><span style="white-space:pre">	</span>fmpsjs, _ := proto.Marshal(fmspconf)</div>
<div><span style="white-space:pre">	</span>&nbsp;</div>
<div><span style="white-space:pre">	</span> //MSPConfig的msp_config.pb.go文件中定义&nbsp;</div>
<div>&nbsp; &nbsp; //type MSPConfig struct {</div>
<div><span style="white-space:pre">	</span>//Type int32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"`</div>
<div><span style="white-space:pre">	</span>//Config []byte `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"`</div>
<div>&nbsp; &nbsp; //}</div>
<div><span style="white-space:pre">	</span>mspconf := &amp;msp.MSPConfig{Config: fmpsjs, Type: int32(FABRIC)}</div>
<div></div>
<div><span style="white-space:pre">	</span>return mspconf, nil</div>
<div></div>
<div></div>
<div>msp/mspimplsetup.go文件中根据上面生成的mspconf对证书进行了相关设置,结果保存</div>
<div></div>
<div>在/mspimpl.go中的结体bccspmsp中</div>
<div>func (msp *bccspmsp) preSetupV1(conf *m.FabricMSPConfig) error {</div>
<div><span style="white-space:pre">	</span>// setup crypto config</div>
<div><span style="white-space:pre">	</span>if err := msp.setupCrypto(conf); err != nil {</div>
<div><span style="white-space:pre"> </span>return err</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// Setup CAs&nbsp; //设置ca证书，中间证书等，涉及到x509包。并构建相关identity类。</div>
<div><span style="white-space:pre">	</span>//根据证书内容加hash后生成identity类</div>
<div><span style="white-space:pre">	</span>if err := msp.setupCAs(conf); err != nil {</div>
<div><span style="white-space:pre"> </span>return err</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// Setup Admins</div>
<div><span style="white-space:pre">	</span>if err := msp.setupAdmins(conf); err != nil {</div>
<div><span style="white-space:pre"> </span>return err</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// Setup CRLs</div>
<div><span style="white-space:pre">	</span>if err := msp.setupCRLs(conf); err != nil {</div>
<div><span style="white-space:pre"> </span>return err</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// Finalize setup of the CAs</div>
<div><span style="white-space:pre">	</span>if err := msp.finalizeSetupCAs(conf); err != nil {</div>
<div><span style="white-space:pre"> </span>return err</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// setup the signer (if present)</div>
<div><span style="white-space:pre">	</span>if err := msp.setupSigningIdentity(conf); err != nil {</div>
<div><span style="white-space:pre"> </span>return err</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// setup TLS CAs</div>
<div><span style="white-space:pre">	</span>if err := msp.setupTLSCAs(conf); err != nil {</div>
<div><span style="white-space:pre"> </span>return err</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>// setup the OUs</div>
<div><span style="white-space:pre">	</span>if err := msp.setupOUs(conf); err != nil {</div>
<div><span style="white-space:pre"> </span>return err</div>
<div><span style="white-space:pre">	</span>}</div>
<div></div>
<div><span style="white-space:pre">	</span>return nil</div>
<div>}</div>
<div></div><img src ="http://www.blogjava.net/fool/aggbug/433286.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2018-06-25 09:00 <a href="http://www.blogjava.net/fool/archive/2018/06/25/433286.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Fabric 1.1源代码分析(3) 系统链码执行过程示例(弟弟篇）</title><link>http://www.blogjava.net/fool/archive/2018/06/13/433279.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Wed, 13 Jun 2018 06:37:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2018/06/13/433279.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433279.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2018/06/13/433279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433279.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433279.html</trackback:ping><description><![CDATA[<div style="color: #d4d4d4; background-color: #1e1e1e; font-family: Consolas, &quot;Courier New&quot;, monospace; line-height: 19px; white-space: pre;"><div><span style="color: #569cd6;font-weight: bold;"># Fabric 1.1源代码分析(3) 系统链码执行过程</span></div><div><span style="color: #569cd6;font-weight: bold;">## 1、系统链码执行过程</span></div><div><span style="color: #6796e6;">*</span>  以peer channel join -b gensis.block命令为例。该命令结果是peer节点加入通道.    </div><div>这个命令会单独启一个进程.在该进程中会构建一个名称为cscc的链码消息传到peer节点.  </div><div>通过grpc调用最终会进到endorser.go中的ProcessProposal函数进行处理。</div><div>   参考Fabric 1.1源代码分析(2)http://www.blogjava.net/fool/archive/2018/06/12/433277.html   <br />系统链码初始化过程,可以找到../shim/handler.go中</div><div>的handleTransaction()函数.最终会调用res := handler.cc.Invoke(stub).这里的</div><div>cc就是importsysccs.go文件中systemChaincodes数组中的cscc系统链码的.&nbsp;&nbsp;&nbsp;&nbsp;  </div><div>Chaincode,其实例是&amp;cscc.PeerConfiger{},实现在cscc/configure.go文件中。每个系统</div><div>链码都实现了这个Chaincode接口()</div><div>```go</div><div><span style="color: #569cd6;">type</span> <span style="color: #4ec9b0;">Chaincode</span> <span style="color: #569cd6;">interface</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// Init is called during Instantiate transaction after the chaincode container</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// has been established for the first time, allowing the chaincode to</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// initialize its internal data</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;Init(stub ChaincodeStubInterface) pb.Response</div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// Invoke is called to update or query the ledger in a proposal transaction.</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// Updated state variables are not committed to the ledger until the</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// transaction is committed.</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;Invoke(stub ChaincodeStubInterface) pb.Response</div><div>}</div><div>```</div><br /><div><span style="color: #6796e6;">*</span>  至此就可以清晰地看到每一个系统链码都会启动一对协程，通过chan通信。系统链码消息由    </div><div>shim/handler.go中的函数处理.并且这里最终调用各自的具体实现的Ivoke方法进行业务处理  </div><br /><div><span style="color: #569cd6;font-weight: bold;">## 2、peer channel join命令处理流程图</span></div><div><span style="color: #6796e6;">*</span> peer channel join命令会调用configure.go中的Excute方法。对应cscc系统链码的处理，  </div><div>原因如下，以下流程图大致可以了解cscc都做了些什么</div><div>![](<span style="text-decoration-line: underline;">cscc.png</span>)<br /><img src="http://www.blogjava.net/images/blogjava_net/fool/cscc.png" border="0" alt="" width="1000" height="459" /></div><br /><div><span style="color: #569cd6;font-weight: bold;">## 3、小结</span></div><br /><div><span style="color: #6796e6;">*</span> 上面的流程图也不是非常地强细，忽略掉了一些方法。但是有了整个流程的理解，就能理解其  </div><div>它系统链码的调用过程，需要时直接细读其实现就好了。从上流程图中可以看到文件末尾添加区  </div><div>区块，leveldb中记录了区块号，索引位置信息等等。另外因为系统链码跟一般链码虽然经过</div><div>的文件基本一样，但最终处理方式还是不一样，一个是协程，一个是grpc.可能参考Fabric 1.1  </div><div>源代码分析之 Chaincode（链码）初始化 http://www.blogjava.net/fool/archive/2018/06/12/433275.html</div></div><img src ="http://www.blogjava.net/fool/aggbug/433279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2018-06-13 14:37 <a href="http://www.blogjava.net/fool/archive/2018/06/13/433279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Fabric 1.1源代码分析之 系统链码初始化过程(哥哥篇)</title><link>http://www.blogjava.net/fool/archive/2018/06/12/433277.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Tue, 12 Jun 2018 07:00:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2018/06/12/433277.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433277.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2018/06/12/433277.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433277.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433277.html</trackback:ping><description><![CDATA[<div style="color: #d4d4d4; background-color: #1e1e1e; font-family: Consolas, &quot;Courier New&quot;, monospace; line-height: 19px; white-space: pre;"><div style="line-height: 19px;"><div><span style="color: #569cd6;font-weight: bold;"># Fabric 1.1源代码分析之 Fabric 1.1源代码分析 系统链码初始化过程<br /><br />* 链码这一块的代码非常的绕。基本上就是一个大循环。限于水平或者其它原因，差露可能难免，各位看官包涵则个...</span></div><br /><div><span style="color: #569cd6;font-weight: bold;">## 1、系统链码</span></div><br /><div><span style="color: #6796e6;">*</span> 系统链码跟智能合约链码涉及到的文件差不多，流程也差不多。只是智能合约是grpc,系统链码是chan实现调用.</div><div>LSCC Lifecycle system chaincode，处理生命周期请求。我理解的生命周期请求应该指的是一个chaincode的安装，实例化，升级，</div><div>卸载等对其生命周期起关键作用的一系列操作请求。</div><div>CSCC Configuration system chaincode，处理在peer程序端的channel配置。</div><div>QSCC Query system chaincode，提供账本查询接口，如获取块和交易信息。</div><div>ESCC Endorsement system chaincode，通过对交易申请的应答信息进行签名，来提供背书功能。</div><div>VSCC Validation system chaincode，处理交易校验，包括检查背书策略和版本在并发时的控制。</div><br /><div><span style="color: #569cd6;font-weight: bold;">## 2、系统链码注册</span></div><div><span style="color: #6796e6;">*</span> 在/core/chaincode/shim/interfaces_stable.go中实现了下面的接口</div><div>```go</div><div><span style="color: #569cd6;">type</span> <span style="color: #4ec9b0;">Chaincode</span> <span style="color: #569cd6;">interface</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// Init is called during Instantiate transaction after the chaincode container</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// has been established for the first time, allowing the chaincode to</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// initialize its internal data</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;Init(stub ChaincodeStubInterface) pb.Response</div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// Invoke is called to update or query the ledger in a proposal transaction.</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// Updated state variables are not committed to the ledger until the</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// transaction is committed.</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;Invoke(stub ChaincodeStubInterface) pb.Response</div><div>}</div><div>```</div><br /><div><span style="color: #6796e6;">*</span> 在core/scc/sysccapi.go中定义了SystemChaincode结构体，其中定义了 Chaincode接口变量</div><div>```go</div><div><span style="color: #569cd6;">type</span> <span style="color: #4ec9b0;">SystemChaincode</span> <span style="color: #569cd6;">struct</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">//Unique name of the system chaincode</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;Name <span style="color: #4ec9b0;">string</span></div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">//Path to the system chaincode; currently not used</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;Path <span style="color: #4ec9b0;">string</span></div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">//InitArgs initialization arguments to startup the system chaincode</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;InitArgs [][]<span style="color: #4ec9b0;">byte</span></div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// Chaincode is the actual chaincode object</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;Chaincode shim.Chaincode</div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// InvokableExternal keeps track of whether</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// this system chaincode can be invoked</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// through a proposal sent to this peer</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;InvokableExternal <span style="color: #4ec9b0;">bool</span></div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// InvokableCC2CC keeps track of whether</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// this system chaincode can be invoked</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// by way of a chaincode-to-chaincode</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// invocation</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;InvokableCC2CC <span style="color: #4ec9b0;">bool</span></div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// Enabled a convenient switch to enable/disable system chaincode without</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">// having to remove entry from importsysccs.go</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;Enabled <span style="color: #4ec9b0;">bool</span></div><div>}</div><div>```</div><br /><div><span style="color: #6796e6;">*</span> 在 core/scc/importsysccs.go文件中对系统链码进行了初始化，并且每个Chainoce指定了具体实现 </div><div>在</div><div>```go</div><div><span style="color: #608b4e;">//see systemchaincode_test.go for an example using "sample_syscc"</span></div><div><span style="color: #569cd6;">var</span> systemChaincodes = []*SystemChaincode{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enabled:           <span style="color: #569cd6;">true</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name:              <span style="color: #ce9178;">"cscc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Path:              <span style="color: #ce9178;">"github.com/hyperledger/fabric/core/scc/cscc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitArgs:          [][]<span style="color: #4ec9b0;">byte</span>{[]byte(<span style="color: #ce9178;">""</span>)},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chaincode:         &amp;cscc.PeerConfiger{},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvokableExternal: <span style="color: #569cd6;">true</span>, <span style="color: #608b4e;">// cscc is invoked to join a channel</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enabled:           <span style="color: #569cd6;">true</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name:              <span style="color: #ce9178;">"lscc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Path:              <span style="color: #ce9178;">"github.com/hyperledger/fabric/core/scc/lscc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitArgs:          [][]<span style="color: #4ec9b0;">byte</span>{[]byte(<span style="color: #ce9178;">""</span>)},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chaincode:         lscc.NewLifeCycleSysCC(),</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvokableExternal: <span style="color: #569cd6;">true</span>, <span style="color: #608b4e;">// lscc is invoked to deploy new chaincodes</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvokableCC2CC:    <span style="color: #569cd6;">true</span>, <span style="color: #608b4e;">// lscc can be invoked by other chaincodes</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enabled:   <span style="color: #569cd6;">true</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name:      <span style="color: #ce9178;">"escc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Path:      <span style="color: #ce9178;">"github.com/hyperledger/fabric/core/scc/escc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitArgs:  [][]<span style="color: #4ec9b0;">byte</span>{[]byte(<span style="color: #ce9178;">""</span>)},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chaincode: &amp;escc.EndorserOneValidSignature{},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enabled:   <span style="color: #569cd6;">true</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name:      <span style="color: #ce9178;">"vscc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Path:      <span style="color: #ce9178;">"github.com/hyperledger/fabric/core/scc/vscc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitArgs:  [][]<span style="color: #4ec9b0;">byte</span>{[]byte(<span style="color: #ce9178;">""</span>)},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chaincode: &amp;vscc.ValidatorOneValidSignature{},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enabled:           <span style="color: #569cd6;">true</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name:              <span style="color: #ce9178;">"qscc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Path:              <span style="color: #ce9178;">"github.com/hyperledger/fabric/core/chaincode/qscc"</span>,</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitArgs:          [][]<span style="color: #4ec9b0;">byte</span>{[]byte(<span style="color: #ce9178;">""</span>)},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chaincode:         &amp;qscc.LedgerQuerier{},</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvokableExternal: <span style="color: #569cd6;">true</span>, <span style="color: #608b4e;">// qscc can be invoked to retrieve blocks</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvokableCC2CC:    <span style="color: #569cd6;">true</span>, <span style="color: #608b4e;">// qscc can be invoked to retrieve blocks also by a cc</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;},</div><div>}</div><div>```</div><div><span style="color: #6796e6;">*</span> 注册流程图</div><div>![](<span style="text-decoration-line: underline;">systemcoderegist.png</span>)<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/fool/systemcoderegist.png" border="0" alt="" /></div><br /><div><span style="color: #569cd6;font-weight: bold;">## 3、系统链码初始化</span></div><div><span style="color: #6796e6;">*</span> 系统注册完成后会对链码初始化.跟一般chaincode稍有不同的是chaincode在合约里通过grpc与peer节点交互。</div><div>而系统链码则是在协程里通过chan 实现交互.下面代码创建两个&nbsp;peerRcvCCSend := make(chan *pb.ChaincodeMessage)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;ccRcvPeerSend := make(chan *pb.ChaincodeMessage)  ，是客户端和服务端共同的参数</div><div>```go</div><br /><div><span style="color: #569cd6;">func</span> (ipc *inprocContainer) launchInProc(ctxt context.Context, id <span style="color: #4ec9b0;">string</span>, args []<span style="color: #4ec9b0;">string</span>, env []<span style="color: #4ec9b0;">string</span>, ccSupport ccintf.CCSupport) <span style="color: #569cd6;">error</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;peerRcvCCSend := <span style="color: #dcdcaa;">make</span>(<span style="color: #569cd6;">chan</span> *pb.ChaincodeMessage)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;ccRcvPeerSend := <span style="color: #dcdcaa;">make</span>(<span style="color: #569cd6;">chan</span> *pb.ChaincodeMessage)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569cd6;">var</span> err error</div><div>&nbsp;&nbsp;&nbsp;&nbsp;ccchan := <span style="color: #dcdcaa;">make</span>(<span style="color: #569cd6;">chan</span> <span style="color: #569cd6;">struct</span>{}, <span style="color: #b5cea8;">1</span>)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;ccsupportchan := <span style="color: #dcdcaa;">make</span>(<span style="color: #569cd6;">chan</span> <span style="color: #569cd6;">struct</span>{}, <span style="color: #b5cea8;">1</span>)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #608b4e;">//启动客户端处理</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">go</span> <span style="color: #569cd6;">func</span>() {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">defer</span> <span style="color: #dcdcaa;">close</span>(ccchan)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inprocLogger.Debugf(<span style="color: #ce9178;">"chaincode started for %s"</span>, id)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">if</span> args == <span style="color: #569cd6;">nil</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args = ipc.args</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">if</span> env == <span style="color: #569cd6;">nil</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env = ipc.env</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err := _shimStartInProc(env, args, ipc.chaincode, ccRcvPeerSend, peerRcvCCSend)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">if</span> err != <span style="color: #569cd6;">nil</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err = fmt.Errorf(<span style="color: #ce9178;">"chaincode-support ended with err: %s"</span>, err)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_inprocLoggerErrorf(<span style="color: #ce9178;">"%s"</span>, err)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inprocLogger.Debugf(<span style="color: #ce9178;">"chaincode ended with for  %s with err: %s"</span>, id, err)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;}()</div><div>    <span style="color: #608b4e;">//启动服务端处理</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">go</span> <span style="color: #569cd6;">func</span>() {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">defer</span> <span style="color: #dcdcaa;">close</span>(ccsupportchan)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inprocStream := newInProcStream(peerRcvCCSend, ccRcvPeerSend)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inprocLogger.Debugf(<span style="color: #ce9178;">"chaincode-support started for  %s"</span>, id)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err := ccSupport.HandleChaincodeStream(ctxt, inprocStream)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">if</span> err != <span style="color: #569cd6;">nil</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err = fmt.Errorf(<span style="color: #ce9178;">"chaincode ended with err: %s"</span>, err)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_inprocLoggerErrorf(<span style="color: #ce9178;">"%s"</span>, err)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inprocLogger.Debugf(<span style="color: #ce9178;">"chaincode-support ended with for  %s with err: %s"</span>, id, err)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;}()</div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">select</span> {</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">case</span> &lt;-ccchan:</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #dcdcaa;">close</span>(peerRcvCCSend)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inprocLogger.Debugf(<span style="color: #ce9178;">"chaincode %s quit"</span>, id)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">case</span> &lt;-ccsupportchan:</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #dcdcaa;">close</span>(ccRcvPeerSend)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inprocLogger.Debugf(<span style="color: #ce9178;">"chaincode support %s quit"</span>, id)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">case</span> &lt;-ipc.stopChan:</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #dcdcaa;">close</span>(ccRcvPeerSend)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #dcdcaa;">close</span>(peerRcvCCSend)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inprocLogger.Debugf(<span style="color: #ce9178;">"chaincode %s stopped"</span>, id)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c586c0;">return</span> err</div><div>}</div><br /><div>```</div><br /><br /><div><span style="color: #6796e6;">*</span> 初始化流程图</div><div>![](<span style="text-decoration-line: underline;">systemcodeinit.png</span>)</div><img src="http://www.blogjava.net/images/blogjava_net/fool/systemcodeinit.png" border="0" alt="" /><br /><br /><div><span style="color: #569cd6;font-weight: bold;">## 4、系统链码的执行</span></div><div>...</div></div></div><img src ="http://www.blogjava.net/fool/aggbug/433277.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2018-06-12 15:00 <a href="http://www.blogjava.net/fool/archive/2018/06/12/433277.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Fabric 1.1源代码分析之 Chaincode（链码）初始化</title><link>http://www.blogjava.net/fool/archive/2018/06/12/433275.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Tue, 12 Jun 2018 06:51:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2018/06/12/433275.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433275.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2018/06/12/433275.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433275.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433275.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: # Fabric 1.1源代码分析之 Chaincode（链码）初始化 #ChaincodeSupport（链码支持服务端）## 1、Endorser概述1、Endorser相关代码分布在protos/peer/peer.pb.go和core/endorser目录。* 在peer/node/start.go的serve（） 方法中注册了 endoser服务 serverEndorser := en...&nbsp;&nbsp;<a href='http://www.blogjava.net/fool/archive/2018/06/12/433275.html'>阅读全文</a><img src ="http://www.blogjava.net/fool/aggbug/433275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2018-06-12 14:51 <a href="http://www.blogjava.net/fool/archive/2018/06/12/433275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开源区块链Hyperleger Fabric之链码开发调试模式在IDE里debug链码</title><link>http://www.blogjava.net/fool/archive/2018/05/23/433231.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Wed, 23 May 2018 06:17:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2018/05/23/433231.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433231.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2018/05/23/433231.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433231.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433231.html</trackback:ping><description><![CDATA[能在IDE里调试链码自然是比较痛快。本文前提是了解fabric合约布署过程。链码调试开发步骤如下：<br />1,启动order<br />&nbsp; &nbsp; orderer start<br />2, 使用开发模式启动peer节点<br />&nbsp; &nbsp;peer node start --peer-chaincodedev=true<br />3,创建通道<br />4,启动链码程序<br />这一步可以在IDE里启动链码，这样就可以debug了<br /><div>cd examples/chaincode/go/chaincode_example02</div><div>go build</div><div>CORE_CHAINCODE_LOGLEVEL=debug CORE_PEER_ADDRESS=127.0.0.1:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./chaincode_example02<br />5,安装链码<div>peer chaincode install -n mycc -v 0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02<br />6,初始化链码</div><div>peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a","100","b","200"]}' -o 127.0.0.1:7050 -C ch1<br />7,链码调用和测试</div><div></div></div><img src ="http://www.blogjava.net/fool/aggbug/433231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2018-05-23 14:17 <a href="http://www.blogjava.net/fool/archive/2018/05/23/433231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开源区块链Hyperleger Fabric之通过Composer开发框架快速搭建开发环境</title><link>http://www.blogjava.net/fool/archive/2018/03/12/433093.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 12 Mar 2018 08:44:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2018/03/12/433093.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433093.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2018/03/12/433093.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433093.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433093.html</trackback:ping><description><![CDATA[Composer是Hyperleder的子项目。用来开发布署智能合约,开发流程如下<img src="http://www.blogjava.net/images/blogjava_net/fool/composer2.png" border="0" alt="" /><br />准备工作：(自行百度）<br /><p style="margin-left:18.0pt"><span style="font-size:10.5pt">开发环境必备软件：</span></p>  <p style="margin-left:42.0pt;text-indent:-24.0pt;"><span style="font-size:10.5pt;font-family:Wingdings;"><span style="font-stretch: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;</span></span><span style="font-size:10.5pt">composer-cli</span></p>  <p style="margin-left:42.0pt;text-indent:-24.0pt;"><span style="font-size:10.5pt;font-family:Wingdings;"><span style="font-stretch: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;</span></span><span style="font-size:10.5pt">generator-hyperledger-composr</span></p>  <p style="margin-left:42.0pt;text-indent:-24.0pt;"><span style="font-size:10.5pt">composer-rest-server<br /></span><span style="font-size: 10.5pt; text-indent: -24pt;">Yeoman<br /><br /></span></p><p style="margin-left: 42pt; text-indent: -24pt;"><span style="font-size: 10.5pt;">安装playground</span></p><div style="display: inline-block;"></div><p>&nbsp;</p><div style="text-indent: -32px;">Installing and running Hyperledger Composer Playground locally<br />docker ps -aq | xargs docker rm -f<br />docker images -aq | xargs docker rmi -f<br />curl -sSL https://hyperledger.github.io/composer/install-hlfv1.sh | bash &nbsp;&nbsp;</div><div>执行install-hlfv1.sh 安装运行fabric1.06版.并运行 playground服务 打开流览器http://xxxx:8080显示如下</div><p style="margin-left: 42pt; text-indent: -24pt;"><span style="font-size: 10.5pt;"><br /><img src="http://www.blogjava.net/images/blogjava_net/fool/composer3.jpg" border="0" alt="" /><br /></span></p><p style="line-height: 150%; margin: 0pt 0in 0pt 0.28in; text-indent: 0in; direction: ltr; unicode-bidi: embed; vertical-align: baseline; word-break: normal;"><span style="font-size:12.0pt;
font-family:Arial;mso-ascii-font-family:Arial;mso-fareast-font-family:微软雅黑;
mso-bidi-font-family:+mn-cs;color:#0070C0;mso-color-index:4;mso-font-kerning:
12.0pt;language:en-US">1,playground</span><span style="font-size:12.0pt;
font-family:Arial;mso-ascii-font-family:Arial;mso-fareast-font-family:微软雅黑;
mso-bidi-font-family:+mn-cs;color:#0070C0;mso-color-index:4;mso-font-kerning:
12.0pt;language:zh-CN"> 的</span><span style="font-size:12.0pt;font-family:Arial;
mso-ascii-font-family:Arial;mso-fareast-font-family:微软雅黑;mso-bidi-font-family:
+mn-cs;color:#0070C0;mso-color-index:4;mso-font-kerning:12.0pt;language:en-US">Web
Browser</span><span style="font-size:12.0pt;font-family:微软雅黑;mso-ascii-font-family:
Arial;mso-fareast-font-family:微软雅黑;mso-bidi-font-family:+mn-cs;color:#0070C0;
mso-color-index:4;mso-font-kerning:12.0pt;language:zh-CN">区域提供了在页面定义模型、测试模型的能力。并不保存。但可以导出</span><span style="font-size:12.0pt;font-family:Arial;mso-ascii-font-family:Arial;
mso-fareast-font-family:微软雅黑;mso-bidi-font-family:+mn-cs;color:#0070C0;
mso-color-index:4;mso-font-kerning:12.0pt;language:en-US">bna</span><span style="font-size:12.0pt;font-family:微软雅黑;mso-ascii-font-family:Arial;
mso-fareast-font-family:微软雅黑;mso-bidi-font-family:+mn-cs;color:#0070C0;
mso-color-index:4;mso-font-kerning:12.0pt;language:zh-CN">文件</span><span style="font-size:12.0pt;font-family:Arial;mso-ascii-font-family:Arial;
mso-fareast-font-family:微软雅黑;mso-bidi-font-family:+mn-cs;color:#0070C0;
mso-color-index:4;mso-font-kerning:12.0pt;language:en-US">
</span></p><p style="line-height: 150%; margin: 0pt 0in 0pt 0.28in; text-indent: 0in; direction: ltr; unicode-bidi: embed; vertical-align: baseline; word-break: normal;"><span style="font-size: 12pt; font-family: Arial; color: #0070c0; letter-spacing: 0pt; vertical-align: baseline;">2,connection</span><span style="font-size: 12pt; font-family: 微软雅黑; color: #0070c0; letter-spacing: 0pt; vertical-align: baseline;">区域</span><span style="font-size:12.0pt;font-family:微软雅黑;mso-ascii-font-family:Arial;
mso-fareast-font-family:微软雅黑;mso-bidi-font-family:+mn-cs;color:#0070C0;
mso-color-index:4;mso-font-kerning:12.0pt;language:zh-CN;vertical-align:baseline;
mso-text-raise:0%">提供了在开发环境布署合约，会生成一个智能合约的docker运行环境.<br /></span><span style="font-size: 12pt; font-family: Arial; color: #0070c0; letter-spacing: 0pt; vertical-align: baseline;">
3,可以在上图中上部分的</span>My Business Networks 工作区点击虚业部分Deploy a new business network<br /></p><p style="line-height: 150%; margin: 0pt 0in 0pt 0.28in; text-indent: 0in; direction: ltr; unicode-bidi: embed; vertical-align: baseline; word-break: normal;"><span style="font-size: 12pt; font-family: Arial; color: #0070c0; letter-spacing: 0pt; vertical-align: baseline;">4，在接下来页面中选中一个示例。如 marble neetworkd. &nbsp;选择&nbsp;</span><span style="color: #19273c; font-family: 'Open Sans', 'Helvetica Neue for IBM', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 0.9rem; line-height: 15px; orphans: 2; widows: 2; background-color: #fdfdfd;">ID and Secret 填入admin 和 adminpw<br /></span></p><p style="line-height: 150%; margin: 0pt 0in 0pt 0.28in; text-indent: 0in; direction: ltr; unicode-bidi: embed; vertical-align: baseline; word-break: normal;"><span style="font-size: 12pt; font-family: Arial; color: #0070c0; letter-spacing: 0pt; vertical-align: baseline;">5，点击Deploy按钮后会发布一个合约.并跳到测试页如下图:<br /><img src="http://www.blogjava.net/images/blogjava_net/fool/compose4.png" border="0" alt="" /><br /><br /></span></p><p style="margin-left: 42pt; text-indent: -24pt;">

<span style="font-size: 10.5pt;"><br />6，在上图中 Test Tab页可以进行测试 ,在Define Tab页可以导出bna文件.<br />7,在第一幅图中点击下载按钮，会下载一个 .card文件，描述了连接fabric peer节点等相关连接信息.记得要导&nbsp;</span>PeerAdmin@hlfv1的card和你自己测试用的card,及bna文件<br />8,分别执行 &nbsp;composer card import -f PeerAdmin.card &nbsp;，composer card import -f admin.card &nbsp;.composer card list 可以查看你导入的card的name信息.<br /></p><p style="margin-left: 42pt; text-indent: -24pt;"><span style="font-size: 10.5pt;">&nbsp; &nbsp; &nbsp; &nbsp;9,</span>composer-rest-server -c admin@empty-business-network -n always -w true &nbsp;启动rest服务默认端口3000.<br /></p><p style="margin-left: 42pt; text-indent: -24pt;"><span style="font-size: 10.5pt;">&nbsp; &nbsp; &nbsp; 10,好了,可以体验一下fabric是个什么玩意了。：） 88!<br /><br /></span></p><br /><div> <img src="file:///C:\Users\hechang\AppData\Roaming\Tencent\Users\53268131\QQ\WinTemp\RichOle\$)F{G7`1~XT5F5R]B$Q~T3P.png" alt="" /></div><img src ="http://www.blogjava.net/fool/aggbug/433093.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2018-03-12 16:44 <a href="http://www.blogjava.net/fool/archive/2018/03/12/433093.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开源区块链Hyperleger Fabric通过SDK-JAVA动态添加通道</title><link>http://www.blogjava.net/fool/archive/2018/03/12/433090.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 12 Mar 2018 03:55:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2018/03/12/433090.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433090.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2018/03/12/433090.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433090.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433090.html</trackback:ping><description><![CDATA[<h2><a id="viewpost1_TitleUrl" href="http://www.blogjava.net/fool/archive/2018/02/01/433032.html"></a><span style="font-weight: normal;"><a href="http://www.blogjava.net/fool/archive/2018/02/01/433032.html"><br style="color: #000000;" /><font color="#2e9ce9"><span style="font-size: 14px;">在阅读本篇之前需要理解</span></font></a><div style="color: #2e9ce9; text-decoration: none; font-size: 14px; display: inline !important;"><a id="viewpost1_TitleUrl" href="http://www.blogjava.net/fool/archive/2018/02/01/433032.html" style="color: #2e9ce9; text-decoration: none; font-size: 14px;"><span style="color: #000000;">configtxgen</span></a><span style="color: #000000;">工具使用原理.基本上能跑通</span></div></span><a href="http://www.blogjava.net/fool/archive/2018/02/01/433032.html"><font color="#2e9ce9"><span style="font-size: 14px;">开源区块链Hyperleger Fabric的SDK-JAVA新手上路指引</span></font></a></h2><div>中的内容。可以参考http://www.blogjava.net/fool/archive/2018/02/01/433032.html.<br />如果知道通过命令行工具进行智能合约的安装测试就更好了。fabric中的channel可以理解为泳道。在这个泳道中可以布署<br />多个智能合约。当然也可以安装多个channel. 顺便多一嘴，在智能合约可以调用另一个channel中的智能合约中的查询方法.<br />通过sdk动态安装通道的步骤：<br />1,通过configtxgen命令生成交易通道初始文件.<br />configtxgen --profile TestSoft --outputCreateChannelTx testsoft.tx --channelID testsoft<br />2,下载testsoft.tx到本机.<br />3,sdk安装通道代码及解释<br /><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">		</span>public boolean installChannel(String channelName) throws IOException, InvalidArgumentException, TransactionException, ProposalException {</div><div><span style="white-space:pre">			</span>// TODO Auto-generated method stub</div><div><span style="white-space:pre">			</span> &nbsp;String configPath = this.config.getConfigPath();<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//初始化&nbsp;ChannelConfiguration 对象.参数是通道初始化文件路径</div><div><span style="white-space:pre">			</span> &nbsp;ChannelConfiguration channelConfiguration = new ChannelConfiguration(new File(configPath + "/"+channelName + ".tx"));</div><div><span style="white-space:pre">			</span>&nbsp; //构造orderder节点信息</div><div><span style="white-space:pre">			</span> &nbsp; &nbsp;String ordererName = orderers.get().get(0).getOrdererName();</div><div><span style="white-space:pre">				</span>Properties ordererProperties = loadOrderProperty(ordererName);</div><div><span style="white-space:pre">				</span>Orderer anOrderer = client.newOrderer(</div><div><span style="white-space:pre">						</span>ordererName,</div><div><span style="white-space:pre">						</span> orderers.get().get(0).getOrdererLocation(), ordererProperties);</div><div><span style="white-space:pre">				</span></div><div><span style="white-space:pre">		</span> &nbsp; &nbsp; &nbsp; &nbsp;//Create channel that has only one signer that is this orgs peer admin. If channel creation policy needed more signature they would need to be added too.</div><div><span style="white-space:pre">		</span> &nbsp; &nbsp; &nbsp; &nbsp;Channel channel = client.newChannel(channelName, anOrderer, channelConfiguration, client.getChannelConfigurationSignature(channelConfiguration, fabricOrg.getPeerAdmin()));<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//构造peer节点信息，并且将peer节点加入到通道中。peer节点加入通道后，才能通过该peer节点中访问通道中的智能合约</div><div><span style="white-space:pre">		</span> &nbsp; &nbsp; &nbsp; &nbsp;for (com.ygsoft.fabric.bean.Peers.Peer p : config.getInstallPeers().get()) {</div><div><span style="white-space:pre">					</span>Properties peerProperties = this.loadPeerProperties(p.getPeerName());</div><div><span style="white-space:pre">					</span>Peer peer = client.newPeer(p.getPeerName(),p.getPeerLocation(),peerProperties);</div><div><span style="white-space:pre">					</span>channel.joinPeer(peer);</div><div><span style="white-space:pre">				</span></div><div><span style="white-space:pre">				</span>}</div><div></div><div><span style="white-space:pre">				</span>for (int i = 0; i &lt; orderers.get().size(); i++) {</div><div><span style="white-space:pre">					</span>Properties ordererProperties2 = loadOrderProperty(ordererName);</div><div><span style="white-space:pre">					</span>channel.addOrderer(client.newOrderer(</div><div><span style="white-space:pre">							</span>orderers.get().get(i).getOrdererName(),</div><div><span style="white-space:pre">							</span>orderers.get().get(i)</div><div><span style="white-space:pre">									</span>.getOrdererLocation(), ordererProperties2));</div><div><span style="white-space:pre">				</span>}</div><div><span style="white-space:pre">				</span>log.debug("channel.isInitialized() = " + channel.isInitialized());</div><div><span style="white-space:pre">			</span> &nbsp; channel.initialize();</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">			</span> &nbsp;return true;</div><div><span style="white-space:pre">		</span>}</div><br />知道了手工命令行安装合约的过程，上面的理解还是比较简单的。安装通道后就可以调用sdk安装合约了。<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div><img src ="http://www.blogjava.net/fool/aggbug/433090.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2018-03-12 11:55 <a href="http://www.blogjava.net/fool/archive/2018/03/12/433090.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开源区块链Hyperleger Fabric的SDK-JAVA新手上路指引</title><link>http://www.blogjava.net/fool/archive/2018/02/01/433032.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Thu, 01 Feb 2018 01:03:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2018/02/01/433032.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/433032.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2018/02/01/433032.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/433032.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/433032.html</trackback:ping><description><![CDATA[话说有个程序员征婚，无人问津。前段时间区块链概念大火，该程序员灵机一动，借势而为，征婚上加了一行：<br />区块链工程师。不久抱得美人归。:)<br /><br />阅读本代码前，先看看fabric的多机布署,参考下面的贴子1:<br /><div>http://blog.csdn.net/songbin830/article/details/78778806 完成多机布署.<br /><br />参考贴子2: http://www.cnblogs.com/aberic/p/8206551.html ，把代码下到本地工程里。新手上路总会遇到<br />各种细节问题.重点来了：<br /><br />使用git命令从github.com上拉下SDK-JAVA源码.<br />1，源码文件中有EclipseSetup.md的文件，介绍如何把源码项目导入eclipse.<br />2，导入eclipse后发现缺少 &nbsp;org.hyperledger.fabric.protos.*文件。github上的源码里也没有。解决办法：从<br />其它网站的 SDK-JAVA打包文件中找到源码包，把org.hyperledger.fabric.protos包中的源码copy到eclipse。<br />3，在orderer节点把 &nbsp;crypto-config文件夹中的内容copy到本机.其中包含了用命令工具生成的证书，身份信息<br />等内容<br />4,贴子2中代码如何用，其实跟源码中的测试用例中的代码差不多.初始化示例如下：因为贴子2是个demo类代码，<br />我作了些改动。有些代码没放ChaincodeManager()实例化。看一下这个类的构造方法，构造对应的需要的实例类<br />也不难<br /><br /><div><span style="white-space:pre">	</span>public static ChaincodeManager init() throws Exception{</div><div><span style="white-space:pre">		</span>FabricConfig fabricConfig = new FabricConfig("E:/fabricConfig"); &nbsp;//fabricConfig文件夹中包含<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //crypto-config文件夹</div><div><span style="white-space:pre">		</span>Peers peers = new Peers(); &nbsp; //初始化peer节点</div><div><span style="white-space:pre">		</span>peers.setOrgDomainName("org1.ygsoft.com");</div><div><span style="white-space:pre">		</span>peers.setOrgMSPID("Org1MSP");</div><div><span style="white-space:pre">		</span>peers.setOrgName("Org1MSP");</div><div><span style="white-space:pre">		</span>//peers.addPeer("peer0.org1.ygsoft.com", "peer0.org1.ygsoft.com", "grpcs://10.121.60.2:7051", "grpcs://10.121.60.2:7053", null);</div><div><span style="white-space:pre">		</span>peers.addPeer("peer1.org1.ygsoft.com", "peer1.org1.ygsoft.com", "grpcs://10.121.60.3:7051", "grpcs://10.121.60.3:7053", null);</div><div><span style="white-space:pre">		</span>fabricConfig.setPeers(peers);</div><div><span style="white-space:pre">		//初始化orderer节点<br /></span></div><div><span style="white-space:pre">		</span>Orderers orders = new Orderers();</div><div><span style="white-space:pre">		</span>orders.setOrdererDomainName("ygsoft.com");</div><div><span style="white-space:pre">		</span>orders.addOrderer("orderer.ygsoft.com", "grpcs://10.121.60.1:7050");</div><div><span style="white-space:pre">		</span>fabricConfig.setOrderers(orders);</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">		</span>fabricConfig.setRegisterEvent(true);</div><div><span style="white-space:pre">		</span>ChaincodeManager chainManager = new ChaincodeManager(fabricConfig);</div><div><span style="white-space:pre">		</span>return chainManager;</div><div><span style="white-space:pre">	</span>}</div><br />5,其它参数，比如chaincode相关信息可以在peer节点 &nbsp;peer chaincode list --installed 命令可以查看<br />可以调用这个ChaincodeManager 的query和invoke方法了.<br /><br />6,补充内容:需要shim-client.jar包，这个需要拉下fabric的源码，在文件夹<br />\src\github.com\hyperledger\fabric\core\chaincode\shim\java 用gradle编译一个jar包出来<br /><br />7，如果grpc用了ssl的需要&nbsp;grpcs://10.121.60.3:7051，grpcs开头<br /><br />因为网上有了fabric多机布署教程,和不完善的示例代码，这里主要介绍一下其中容易遇到的问题，解决起<br />来也颇为头痛和费时。<br />本贴原地址:http://www.blogjava.net/fool .下一篇区块链贴子预告：Fabric的SDK-JAVA动态安装<br />Channel<br /><br /><br /><br /></div><br /><br /><br /><br /><br /><br /><br /><br /><img src ="http://www.blogjava.net/fool/aggbug/433032.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2018-02-01 09:03 <a href="http://www.blogjava.net/fool/archive/2018/02/01/433032.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>springCloud、boot集成elk</title><link>http://www.blogjava.net/fool/archive/2017/10/08/432851.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Sun, 08 Oct 2017 11:15:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/10/08/432851.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432851.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/10/08/432851.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432851.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432851.html</trackback:ping><description><![CDATA[elasticsearch、logstash、kibana版本均为5.6.2版,需要注意版本匹配问题<br />1,启动elashticsearch<br />2,logstash/config目录下新建log.conf文件,其内容：<br /><div>input {</div><div>&nbsp; # For detail config for log4j as input,&nbsp;</div><div>&nbsp; # See: https://www.elastic.co/guide/en/logstash/current/plugins-inputs-log4j.html</div><div></div><div>&nbsp; &nbsp; &nbsp; tcp {&nbsp;</div><div><span style="white-space:pre">	</span>&nbsp; &nbsp; mode =&gt; "server"</div><div><span style="white-space:pre">	</span>&nbsp; &nbsp; host =&gt; "127.0.0.1"</div><div>&nbsp; &nbsp; &nbsp; &nbsp; port =&gt; 4567</div><div>&nbsp; &nbsp; &nbsp; &nbsp; codec =&gt; json_lines&nbsp;</div><div>&nbsp; &nbsp; }&nbsp;&nbsp;</div><div>}</div><div>filter {</div><div>&nbsp; #Only matched data are send to output.</div><div>}</div><div>output {</div><div>&nbsp; # For detail config for elasticsearch as output,&nbsp;</div><div>&nbsp; # See: https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html</div><div>&nbsp; elasticsearch {&nbsp;&nbsp;</div><div>&nbsp; &nbsp; hosts&nbsp; =&gt; ["127.0.0.1:9200"]&nbsp; &nbsp;#ElasticSearch host, can be array.</div><div>&nbsp; &nbsp; index&nbsp; =&gt; "applog"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#The index to write data to.</div><div>&nbsp; }</div><div>}<br />3,kibana配置.修改kibana/config文件夹中的kibana.yml的配置文件<div>server.port: 5601</div><div>server.host: "localhost"</div><div>elasticsearch.url: "http://localhost:9200"</div><div>kibana.index: ".kibana"<br /><br />4,springCload、springBoot中的logback-spring.xml文件配置将日志写入logstash<br /><br /><div>&nbsp; &nbsp; &lt;appender name="logstash2" class="net.logstash.logback.appender.LogstashTcpSocketAppender"&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;remoteHost&gt;127.0.0.1&lt;/remoteHost&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;port&gt;4567&lt;/port&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;filter class="ch.qos.logback.classic.filter.ThresholdFilter"&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- Minimum logging level to be presented in the console logs--&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;level&gt;INFO&lt;/level&gt; &lt;!--写入logstash的日志级别--&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;/filter&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/&gt;</div><div>&nbsp; &nbsp; &lt;/appender&gt;</div><div>&nbsp; &nbsp; &#8203;</div><div>&nbsp; &nbsp; &lt;root level="INFO"&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;appender-ref ref="console"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;appender-ref ref="logstash"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;appender-ref ref="logstash2"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;!--&lt;appender-ref ref="flatfile"/&gt;--&gt;</div><div>&nbsp; &nbsp; &lt;/root&gt;<br /><br />后记:日志是直接写入到elashticsearch,可以集成kafka或redis作为缓冲。</div></div></div><img src ="http://www.blogjava.net/fool/aggbug/432851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-10-08 19:15 <a href="http://www.blogjava.net/fool/archive/2017/10/08/432851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>springboot、mybatis、mycat分库实践</title><link>http://www.blogjava.net/fool/archive/2017/10/01/432841.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Sun, 01 Oct 2017 09:40:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/10/01/432841.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432841.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/10/01/432841.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432841.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432841.html</trackback:ping><description><![CDATA[<div>1.pom文件中引入下面引入mybatis逆向工程插件</div><div><span style="white-space:pre">	</span>&lt;build&gt;</div><div><span style="white-space:pre">		</span>&lt;plugins&gt;</div><div><span style="white-space:pre">			</span>&lt;plugin&gt;</div><div><span style="white-space:pre">				</span>&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</div><div><span style="white-space:pre">				</span>&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;</div><div><span style="white-space:pre">			</span>&lt;/plugin&gt;</div><div><span style="white-space:pre">			</span>&lt;plugin&gt;</div><div><span style="white-space:pre">				</span>&lt;groupId&gt;org.mybatis.generator&lt;/groupId&gt;</div><div><span style="white-space:pre">				</span>&lt;artifactId&gt;mybatis-generator-maven-plugin&lt;/artifactId&gt;</div><div><span style="white-space:pre">				</span>&lt;version&gt;1.3.4&lt;/version&gt;</div><div><span style="white-space:pre">				</span>&lt;configuration&gt;</div><div><span style="white-space:pre">					</span>&lt;verbose&gt;true&lt;/verbose&gt;</div><div><span style="white-space:pre">					</span>&lt;overwrite&gt;true&lt;/overwrite&gt;</div><div><span style="white-space:pre">				</span>&lt;/configuration&gt;</div><div><span style="white-space:pre">			</span>&lt;/plugin&gt;</div><div><span style="white-space:pre">		</span>&lt;/plugins&gt;</div><div><span style="white-space:pre">	</span>&lt;/build&gt;</div><div>&nbsp; &nbsp;2, src/main/resource 目录下引入mybatis逆向工程配置文件，这样就可以自动生成mybatis需要的xml及dao interface</div><div></div><div>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</div><div>&nbsp;&lt;!DOCTYPE generatorConfiguration</div><div>&nbsp; &nbsp;PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"</div><div>&nbsp; &nbsp;"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"&gt;</div><div>&nbsp;&lt;generatorConfiguration&gt;</div><div>&nbsp; &nbsp; &nbsp;&lt;!--数据库驱动--&gt;</div><div>&nbsp; &nbsp; &nbsp;&lt;classPathEntry&nbsp; &nbsp; location="E:\\worksource\\springboot\\src\\main\\webapp\\WEB-INF\\lib\\mysql-connector-java-5.1.39.jar"/&gt;</div><div>&nbsp; &nbsp; &nbsp;&lt;context id="DB2Tables"&nbsp; &nbsp; targetRuntime="MyBatis3"&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;commentGenerator&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="suppressDate" value="true"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="suppressAllComments" value="true"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/commentGenerator&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;!--数据库链接地址账号密码--&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/jeeshop" userId="root" password=""&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/jdbcConnection&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;javaTypeResolver&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="forceBigDecimals" value="false"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/javaTypeResolver&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;!--生成Model类存放位置--&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;javaModelGenerator targetPackage="com.junjun.myblog.domain" targetProject="src/main/java"&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="enableSubPackages" value="true"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="trimStrings" value="true"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/javaModelGenerator&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;!--生成映射文件存放位置--&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;sqlMapGenerator targetPackage="src/main/resources/mapper" targetProject="."&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="enableSubPackages" value="true"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/sqlMapGenerator&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;!--生成Dao类存放位置--&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;javaClientGenerator type="XMLMAPPER" targetPackage="com.junjun.myblog.dao" targetProject="src/main/java"&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="enableSubPackages" value="true"/&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/javaClientGenerator&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;!--生成对应表及类名 mapperName="AreaDao"&nbsp; 工程右键 Debug As -&gt; maven build... -&gt; mybatis-generator:generate</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;table tableName="t_area"&nbsp; &nbsp;domainObjectName="Area" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"&gt;&lt;/table&gt;</div><div>&nbsp; &nbsp; --&gt;</div><div>&lt;/context&gt;</div><div>&nbsp;&lt;/generatorConfiguration&gt;</div><div></div><div>3,application 中加上注解&nbsp; @MapperScan("com.junjun")&nbsp;</div><div>4，数据源连接mycat</div><div>spring.datasource.type=com.alibaba.druid.pool.DruidDataSource</div><div>spring.datasource.driver-class-name=com.mysql.jdbc.Driver</div><div>spring.datasource.url=jdbc:mysql://localhost:8066/MYSQL?useUnicode=true&amp;characterEncoding=UTF-8</div><div>spring.datasource.username=root</div><div>spring.datasource.password=123456</div><div></div><div>二，mycat配置</div><div>1,conf/server.xml中配置用户 和schema</div><div><span style="white-space:pre">	</span>&lt;user name="root"&gt;</div><div><span style="white-space:pre">		</span>&lt;property name="password"&gt;123456&lt;/property&gt;</div><div><span style="white-space:pre">		</span>&lt;property name="schemas"&gt;MYSQL&lt;/property&gt;<span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span>&lt;/user&gt;</div><div>2,schema.xml配置数据库和分片表分片规则</div><div><span style="white-space:pre">	</span>&lt;schema name="MYSQL" checkSQLschema="false" sqlMaxLimit="100"&gt;</div><div><span style="white-space:pre">		</span>&lt;table name="t_blogger" primaryKey="id" dataNode="dn1" &gt;&nbsp; &nbsp; &nbsp;&lt;/table&gt;&nbsp;</div><div><span style="white-space:pre">		</span> &lt;!--按需配置分片规则--&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &lt;table name="t_area" primaryKey="id" dataNode="dn1,dn2,dn3" rule="mod-long1"&gt;&nbsp; &nbsp; &nbsp;&lt;/table&gt;&nbsp;</div><div><span style="white-space:pre">		</span>&lt;table name="t_blog" primaryKey="id" dataNode="dn1" &gt;&nbsp; &nbsp; &nbsp;&lt;/table&gt;&nbsp;</div><div><span style="white-space:pre">		</span>&lt;table name="t_blogtype" primaryKey="id" dataNode="dn1" &gt;&nbsp; &nbsp; &nbsp;&lt;/table&gt;&nbsp;</div><div></div><div><span style="white-space:pre">	</span>&lt;/schema&gt;</div><div><span style="white-space:pre">	</span>&lt;!-- &lt;dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"</div><div><span style="white-space:pre">		</span>/&gt; --&gt;</div><div><span style="white-space:pre">	</span>&lt;dataNode name="dn1" dataHost="localhost1" database="jeeshop" /&gt;</div><div><span style="white-space:pre">	</span>&lt;dataNode name="dn2" dataHost="localhost2" database="jysystem" /&gt;</div><div><span style="white-space:pre">	</span>&lt;dataNode name="dn3" dataHost="localhost3" database="dn3" /&gt;</div><div></div><div><span style="white-space:pre">	</span>&lt;!--&lt;dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" /&gt;</div><div><span style="white-space:pre">	</span> &lt;dataNode name="jdbc_dn1" dataHost="jdbchost" database="db1" /&gt;</div><div><span style="white-space:pre">	</span>&lt;dataNode<span style="white-space:pre">	</span>name="jdbc_dn2" dataHost="jdbchost" database="db2" /&gt;</div><div><span style="white-space:pre">	</span>&lt;dataNode name="jdbc_dn3" <span style="white-space:pre">	</span>dataHost="jdbchost" database="db3" /&gt; --&gt;</div><div><span style="white-space:pre">	</span>&lt;dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"</div><div><span style="white-space:pre">			</span>&nbsp; writeType="0" dbType="mysql" dbDriver="native" switchType="1"&nbsp; slaveThreshold="100"&gt;</div><div><span style="white-space:pre">		</span>&lt;heartbeat&gt;select user()&lt;/heartbeat&gt;</div><div><span style="white-space:pre">		</span>&lt;!-- can have multi write hosts --&gt;</div><div><span style="white-space:pre">		</span>&lt;writeHost host="hostM1" url="localhost:3306" user="root"</div><div><span style="white-space:pre">				</span>&nbsp; &nbsp;password=""&gt;</div><div><span style="white-space:pre">			</span>&lt;!-- can have multi read hosts&nbsp;</div><div><span style="white-space:pre">			</span>&lt;readHost host="hostS2" url="192.168.1.200:3306" user="root" password="" /&gt; --&gt;</div><div><span style="white-space:pre">		</span>&lt;/writeHost&gt;</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">		</span>&lt;!-- &lt;writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/&gt; --&gt;</div><div><span style="white-space:pre">	</span>&lt;/dataHost&gt;</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">		</span>&lt;dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"</div><div><span style="white-space:pre">			</span>&nbsp; writeType="0" dbType="mysql" dbDriver="native" switchType="1"&nbsp; slaveThreshold="100"&gt;</div><div><span style="white-space:pre">		</span>&lt;heartbeat&gt;select user()&lt;/heartbeat&gt;</div><div><span style="white-space:pre">		</span>&lt;!-- can have multi write hosts --&gt;</div><div><span style="white-space:pre">		</span>&lt;writeHost host="hostM2" url="127.0.0.1:3306" user="root"</div><div><span style="white-space:pre">				</span>&nbsp; &nbsp;password=""&gt;</div><div><span style="white-space:pre">			</span>&lt;!-- can have multi read hosts&nbsp;</div><div><span style="white-space:pre">			</span>&lt;readHost host="hostS2" url="192.168.1.200:3306" user="root" password="" /&gt; --&gt;</div><div><span style="white-space:pre">		</span>&lt;/writeHost&gt;</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">		</span>&lt;!-- &lt;writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/&gt; --&gt;</div><div><span style="white-space:pre">	</span>&lt;/dataHost&gt;</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">			</span>&lt;dataHost name="localhost3" maxCon="1000" minCon="10" balance="0"</div><div><span style="white-space:pre">			</span>&nbsp; writeType="0" dbType="mysql" dbDriver="native" switchType="1"&nbsp; slaveThreshold="100"&gt;</div><div><span style="white-space:pre">		</span>&lt;heartbeat&gt;select user()&lt;/heartbeat&gt;</div><div><span style="white-space:pre">		</span>&lt;!-- can have multi write hosts --&gt;</div><div><span style="white-space:pre">		</span>&lt;writeHost host="hostM2" url="127.0.0.1:3306" user="root"</div><div><span style="white-space:pre">				</span>&nbsp; &nbsp;password=""&gt;</div><div><span style="white-space:pre">			</span>&lt;!-- can have multi read hosts&nbsp;</div><div><span style="white-space:pre">			</span>&lt;readHost host="hostS2" url="192.168.1.200:3306" user="root" password="" /&gt; --&gt;</div><div><span style="white-space:pre">		</span>&lt;/writeHost&gt;</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">		</span>&lt;!-- &lt;writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/&gt; --&gt;</div><div><span style="white-space:pre">	</span>&lt;/dataHost&gt;</div><div>3,rule.xml配置分片规则</div><div>&nbsp; &nbsp; 添加如下规则 按表的name字段进行分片存储</div><div><span style="white-space:pre">	</span>&lt;tableRule name="mod-long1"&gt;</div><div><span style="white-space:pre">		</span>&lt;rule&gt;</div><div><span style="white-space:pre">			</span>&lt;columns&gt;name&lt;/columns&gt;</div><div><span style="white-space:pre">			</span>&lt;algorithm&gt;mod-long&lt;/algorithm&gt;</div><div><span style="white-space:pre">		</span>&lt;/rule&gt;</div><div><span style="white-space:pre">	</span>&lt;/tableRule&gt;</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span></div><div>备注：内容太多，记一下重点. 分库后连接查询不在同一个库是查不到数据的,真有这需要那就真需要考虑</div><div>设计是否合理了.</div><div></div><img src ="http://www.blogjava.net/fool/aggbug/432841.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-10-01 17:40 <a href="http://www.blogjava.net/fool/archive/2017/10/01/432841.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>springboot中action绑定ServletRequest的attirbute的值传参</title><link>http://www.blogjava.net/fool/archive/2017/09/29/432838.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Fri, 29 Sep 2017 03:58:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/09/29/432838.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432838.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/09/29/432838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432838.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432838.html</trackback:ping><description><![CDATA[有些时候需要在后台处理一封装一些参数送到action中便于业务处理.比于app中的token验证,<br />根据token查找到对应的用户信息。比如分布式框架中获取用户信息等.springboot中可以自<br />定义参数解析器来绑定参数，通过它可以拿到ServletRequest中的attirbute中的值进行参数<br />绑定。<br /><br />自定义一个annotation,通过这个注解中的 name查找attribute中的key对应的值&nbsp;<br /><br /><div>import java.lang.annotation.ElementType;</div><div>import java.lang.annotation.Retention;</div><div>import java.lang.annotation.RetentionPolicy;</div><div>import java.lang.annotation.Target;</div><div></div><div>@Target(ElementType.PARAMETER)</div><div>@Retention(RetentionPolicy.RUNTIME)</div><div>public @interface AttributeResolve {</div><div><span style="white-space:pre">	</span>String name() default "user";</div><div>}</div><div></div><br /><div>自定义一个解析器类<br /><br /><div>import javax.servlet.http.HttpServletRequest;</div><div></div><div>import org.springframework.core.MethodParameter;</div><div>import org.springframework.web.bind.support.WebDataBinderFactory;</div><div>import org.springframework.web.context.request.NativeWebRequest;</div><div>import org.springframework.web.method.support.HandlerMethodArgumentResolver;</div><div>import org.springframework.web.method.support.ModelAndViewContainer;</div><div></div></div><div>public class AttributeArgumentResolver implements HandlerMethodArgumentResolver{</div><div></div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public Object resolveArgument(MethodParameter arg0, ModelAndViewContainer arg1, NativeWebRequest arg2,</div><div><span style="white-space:pre">			</span>WebDataBinderFactory arg3) throws Exception {</div><div><span style="white-space:pre">		</span>// TODO Auto-generated method stub</div><div><span style="white-space:pre">		</span> Object resultObj=null;</div><div><span style="white-space:pre">		</span> &nbsp;AttributeResolve mp = &nbsp;arg0.getParameterAnnotation(AttributeResolve.class);</div><div><span style="white-space:pre">		</span> &nbsp;if(mp!=null) {</div><div><span style="white-space:pre">			</span> String attributeName= mp.name();</div><div><span style="white-space:pre">			</span> HttpServletRequest request = arg2.getNativeRequest(HttpServletRequest.class);<span style="white-space:pre">	</span></div><div><span style="white-space:pre">			</span> resultObj = request.getAttribute(attributeName);</div><div><span style="white-space:pre">		</span> &nbsp;}</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">		</span>return resultObj;</div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public boolean supportsParameter(MethodParameter arg0) {</div><div><span style="white-space:pre">		</span>// TODO Auto-generated method stub</div><div><span style="white-space:pre">		</span>return &nbsp;arg0.hasParameterAnnotation(AttributeResolve.class);</div><div><span style="white-space:pre">	</span>}</div><br />springboot中注册自定义的参数解析器<br /><div>@Configuration</div><div>public class MyWebMvcConfig extends WebMvcConfigurerAdapter{</div><div><span style="white-space:pre">	</span>public void addArgumentResolvers(List&lt;HandlerMethodArgumentResolver&gt; argumentResolvers) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; argumentResolvers.add(new AttributeArgumentResolver());</div><div>&nbsp; &nbsp; }<br />}<br /><br /><br />使用方法.<br />需要在action调用前向HttpServletRequest中的attribute中注入值 ，可以自定义一个filter,在filter中进行处理<br />如在filter中处理app传过来的token验证后取得对应的用户信息等.下面例子简单放入一个对象<br /><div></div><div>@WebFilter(filterName = "axssFilter", urlPatterns = "/*",</div><div>initParams = {</div><div><span style="white-space:pre">		</span>@WebInitParam(name = "ignores", value = "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源</div><div>}</div><div>)</div><div>public class XssFilter implements javax.servlet.Filter{</div><div><span style="white-space:pre">	</span>private Set&lt;String&gt; prefixIignores = new HashSet&lt;String&gt;();</div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public void destroy() {</div><div><span style="white-space:pre">		</span>// TODO Auto-generated method stub</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)</div><div><span style="white-space:pre">			</span>throws IOException, ServletException {</div><div><span style="white-space:pre">		</span>// TODO Auto-generated method stub</div><div><span style="white-space:pre">		</span>HttpServletRequest request = (HttpServletRequest) req;</div><div><span style="white-space:pre">		</span>HttpServletResponse response = (HttpServletResponse) res;</div><div>&nbsp; &nbsp; <span style="white-space:pre">	</span>&nbsp; &nbsp; &nbsp; &nbsp; Blogger user = new Blogger();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="white-space:pre">	</span>user.setUsername("asfdasdf");</div><div>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="white-space:pre">	</span>request.setAttribute("user", user);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;chain.doFilter(request, response); &nbsp;</div><div></div><div><span style="white-space:pre">	</span>}</div><div>}</div><br />action获取attribute中放入的对象<br /><div>&nbsp; &nbsp; &nbsp; &nbsp; @RequestMapping("/index")</div><div><span style="white-space:pre">	</span>public String index(@AttributeResolve(name="user") Bloggerbh,<span style="white-space: pre;">	</span>HttpServletRequest request,Model model)&nbsp;<br /><br />嗯，还算优雅</div><br /><br /></div><img src ="http://www.blogjava.net/fool/aggbug/432838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-09-29 11:58 <a href="http://www.blogjava.net/fool/archive/2017/09/29/432838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sbringboot异步执行</title><link>http://www.blogjava.net/fool/archive/2017/09/26/432832.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Tue, 26 Sep 2017 04:26:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/09/26/432832.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432832.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/09/26/432832.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432832.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432832.html</trackback:ping><description><![CDATA[把需要异步执行的任务丢到统一的线程池里执行，这个想法不错。springboot简化这个的代码。实现如下：<br /><br /><div></div><div>import java.util.concurrent.Executor;</div><div></div><div>import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;</div><div>import org.springframework.context.annotation.Configuration;</div><div>import org.springframework.scheduling.annotation.AsyncConfigurer;</div><div>import org.springframework.scheduling.annotation.EnableAsync;</div><div>import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;</div><div></div><div>@Configuration</div><div>@EnableAsync &nbsp; //开启异步任务支持</div><div>public class TaskExcutorConfig implements AsyncConfigurer {</div><div></div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public Executor getAsyncExecutor() {</div><div><span style="white-space:pre">		</span>// TODO Auto-generated method stub</div><div><span style="white-space:pre">		</span>ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();</div><div><span style="white-space:pre">		</span>taskExecutor.setMaxPoolSize(10);</div><div><span style="white-space:pre">		</span>taskExecutor.setQueueCapacity(20);</div><div><span style="white-space:pre">		</span>taskExecutor.setCorePoolSize(5);</div><div><span style="white-space:pre">		</span>taskExecutor.initialize();</div><div><span style="white-space:pre">		</span>return taskExecutor;</div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {</div><div><span style="white-space:pre">		</span>// TODO Auto-generated method stub</div><div><span style="white-space:pre">		</span>return null;</div><div><span style="white-space:pre">	</span>}</div><div><br />任务类或方法<br /><br /><div>import org.springframework.scheduling.annotation.Async;</div><div>import org.springframework.stereotype.Service;</div><div><span style="white-space: pre;">	</span>//@Async 写在这里则整个类的方法都 是异步执行</div><div>@Service</div><div>public class AsynTestService {</div><div><span style="white-space:pre">	</span>@Async &nbsp; //需要异步执行的方法</div><div><span style="white-space:pre">	</span>public void asyncTest() {</div><div><span style="white-space:pre">		</span>for(int i = 0; i &lt; 10;i++) {</div><div><span style="white-space:pre">			</span>System.out.println(i);</div><div><span style="white-space:pre">			</span>try {</div><div><span style="white-space:pre">				</span>Thread.sleep(1000);</div><div><span style="white-space:pre">			</span>} catch (InterruptedException e) {</div><div><span style="white-space:pre">				</span>// TODO Auto-generated catch block</div><div><span style="white-space:pre">				</span>e.printStackTrace();</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div></div><div>}</div></div><img src ="http://www.blogjava.net/fool/aggbug/432832.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-09-26 12:26 <a href="http://www.blogjava.net/fool/archive/2017/09/26/432832.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>springboot文件上传等杂项</title><link>http://www.blogjava.net/fool/archive/2017/09/18/432826.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 18 Sep 2017 03:01:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/09/18/432826.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432826.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/09/18/432826.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432826.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432826.html</trackback:ping><description><![CDATA[1,springboot中文件上传<br />springmvc中配置文件上传写法在boot并不支持<br /><span style="white-space: pre;">	</span>@Bean<div><span style="white-space:pre">	</span>public MultipartResolver multipartResolver() {</div><div><span style="white-space:pre">		</span>CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();</div><div><span style="white-space:pre">		</span>multipartResolver.setMaxUploadSize(100000000);</div><div><span style="white-space:pre">		</span>return multipartResolver;</div><div><span style="white-space:pre">	</span>}</div><div>得这样写<span style="white-space:pre">	</span></div><div><div>&nbsp; @Bean</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;public MultipartConfigElement multipartConfigElement() {</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp;MultipartConfigFactory factory = new MultipartConfigFactory();</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp;factory.setMaxFileSize("128KB");</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp;factory.setMaxRequestSize("128KB");</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp;return factory.createMultipartConfig();</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;}<br /><br />2,拦截器<br /><div>继承HandlerInterceptorAdapter确实可以拦截，但是afterCompletion在preHandle方法返回false后并<br />不执行，那么只能在preHandle中处理了，比如转向，ajax请求返回内容<br /><br />3,关于快速跳转<br />有时候只是做一个简单的跳转，可以集中写在这里<br /><div><span style="white-space:pre">	</span>public void addViewControllers(ViewControllerRegistry registry) {</div><div><span style="white-space:pre">	</span><span style="white-space:pre">	</span>registry.addViewController("/index").setViewName("/index");</div><div><span style="white-space:pre">	</span>&nbsp; &nbsp; &nbsp; &nbsp;registry.addViewController("/converter").setViewName("/converter");</div><div><span style="white-space:pre">	</span>}</div><br />完整示例：<br /><div>package com.example.demo.config;</div><div></div><div>import java.util.List;</div><div></div><div>import javax.servlet.MultipartConfigElement;</div><div></div><div>import org.springframework.boot.web.servlet.MultipartConfigFactory;</div><div>import org.springframework.context.annotation.Bean;</div><div>import org.springframework.context.annotation.Configuration;</div><div>import org.springframework.web.servlet.config.annotation.InterceptorRegistration;</div><div>import org.springframework.web.servlet.config.annotation.InterceptorRegistry;</div><div>import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;</div><div>import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;</div><div>import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;</div><div>import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;</div><div>import org.springframework.web.servlet.view.InternalResourceViewResolver;</div><div>import org.springframework.web.servlet.view.JstlView;</div><div></div><div></div><div></div><div>//其中默认配置的 /** 映射到 /static （或/public、/resources、/META-INF/resources）&nbsp;</div><div>//其中默认配置的 /webjars/** 映射到 classpath:/META-INF/resources/webjars/&nbsp;</div><div></div><div>/*</div><div>spring.mvc.static-path-pattern=</div><div></div><div>@Configuration</div><div>public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {</div><div><span style="white-space:pre">	</span>public void addResourceHandlers(ResourceHandlerRegistry registry) {</div><div></div><div><span style="white-space:pre">		</span>registry.addResourceHandler("/myres/**").addResourceLocations("classpath:/myres/");</div><div><span style="white-space:pre">		</span>//使用外部目录 registry.addResourceHandler("/api_files/**").addResourceLocations("file:D:/data/api_files");</div><div></div><div></div><div><span style="white-space:pre">		</span>super.addResourceHandlers(registry);</div><div></div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>@Bean</div><div><span style="white-space:pre">	</span>public InternalResourceViewResolver viewResolver() {</div><div><span style="white-space:pre">		</span>InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();</div><div><span style="white-space:pre">		</span>viewResolver.setPrefix("/WEB-INF/views/");</div><div><span style="white-space:pre">		</span>viewResolver.setSuffix(".jsp");</div><div><span style="white-space:pre">		</span>viewResolver.setViewClass(JstlView.class);</div><div><span style="white-space:pre">		</span>return viewResolver;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span>//拦截器</div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public void addInterceptors(InterceptorRegistry registry) {// 2</div><div><span style="white-space:pre">		</span>InterceptorRegistration i=registry.addInterceptor(demoInterceptor());</div><div><span style="white-space:pre">		</span>i.addPathPatterns("/jsp/*");//只拦截 /jsp/* 的action</div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>@Bean</div><div><span style="white-space:pre">	</span>// 1 &nbsp;配置拦截器</div><div><span style="white-space:pre">	</span>public DemoInterceptor demoInterceptor() {</div><div><span style="white-space:pre">		</span>return new DemoInterceptor();</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>//快速转向</div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public void addViewControllers(ViewControllerRegistry registry) {</div><div><span style="white-space:pre">	</span>//<span style="white-space:pre">	</span>registry.addViewController("/index").setViewName("/index");</div><div><span style="white-space:pre">		</span>registry.addViewController("/toUpload").setViewName("/upload");</div><div><span style="white-space:pre">		</span>registry.addViewController("/converter").setViewName("/converter");</div><div><span style="white-space:pre">		</span>registry.addViewController("/sse").setViewName("/sse");</div><div><span style="white-space:pre">		</span>registry.addViewController("/async").setViewName("/async");</div><div><span style="white-space:pre">	</span>}</div><div></div><div></div><div></div><div></div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;@Bean</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;public MultipartConfigElement multipartConfigElement() {</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp;MultipartConfigFactory factory = new MultipartConfigFactory();</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp;factory.setMaxFileSize("128KB");</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp;factory.setMaxRequestSize("128KB");</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp;return factory.createMultipartConfig();</div><div><span style="white-space:pre">	</span> &nbsp; &nbsp;}</div><div><span style="white-space:pre">	</span></div><div>}</div><div></div>拦截器类<br /><div></div><div>public class DemoInterceptor extends HandlerInterceptorAdapter {// 1</div><div></div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public boolean preHandle(HttpServletRequest request, // 2</div><div><span style="white-space:pre">			</span>HttpServletResponse response, Object handler) throws Exception {</div><div><span style="white-space:pre">		</span>long startTime = System.currentTimeMillis();</div><div><span style="white-space:pre">		</span>System.out.println("本次始请求处理时间为:" + startTime + "ms");</div><div><span style="white-space:pre">		</span>request.setAttribute("startTime", startTime);</div><div><span style="white-space:pre">		</span>if (request.getHeader("x-requested-with") != null</div><div><span style="white-space:pre">				</span>&amp;&amp; request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {</div><div><span style="white-space:pre">			</span>response.setHeader("sessionstatus", "timeout"); // 响应头设置session状态</div><div><span style="white-space:pre">		</span>} else {</div><div><span style="white-space:pre">			</span>response.sendRedirect("/");</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span>return false;</div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span>@Override</div><div><span style="white-space:pre">	</span>public void postHandle(HttpServletRequest request, // 3</div><div><span style="white-space:pre">			</span>HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {</div><div><span style="white-space:pre">		</span>long startTime = (Long) request.getAttribute("startTime");</div><div><span style="white-space:pre">		</span>request.removeAttribute("startTime");</div><div><span style="white-space:pre">		</span>long endTime = System.currentTimeMillis();</div><div><span style="white-space:pre">		</span>System.out.println("本次请求处理时间�?:" + new Long(endTime - startTime) + "ms");</div><div><span style="white-space:pre">		</span>request.setAttribute("handlingTime", endTime - startTime);</div><div><span style="white-space:pre">	</span>}</div><div></div><div></div><div>}</div></div></div></div>文件上传页面upload.jsp<br /><div></div><div>&lt;%@ page language="java" contentType="text/html; charset=UTF-8"</div><div>&nbsp; &nbsp; pageEncoding="UTF-8"%&gt;</div><div>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;</div><div>&lt;html&gt;</div><div>&lt;head&gt;</div><div>&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;</div><div>&lt;title&gt;upload page&lt;/title&gt;</div><div></div><div>&lt;/head&gt;</div><div>&lt;body&gt;</div><div></div><div></div><div>&lt;div class="upload"&gt;</div><div><span style="white-space:pre">	</span>&lt;form action="upload" enctype="multipart/form-data" method="post"&gt;</div><div><span style="white-space:pre">		</span>&lt;input type="file" name="file"/&gt;&lt;br/&gt;</div><div><span style="white-space:pre">		</span>&lt;input type="submit" value="上传"&gt;</div><div><span style="white-space:pre">	</span>&lt;/form&gt;</div><div>&lt;/div&gt;</div><div></div><div></div><div>&lt;/body&gt;</div><div>&lt;/html&gt;</div><div><br />文件上传控制器类<br /><br /><div>@Controller</div><div>public class UploadController {</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span>@RequestMapping(value = "/upload",method = RequestMethod.POST)</div><div><span style="white-space:pre">	</span>//MultipartFile[] ,涓婁紶澶氫釜鏂囦欢</div><div><span style="white-space:pre">	</span>public @ResponseBody String upload(@RequestParam("file") MultipartFile file) {//1</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">			</span>try {</div><div><span style="white-space:pre">				</span>FileUtils.writeByteArrayToFile(new File("e:/upload/"+file.getOriginalFilename()),</div><div><span style="white-space:pre">						</span>file.getBytes()); //2</div><div><span style="white-space:pre">				</span>return "ok";</div><div><span style="white-space:pre">			</span>} catch (IOException e) {</div><div><span style="white-space:pre">				</span>e.printStackTrace();</div><div><span style="white-space:pre">				</span>return "wrong";</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">			</span></div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">	</span>}</div><div></div><div>}</div></div><img src ="http://www.blogjava.net/fool/aggbug/432826.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-09-18 11:01 <a href="http://www.blogjava.net/fool/archive/2017/09/18/432826.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>springboot中的jsp支持</title><link>http://www.blogjava.net/fool/archive/2017/09/18/432823.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 18 Sep 2017 01:22:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/09/18/432823.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432823.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/09/18/432823.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432823.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432823.html</trackback:ping><description><![CDATA[springmvc4中零配置的用法在springboot中同样有效。pom.xml配置<br /><div><span style="white-space:pre">	</span>&nbsp; &nbsp; &nbsp; &nbsp;&lt;dependency&gt;</div><div><span style="white-space:pre">			</span>&lt;groupId&gt;javax.servlet&lt;/groupId&gt;</div><div><span style="white-space:pre">			</span>&lt;artifactId&gt;jstl&lt;/artifactId&gt;</div><div><span style="white-space:pre">	</span>&nbsp; &nbsp; &nbsp;&nbsp;&lt;/dependency&gt;</div><div><span style="white-space:pre">	</span>&nbsp; &nbsp;&lt;dependency&gt;</div><div><span style="white-space:pre">			</span>&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</div><div><span style="white-space:pre">			</span>&lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;</div><div><span style="white-space:pre">			</span>&lt;scope&gt;provided&lt;/scope&gt;</div><div><span style="white-space:pre">		</span>&lt;/dependency&gt;</div><div><span style="white-space:pre">		</span>&lt;dependency&gt;</div><div><span style="white-space:pre">			</span>&lt;groupId&gt;org.apache.tomcat.embed&lt;/groupId&gt;</div><div><span style="white-space:pre">			</span>&lt;artifactId&gt;tomcat-embed-jasper&lt;/artifactId&gt;</div><div><span style="white-space:pre">			</span>&lt;scope&gt;provided&lt;/scope&gt;</div><div><span style="white-space:pre">		</span>&lt;/dependency&gt;<br /><br />写配置类配置jsp支持<br /><div>@Configuration</div><div>public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {<br /><br /><div><span style="white-space:pre">	</span>@Bean</div><div><span style="white-space:pre">	</span>public InternalResourceViewResolver viewResolver() {</div><div><span style="white-space:pre">		</span>InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();</div><div><span style="white-space:pre">		</span>viewResolver.setPrefix("/WEB-INF/views/");</div><div><span style="white-space:pre">		</span>viewResolver.setSuffix(".jsp");</div><div><span style="white-space:pre">		</span>viewResolver.setViewClass(JstlView.class);</div><div><span style="white-space:pre">		</span>return viewResolver;</div><div><span style="white-space:pre">	</span>}<br /><br />}<br /><br />所谓零配置。。。 一言难尽<br /></div></div></div><img src ="http://www.blogjava.net/fool/aggbug/432823.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-09-18 09:22 <a href="http://www.blogjava.net/fool/archive/2017/09/18/432823.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>js外部调用更新angularjs的ng-repeat视图问题 </title><link>http://www.blogjava.net/fool/archive/2017/09/11/432808.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 11 Sep 2017 13:37:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/09/11/432808.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432808.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/09/11/432808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432808.html</trackback:ping><description><![CDATA[找了个开源基础框架测试一下微信公众号。没想是用jquery做的restful风格的页面。jquery更<br />新table中数据就有些麻烦。所以用angularjs重构一下。<br />页面中angularjs展示数据 &nbsp;<br />&lt;body &nbsp; ng-controller="multi"&gt;&nbsp;<br /><div>&nbsp; &lt;table id="baseTable" class="table table-striped table-bordered table-hover" &gt;</div><div><span style="white-space:pre">					</span>&lt;thead&gt;</div><div><span style="white-space:pre">						</span>&lt;tr&gt;&lt;th style="width:10%" class="center"&gt;标题&lt;/th&gt;</div><div><span style="white-space:pre">						</span>&lt;/tr&gt;</div><div><span style="white-space:pre">					</span>&lt;/thead&gt;</div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;body &nbsp; ng-controller="multi"&gt; &nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;tbody&gt;<span style="white-space: pre;">	</span>&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;tr ng-repeat="item in defaultData " &gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;td class='center hidden-480'&gt;{{item.title}}&lt;/td&gt;&nbsp; &nbsp;&nbsp;<div><span style="white-space:pre">	</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="white-space:pre">	</span> &nbsp;&lt;/tr&gt;&nbsp;</div><div><span style="white-space:pre">		</span>&nbsp; &lt;/tbody&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/body&gt;<br />&nbsp; &lt;/table&gt;<br />&lt;/body&gt;<br />外部jquery的ajax调用更新数据&nbsp;<br /><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var controllerScope = $('body[ng-controller="multi"]').scope();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <span style="white-space:pre">	</span> &nbsp; &nbsp; controllerScope.defaultData=results;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <span style="white-space:pre">	</span> &nbsp; &nbsp; controllerScope.$apply();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <span style="white-space:pre">	</span>&nbsp;&nbsp;</div><div>注意：外部js不要删除了下面这段代码块。<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;tr ng-repeat="item in defaultData " &gt;</div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;td class='center hidden-480'&gt;{{item.title}}&lt;/td&gt;&nbsp; &nbsp;&nbsp;<div><span style="white-space: pre;">	</span>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="white-space: pre;">	</span>&nbsp;&nbsp;&lt;/tr&gt;&nbsp;</div></div><img src ="http://www.blogjava.net/fool/aggbug/432808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-09-11 21:37 <a href="http://www.blogjava.net/fool/archive/2017/09/11/432808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>业务规则与自定义规则处理库</title><link>http://www.blogjava.net/fool/archive/2017/08/20/432763.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Sun, 20 Aug 2017 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/08/20/432763.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432763.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/08/20/432763.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432763.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432763.html</trackback:ping><description><![CDATA[前篇随笔《需求收集、分析》中简单提了一下业务规则。业务规则是很重要的一个东西，并且用户对于业务规则也极易<br />更改或者新增新的业务规则.尤其是在某些场合如促销，积分商城等场景。正因为规则如此重要，建议使用单独的文档<br />维护，规则名称编号可以与用例名称编对一一对应。<br />业务规则分类：<br />一,内禀规则：业务实体本身的规则。如订单中销售记录不能为空，数量不能为等。<br />二，全局规则：一般与所有用例相关而不是某个特定用例相关。例如系统安全方面的sql注入，ddos攻击等。<br />三，交互规则：用于用例当中。<span style="font-family: Arial; background-color: #ffffff;">它们规定了满足什么条件后业务将如何反应。有些规则需要开发成系统用例。比如人事<br />管理系统中请假业务只有工作日才计入请假天数，那么这个工作日就需要电脑来维护了，会作为一个系统用例存在，并<br />且作为请假用例的前置条件。 交互规则又是最容易引起.<br />交互规则如此灵活多变，需要良好的设计才能保证系统的扩展性和可维护性。如何做：<br />思路一：<br />&nbsp; &nbsp; 在 j</span><span style="font-family: &quot;ms shell dlg&quot;; background-color: #ffffff;">avax.swing.border包提供了</span><span style="font-family: &quot;ms shell dlg&quot;; background-color: #ffffff;">Border接口和几个不同的Boder的实现。在swing中每个组件提供了paint方法，每<br />个组件知道怎么画自己展示自己的外观。那么我们可以提供业务规则处理接口，每个具体业务规则自己知道怎么处理业务。<br />可以用简单工厂来决定调用哪一个具体业务规则。这个是策略模式的使用,缺点是新增具体业务时工厂类会修改。也可以<br />用观察者模式来实现，所有的具体业务类都来观察这个业务规则，自己判断是不是自己可以处理的，不是就不理会。<br />基于策略模式的规则实现类图:<br /><img src="http://www.blogjava.net/images/blogjava_net/fool/rule.png" border="0" alt="" /><br />思路二：<br />&nbsp; &nbsp; &nbsp;规则引擎比如drools处理一些问题 。</span><span style="color: #333333; font-family: Arial; background-color: #ffffff;">规则引擎适合于做业务规则频繁变化的场景.</span><span style="background-color: #ffffff;"><font face="ms shell dlg">把业务规则抽出来通过规则引擎来</font><br /><font face="ms shell dlg">处理。类似工作流系统的概念。</font><br /><br /><font face="ms shell dlg">自定义规则处理库:</font><br /><font face="ms shell dlg">&nbsp; &nbsp; &nbsp;一些动态的语言很适合来做这样的事情。java支持script.Mvel是一个表达式语言，drools也支持mvel来处理业务规则.</font><br /><font face="ms shell dlg">这里自定义规则引擎使用Mvel表达式语言.</font><br /><font face="ms shell dlg">&nbsp; &nbsp; &nbsp; 规则文件示例：</font><br /><font face="ms shell dlg">&nbsp; &nbsp; &nbsp;</font></span>&lt;rules&gt;<div>&nbsp; &nbsp; &nbsp; &nbsp;&lt;!--rule-set 是一个规则集,执行规则 rule1时会迭代规则集里面所有的规则(mvel-rule)--&gt;</div><div><span style="white-space:pre">	</span>&lt;rule-set name="rule1"&gt;</div><div><span style="white-space:pre">		</span>&lt;!-- id是规则的标识，也是默认的排序处理顺序。exclusive 是排它。如果为true,则当前规则执行后，不再执行后面的规则--&gt;</div><div><span style="white-space:pre">		</span>&lt;mvel-rule id="step1" &nbsp;exclusive="false"&gt;</div><div><span style="white-space:pre">			</span>&lt;block&gt;&lt;![CDATA[</div><div><span style="white-space:pre">			</span>if(salary&lt;=3500) {result=0;}</div><div><span style="white-space:pre">			</span>]]&gt;&lt;/block&gt;</div><div></div><div><span style="white-space:pre">		</span>&lt;/mvel-rule&gt;</div><div><span style="white-space:pre">		</span>&lt;mvel-rule id="step2" exclusive="false"&gt;</div><div><span style="white-space:pre">			</span>&lt;block&gt;&lt;![CDATA[if(salary&gt;3500) {result=1};]]&gt;&lt;/block&gt;</div><div></div><div><span style="white-space:pre">		</span>&lt;/mvel-rule&gt;</div><div></div><div><span style="white-space:pre">	</span>&lt;/rule-set&gt;</div><div></div><div></div><div><span style="white-space:pre">	</span>&lt;rule-set name="rule2"&gt;</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">		</span>&lt;mvel-rule id="step1" &nbsp;exclusive="false"&gt;</div><div><span style="white-space:pre">			</span>&lt;block&gt;&lt;![CDATA[&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;import &nbsp;com.custom.rule.*;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rs = new RuleSet();&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rs.name="asdf";</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rs.print();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;]]&gt;&lt;/block&gt;</div><div></div><div><span style="white-space:pre">		</span>&lt;/mvel-rule&gt;</div><div></div><div></div><div><span style="white-space:pre">	</span>&lt;/rule-set&gt;</div><div></div><div>&lt;/rules&gt;</div>rule2中可见mvel可以导入未知jar包并进行处理，确实强大，就有了足够的灵活性.&nbsp;<span style="background-color: #ffffff;">自定义规则库源码及使用示例<a href="/Files/fool/rules.rar">下载</a>.<a></a><br />本例依赖xstream</span>1.4.9 ,mvel2.0<span style="background-color: #ffffff;"><br /></span><span style="background-color: #ffffff;">自定义规则库除了可以应用于一般系统业务处理，当然也还可以用于大数据处理。比如hadoop/spark统计用户积分等<br />如果再定义一套配置规则的UI。。。好的，业务人员可以自己设置计算规则了。<br /><br /><br /><br /><br /></span><br /><span style="font-family: &quot;ms shell dlg&quot;; background-color: #ffffff;"><br /></span><img src ="http://www.blogjava.net/fool/aggbug/432763.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-08-20 14:52 <a href="http://www.blogjava.net/fool/archive/2017/08/20/432763.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>架构设计过程分析小结</title><link>http://www.blogjava.net/fool/archive/2017/04/28/432490.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Fri, 28 Apr 2017 06:22:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/04/28/432490.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432490.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/04/28/432490.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432490.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432490.html</trackback:ping><description><![CDATA[<p><span style="font-family:宋体;">架构设计过程简单总结：架构设计的驱动力</span>=<span style="font-family:宋体;">功能</span>+<span style="font-family:宋体;">质量</span>+<span style="font-family:宋体;">约束</span>.<span style="font-family:宋体;">功能即系统要满足的业务需求。质量包括运行期质量和开发期质量</span>. <span style="font-size:11.0pt; font-family:宋体;color:#333333;background:white">常见的运行期质量属性包括软件系统的易用性、性能、可伸缩性、持续可用性、鲁棒性、安全性等。开发期质量属性是开发人员最为关心的，要达到怎样的目标应根据项目的具体情况而定。</span><span style="font-family:宋体;">约束可能是商业预算，运行环境，使用人员水平，开发团队水平等。架构设计过程如下</span>:<br /></p><p class="MsoListParagraph" style="margin-left:21.0pt;text-indent:-21.0pt;
mso-char-indent-count:0;mso-list:l0 level1 lfo1"><!--[if !supportLists]--><span lang="EN-US">一，</span><!--[endif]--><span style="font-family:
宋体;mso-ascii-font-family:Calibri;mso-ascii-theme-font:minor-latin;mso-fareast-font-family:
宋体;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin">需求收集，分析。</span></p><p style="margin-left:21.0pt;text-indent:0cm;"><span style="font-family:宋体;">此处省略</span>2000<span style="font-family:宋体;">字。。。</span><span style="text-indent: 0cm;">&nbsp;见前篇 《</span><a id="Editor_Results_rprSelectionList_ctl02_Hyperlink1" class="titlelink" href="http://www.blogjava.net/fool/archive/2017/04/28/432489.html" style="color: black; text-decoration-line: none; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: #ffffff; font-size: 12px; font-family: Arial;">需求收集、分析小结</a><span style="color: #333333; font-family: arial; font-size: 12px; background-color: #ffffff;">》</span>http://www.blogjava.net/fool/archive/2017/04/28/432489.html</p>  <p style="margin-left:21.0pt;text-indent:-21.0pt;">二，<span style="font-family: 宋体;">概念架构</span>/<span style="font-family:宋体;">概念模型</span></p>  <p style="margin-left:21.0pt;text-indent:0cm;"><span style="font-family:宋体;">从需求中找出关健、重大需求，进行概念建模</span>.<span style="font-family:宋体;">下面三个图称之鲁棒图。其中控制对象理解为</span>mvc<span style="font-family:宋体;">模式中的控制器和</span>model<span style="font-family:宋体;">。使用鲁棒图可以建立概念模型，约等于初步设计。初步设计并不关心细节。</span></p>  <p style="margin-left:21.0pt;text-indent:0cm;">&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/fool/j1.png" border="0" alt="" /><br /></p><p class="MsoNormal">&nbsp;<span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:宋体;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family:
Calibri;mso-hansi-theme-font:minor-latin">鲁棒图建立概念模型语法</span><span lang="EN-US">:<br /><img src="http://www.blogjava.net/images/blogjava_net/fool/j2.png" border="0" alt="" /><br /></span></p><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">概念设计举例：</span><span lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal"><span lang="EN-US"><br /></span></p><p><span style="font-family:宋体;">上次谈到超市小票如何分析实体对象</span>,<span style="font-family:宋体;">本次接着举例如何对收银进行概念建模<br /><br /><br /><img src="http://www.blogjava.net/images/blogjava_net/fool/j3.png" border="0" alt="" /><br /></span></p>  <p align="left"> </p>  <span style="font-size:10.5pt;font-family:宋体;Times New Roman&quot;;">如上图：具备基本收银功能的概念模型。概念模型建模可以是增量的。比如商品折扣或其它</span><br /><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">促销活动等。</span><span lang="EN-US"><o:p></o:p></span></p><p><br /></p><p><span style="font-family:宋体;">概念架构的用途：</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">1）&nbsp;<span style="font-family:宋体;">可以帮助我们找出领域模型中的实体对象。</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">2）&nbsp;<span style="font-family:宋体;">检查需求用例是否正确和完善。</span></p>  <p>3<span style="font-family:宋体;">）初步设计</span>,<span style="font-family:宋体;">鲁棒图是一种初步设计技术。</span></p>  <p>4<span style="font-family:宋体;">）根据用例和概念设计划分系统、子系统、模块或者包。借助鲁棒图</span>,<span style="font-family:宋体;">初步识别功能背后的职责，规划切分系统的方式。</span></p>  <p>&nbsp;</p>  <p style="margin-left:21.0pt;text-indent:-21.0pt;">三，<span style="font-family: 宋体;">关注非功能性需求，包括运行期质量和开发期质量。</span></p>  <p style="margin-left:21.0pt;text-indent:0cm;"><span style="font-family:宋体;">运用目标</span>&#8212;<span style="font-family:宋体;">场景</span>&#8212;<span style="font-family:宋体;">决策表对非功能性需求作出决策</span>.<span style="font-family:宋体;">小举例：</span></p>  <table border="1" cellspacing="0" cellpadding="0" style="margin-left: 21pt; border-collapse: collapse; border-width: initial; border-style: none; border-color: initial;">  <tbody><tr>   <td width="189" valign="top" style="width: 142pt; border-width: 1pt; border-style: solid; border-color: windowtext; padding: 0cm 5.4pt;">   <p style="text-indent:0cm;"><span style="font-family:宋体;">目标</span></p>   </td>   <td width="189" valign="top" style="width: 142.05pt; border-top: 1pt solid windowtext; border-right: 1pt solid windowtext; border-bottom: 1pt solid windowtext; border-left: none; padding: 0cm 5.4pt;">   <p style="text-indent:0cm;"><span style="font-family:宋体;">场景</span></p>   </td>   <td width="189" valign="top" style="width: 142.05pt; border-top: 1pt solid windowtext; border-right: 1pt solid windowtext; border-bottom: 1pt solid windowtext; border-left: none; padding: 0cm 5.4pt;">   <p style="text-indent:0cm;"><span style="font-family:宋体;">决策</span></p>   </td>  </tr>  <tr>   <td width="189" valign="top" style="width: 142pt; border-right: 1pt solid windowtext; border-bottom: 1pt solid windowtext; border-left: 1pt solid windowtext; border-top: none; padding: 0cm 5.4pt;">   <p style="text-indent:0cm;"><span style="font-family:宋体;">易用性</span></p>   </td>   <td width="189" valign="top" style="width:142.05pt;border-top:none;border-left:   none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt">   <p style="text-indent:0cm;"><span style="font-family:宋体;">销售员需要输入条码检索商品</span>,<span style="font-family:宋体;">繁琐且速度慢</span></p>   </td>   <td width="189" valign="top" style="width:142.05pt;border-top:none;border-left:   none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt">   <p style="text-indent:0cm;"><span style="font-family:宋体;">根据条码，品名模糊匹配检索商品</span>,<span style="font-family:宋体;">提供辅助录入。</span></p>   </td>  </tr>  <tr>   <td width="189" valign="top" style="width: 142pt; border-right: 1pt solid windowtext; border-bottom: 1pt solid windowtext; border-left: 1pt solid windowtext; border-top: none; padding: 0cm 5.4pt;">   <p style="text-indent:0cm;"><span style="font-family:宋体;">性能</span></p>   </td>   <td width="189" valign="top" style="width:142.05pt;border-top:none;border-left:   none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt">   <p style="text-indent: 0cm;"><span style="font-family:宋体;">长时间稳定运行</span></p>   </td>   <td width="189" valign="top" style="width:142.05pt;border-top:none;border-left:   none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt">   <p style="text-indent:0cm;"><span style="font-family: 宋体;">数据库集群，服务应用集群</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;&nbsp;</span></p>   </td>  </tr> </tbody></table>&nbsp; &nbsp; &nbsp; &nbsp; 技术选型 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 需要管理钱箱、打印机、响应速 &nbsp; &nbsp;pos系统使用c/s<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 度快<br />  <p style="margin-left: 21pt; text-indent: 0cm;">&nbsp;</p>  <p style="margin-left:21.0pt;text-indent:0cm;">&nbsp;</p><div style="display: inline-block;"></div><p>&nbsp;</p><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">四，细化架构。</span><span lang="EN-US">RUP 4+1</span><span style="font-family:宋体;mso-ascii-font-family:
Calibri;mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">视图法则将架构需要关注的不同的点使用不同的视图表示</span><span lang="EN-US">.</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">从不同的维度对系统进行解读</span><span lang="EN-US">,</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">从而形成统一软件过程架构描述。</span><span lang="EN-US"><o:p></o:p></span></p><p style="margin-left:21.0pt;text-indent:0cm;"></p><p><span style="font-family:宋体;">运行架构：</span></p>  <p><span style="font-family:宋体;">关心进程、线程、同步的相关设计，捕捉并发和同步特征</span></p>  <p><span style="font-family:宋体;">逻辑架构：</span></p>  <p><span style="font-family:宋体;">关心逻辑层</span>(layer)<span style="font-family:宋体;">的划分，系统</span>/<span style="font-family:宋体;">子系统的划分，划分模块及其接口的定义。功能组划分也属于逻辑架构</span>.<span style="font-family:宋体;">功能</span>:<span style="font-family:宋体;">不仅包括用户可见的功能，还包括为实现用户功能而必须提供的</span>"<span style="font-family:宋体;">辅助功能模块</span>"<span style="font-family:宋体;">；它们可能是逻辑层、功能模块等。</span></p>  <p><span style="font-family:宋体;">物理架构：</span></p>  <p><span style="font-family:宋体;">关心服务器选型，物理层划分</span>(tier)<span style="font-family:宋体;">。</span> <span style="font-family:宋体;">描述如何部署机器和网络来配合软件系统的可靠性、可伸缩性等要求</span>.layer<span style="font-family:宋体;">就运行在</span>tier<span style="font-family:宋体;">上。</span>Tier<span style="font-family:宋体;">反映系统伸缩能力。</span></p>  <p><span style="font-family:宋体;">开发架构：</span></p>  <p><span style="font-family:宋体;">描述了在开发环境中软件的静态组织结构。即开发工具下的开发视图，描述文件编译及其依赖关系。而使用</span>maven<span style="font-family:宋体;">管理开发的项目编译及依赖关系结构更加分明。</span></p>  <p><span style="font-family:宋体;">数据架构：</span></p>  <p><span style="font-family:宋体;">关心数据的存储、分布和文件的存放及数据的复制，传递，同步。数据的存放包括</span>sql,<span style="font-family:宋体;">内存数据库，</span>nosql<span style="font-family:宋体;">数据库等</span>.</p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">逻辑架构设计举例：</span></p>  <p><span style="font-family: 宋体;">还是用收银系统简单举例，收银系统逻辑架构图如下：<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/fool/j4.png" border="0" alt="" /><br /><br /></span></p><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">整个系统划系统为系统，切为两个系统，一个收银员角色处理的业务，收银系统。</span><span lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">一个后台管理系统。后台管理系统包括用户管理模块，基础资料模块（产品资料等）</span><span lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">销售模块（本例对销售单）。另外，因为收银系统需要和后台系统交互，把收银系统需要使用到的相关的各模块封装成一个接口模块，专门处理和收银系统交互的模块。系统、模块之间的通讯方式应当尽量避免双向。相互依赖可能会引发很多问题。</span><span lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal"><span lang="EN-US">&nbsp;</span></p><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">物理架构设计举例：</span><span lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">物理架构和逻辑架构可以相互印证。描述软件系统的物理布署。<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/fool/j5.png" border="0" alt="" /><br /><br /></span></p><p class="MsoNormal" align="left"><span style="font-size:12.0pt;font-family:宋体;mso-bidi-font-family:宋体;mso-font-kerning:
0pt">如果考虑运行期质量比如长时间运行布署图可能应用做集群。数据库做集群等。逻辑层<span lang="EN-US">layer</span>运行在物理层<span lang="EN-US">tier</span>之上<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal"><span lang="EN-US">&nbsp;</span></p><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">运行架构和数据架构视图根据实际情况可选设计</span><span lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal">



<span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin"><br /></span><span lang="EN-US"><o:p></o:p></span></p><p>









<span style="font-family: 宋体;"><br /></span></p><img src ="http://www.blogjava.net/fool/aggbug/432490.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2017-04-28 14:22 <a href="http://www.blogjava.net/fool/archive/2017/04/28/432490.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>