Fabric go sdk初始化所需证书解析
fabric sdk go 提供的官方文档少之又少,要想入门,主要就靠研究官方的e2e
系列示例,这真的是一件挺无奈的事情。没法子,只能硬着头皮上了。研究发现,e2e
这个例子是通过cryptogen
生成网络所需的所有证书及密钥的。一旦你按着操作后,你会发现你被大堆目录淹没,不知所措,根本不知道他们都是干嘛的。
那么,这篇文章的作用,就是告诉你,他们都是干嘛的,哪些是初始化sdk所需的。
让我们开始吧!
生成证书配置
首先,用于生成证书目录的配置文件crypto-config.yaml
内容如下所示
# "OrdererOrgs" - Definition of organizations managing orderer nodes
OrdererOrgs:
- Name: Mango
Domain: mango.com
# Specs is an array of Spec entries. Each Spec entry consists of two fields : Hostname and CommonName
Specs:
- Hostname: orderer
# "PeerOrgs" - Definition of organizations managing peer nodes
PeerOrgs:
- Name: Mango
Domain: mango.com
# Allows for the definition of 1 or more hosts that are created sequentially
# from a template. By default, this looks like "peer%d" from 0 to Count-1.
# You may override the number of nodes (Count), the starting index (Start)
# or the template used to construct the name (Hostname).
Template:
Count: 2
证书目录解析
我们根据上述配置来生成证书
mkdir -p crypto-config
./bin/cryptogen generate --config=./crypto-config.yaml
每个目录和对应文件的功能如下:
crypto-config
├── ordererOrganizations
│ └── mango.com # domain
│ ├── ca
│ │ ├── ca.mango.com-cert.pem
│ │ └── ed9854ea794ed178750ab5fff0b8f7a4c4938721e85de25a65e171dac4dadf41_sk
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@mango.com-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.mango.com-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.mango.com-cert.pem
│ ├── orderers
│ │ └── orderer.mango.com
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── Admin@mango.com-cert.pem
│ │ │ ├── cacerts
│ │ │ │ └── ca.mango.com-cert.pem
│ │ │ ├── keystore
│ │ │ │ └── b1ee6269b624746f682843f566dcfdbb9b1318ea36d605becc13843f52d13e2c_sk
│ │ │ ├── signcerts
│ │ │ │ └── orderer.mango.com-cert.pem
│ │ │ └── tlscacerts
│ │ │ └── tlsca.mango.com-cert.pem
│ │ └── tls
│ │ ├── ca.crt
│ │ ├── server.crt
│ │ └── server.key
│ ├── tlsca
│ │ ├── 30fe7e37c6b416049d567b99d07d4d0fca282d28cf51819a8ba9cb12a4b1b5c1_sk
│ │ └── tlsca.mango.com-cert.pem
│ └── users
│ └── Admin@mango.com
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@mango.com-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.mango.com-cert.pem
│ │ ├── keystore
│ │ │ └── 749735ce27f18879efa1ffdf76bf9d800ccb0298c826cee2c2d68217eb731610_sk
│ │ ├── signcerts
│ │ │ └── Admin@mango.com-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.mango.com-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── client.crt
│ └── client.key
└── peerOrganizations
└── org1.mango.com
├── ca # 存放组织的根证书和对应的私钥文件,默认采用EC算法,证书为自签名。组织内的实体将基于该证书作为证书根。
│ ├── 2c3c2cde48c8f1b5eb0fd54e0b1865d6b5bc3269ebba8cb5ac5a7dfbbd303367_sk
│ └── ca.org1.mango.com-cert.pem
├── msp # 存放代表该组织的身份信息。
│ ├── admincerts # 组织管理员的身份验证证书,被根证书签名。
│ │ └── Admin@org1.mango.com-cert.pem
│ ├── cacerts # 组织的根证书,同ca目录下文件。
│ │ └── ca.org1.mango.com-cert.pem
│ └── tlscacerts # 用于TLS的ca证书,自签名。
│ └── tlsca.org1.mango.com-cert.pem
├── peers # 存放属于该组织的所有peer节点。
│ ├── peer0.org1.mango.com # 第一个peer的信息,包括其msp证书和TLS证书两类。
│ │ ├── msp
│ │ │ ├── admincerts # 组织管理员的身份验证证书。peer将基于这些证书来认证交易签署这是否为管理员身份。
│ │ │ │ └── Admin@org1.mango.com-cert.pem
│ │ │ ├── cacerts # 组织的根证书.
│ │ │ │ └── ca.org1.mango.com-cert.pem
│ │ │ ├── keystore # 本节点的身份私钥,用来签名。
│ │ │ │ └── d35fbb340c84ad06ffd6d58addaf694a62e23adf53066b9a287f86edbf6dd476_sk
│ │ │ ├── signcerts # 验证本节点签名的证书,被组织根证书签名。
│ │ │ │ └── peer0.org1.mango.com-cert.pem
│ │ │ └── tlscacerts # TLS连接用的身份证书,即组织TLS证书。
│ │ │ └── tlsca.org1.mango.com-cert.pem
│ │ └── tls # 存放tls相关的证书和私钥
│ │ ├── ca.crt # 组织的根证书
│ │ ├── server.crt # 验证本节点签名的证书,被组织根证书签名。
│ │ └── server.key # 本节点的身份私钥,用来签名。
│ └── peer1.org1.mango.com # 第二个peer的信息,结构类似。(省略)
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@org1.mango.com-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.org1.mango.com-cert.pem
│ │ ├── keystore
│ │ │ └── ecfeefdab7f95113064a00227d7af5cb3ae448ec1334a932f768010b95dc32f3_sk
│ │ ├── signcerts
│ │ │ └── peer1.org1.mango.com-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.org1.mango.com-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── server.crt
│ └── server.key
├── tlsca 存放组织tls连接用的根证书和私钥文件。(TLS是传输层安全协议,其实就是SSL,现在叫TLS了)
│ ├── 65b65931318b4aa19ae15d1da75413c68371d1506237311fc7244c8e46c1ba8a_sk
│ └── tlsca.org1.mango.com-cert.pem # TLS根证书
└── users 存放属于该组织的用户的实体。
└── Admin@org1.mango.com # 管理员用户的信息,包括其msp证书和tls证书两类。
├── msp
│ ├── admincerts # 组织根证书作为管理者身份验证证书。
│ │ └── Admin@org1.mango.com-cert.pem
│ ├── cacerts # 组织的根证书.
│ │ └── ca.org1.mango.com-cert.pem
│ ├── keystore # 本用户的身份私钥,用来签名。
│ │ └── 22e70042f7dd79f35ea92a285d2377a673163805f85c9bf160c87de82db52a4c_sk
│ ├── signcerts # 管理员用户的身份验证证书,被组织根证书签名。要被某个Peer认可,则必须放到该peer的msp/admincerts下。
│ │ └── Admin@org1.mango.com-cert.pem
│ └── tlscacerts # TLS连接用的身份证书,即组织TLS证书。
│ └── tlsca.org1.mango.com-cert.pem
└── tls # 存放tls相关的证书和私钥
├── ca.crt # 组织的根证书
├── client.crt # 管理员的用户身份验证证书,被组织根证书签名。
└── client.key # 管理员用户的身份私钥,用来签名。
证书目录精简
一大堆文件是不是?其实经过分析后,可以发现,很多目录的证书或者密钥都是重复的。真正用到的主要是:
- 组织中
Admin
用户的证书和密钥 - 组织中的tls证书
如果你启用了其他用户,比如
User1
之类的,就还会有User1@mango.com
这样的目录
精简目录
让我们删除多余目录,精简后目录如下所示:
fixtures/crypto/
├── ordererOrganizations
│ └── mango.com
│ ├── tlsca
│ └── tlsca.org1.mango.com-cert.pem
└── peerOrganizations
└── org1.mango.com
├── tlsca
│ └── tlsca.org1.mango.com-cert.pem
└── users
└── Admin@org1.mango.com
└── msp
├── keystore
│ └── 22e70042f7dd79f35ea92a285d2377a673163805f85c9bf160c87de82db52a4c_sk
└── signcerts
└── Admin@org1.mango.com-cert.pem
怎么样,是不是清爽多了。
证书目录再精简
本节内容依个人业务差异,仅供参考
我们发现证书的路径六面都带有mango.com
这样的ID字段,不方便重用,我们可以选择去除这些ID,精简目录。
此外,密钥文件22e70042f7dd79f35ea92a285d2377a673163805f85c9bf160c87de82db52a4c_sk
名称前面还有一长串的字符,看上去很奇怪是不是。这个一长串的字符,其实就是ski
。我们也可以去除这个ski。
当然,如果你直接去除这些东西,那么sdk会报找不到响应文件的错误,所以我们需要去修改sdk源码。
主要修改的文件如下:
fabric-go-sdk/pkg/msp/filecertstore.go
原先代码
// NewFileCertStore ...
func NewFileCertStore(cryptoConfigMSPPath string) (core.KVStore, error) {
_, orgName := path.Split(path.Dir(path.Dir(path.Dir(cryptoConfigMSPPath))))
opts := &keyvaluestore.FileKeyValueStoreOptions{
Path: cryptoConfigMSPPath,
KeySerializer: func(key interface{}) (string, error) {
ck, ok := key.(*msp.IdentityIdentifier)
if !ok {
return "", errors.New("converting key to CertKey failed")
}
if ck == nil || ck.MSPID == "" || ck.ID == "" {
return "", errors.New("invalid key")
}
// TODO: refactor to case insensitive or remove eventually.
r := strings.NewReplacer("{userName}", ck.ID, "{username}", ck.ID)
certDir := path.Join(r.Replace(cryptoConfigMSPPath), "signcerts")
return path.Join(certDir, fmt.Sprintf("%s@%s-cert.pem", ck.ID, orgName)), nil
},
}
return keyvaluestore.New(opts)
}
修改后代码
// NewFileCertStore ...
func NewFileCertStore(cryptoConfigMSPPath string) (core.KVStore, error) {
opts := &keyvaluestore.FileKeyValueStoreOptions{
Path: cryptoConfigMSPPath,
KeySerializer: func(key interface{}) (string, error) {
ck, ok := key.(*msp.IdentityIdentifier)
if !ok {
return "", errors.New("converting key to CertKey failed")
}
if ck == nil || ck.MSPID == "" || ck.ID == "" {
return "", errors.New("invalid key")
}
// TODO: refactor to case insensitive or remove eventually.
// 文件夹去除Mspid名称
r := strings.NewReplacer("{userName}", ck.ID)
certDir := path.Join(r.Replace(cryptoConfigMSPPath), "signcerts")
// 文件名精简为cert.pem
return path.Join(certDir, "cert.pem"), nil
},
}
return keyvaluestore.New(opts)
}
fabric-go-sdk/pkg/msp/filecertstore.go
原先代码
// NewFileKeyStore ...
func NewFileKeyStore(cryptoConfigMSPPath string) (core.KVStore, error) {
opts := &keyvaluestore.FileKeyValueStoreOptions{
Path: cryptoConfigMSPPath,
KeySerializer: func(key interface{}) (string, error) {
pkk, ok := key.(*msp.PrivKeyKey)
if !ok {
return "", errors.New("converting key to PrivKeyKey failed")
}
if pkk == nil || pkk.MSPID == "" || pkk.ID == "" || pkk.SKI == nil {
return "", errors.New("invalid key")
}
// TODO: refactor to case insensitive or remove eventually.
r := strings.NewReplacer("{userName}", pkk.ID, "{username}", pkk.ID)
keyDir := path.Join(r.Replace(cryptoConfigMSPPath), "keystore")
return path.Join(keyDir, hex.EncodeToString(pkk.SKI)+"_sk"), nil
},
}
return keyvaluestore.New(opts)
}
修改后代码
// NewFileKeyStore ...
func NewFileKeyStore(cryptoConfigMSPPath string) (core.KVStore, error) {
opts := &keyvaluestore.FileKeyValueStoreOptions{
Path: cryptoConfigMSPPath,
KeySerializer: func(key interface{}) (string, error) {
pkk, ok := key.(*msp.PrivKeyKey)
if !ok {
return "", errors.New("converting key to PrivKeyKey failed")
}
if pkk == nil || pkk.MSPID == "" || pkk.ID == "" || pkk.SKI == nil {
return "", errors.New("invalid key")
}
// TODO: refactor to case insensitive or remove eventually.
r := strings.NewReplacer("{userName}", pkk.ID, "{username}", pkk.ID)
keyDir := path.Join(r.Replace(cryptoConfigMSPPath), "keystore")
// 文件名统一为_sk
return path.Join(keyDir, "_sk"), nil
},
}
return keyvaluestore.New(opts)
}
再次精简后的目录
如此修改后,对应的证书目录,我们就可以改成如下所示:
fixtures/crypto/
├── ordererOrganizations
│ └── tlsca
│ └── tlsca-cert.pem
└── peerOrganizations
├── tlsca
│ └── tlsca-cert.pem
└── users
└── Admin
└── msp
├── keystore
│ └── _sk
└── signcerts
└── cert.pem
怎么样,是不是又精简了很多?
初始化SDK配置文件
最后附上相应的初始化sdk所需的config.yaml
文件
name: "mango-service-network"
#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
#
version: 1.0.0
#
# The client section used by GO SDK.
#
client:
# Which organization does this application instance belong to? The value must be the name of an org
# defined under "organizations"
organization: org1
logging:
level: info
# Global configuration for peer, event service and orderer timeouts
# if this this section is omitted, then default values will be used (same values as below)
# peer:
# timeout:
# connection: 10s
# response: 180s
# discovery:
# # Expiry period for discovery service greylist filter
# # The channel client will greylist peers that are found to be offline
# # to prevent re-selecting them in subsequent retries.
# # This interval will define how long a peer is greylisted
# greylistExpiry: 10s
# eventService:
# # Event service type (optional). If not specified then the type is automatically
# # determined from channel capabilities.
# type: (deliver|eventhub)
# the below timeouts are commented out to use the default values that are found in
# "pkg/fab/endpointconfig.go"
# the client is free to override the default values by uncommenting and resetting
# the values as they see fit in their config file
# timeout:
# connection: 15s
# registrationResponse: 15s
# orderer:
# timeout:
# connection: 15s
# response: 15s
# global:
# timeout:
# query: 180s
# execute: 180s
# resmgmt: 180s
# cache:
# connectionIdle: 30s
# eventServiceIdle: 2m
# channelConfig: 30m
# channelMembership: 30s
# discovery: 10s
# selection: 10m
# Root of the MSP directories with keys and certs.
cryptoconfig:
path: ${GOPATH}/src/github.com/hyperledger/fabric-sdk-go-api/fixtures/crypto
# Some SDKs support pluggable KV stores, the properties under "credentialStore"
# are implementation specific
credentialStore:
path: /tmp/mango-service-store
# [Optional]. Specific to the CryptoSuite implementation used by GO SDK. Software-based implementations
# requiring a key store. PKCS#11 based implementations does not.
cryptoStore:
path: /tmp/mango-service-msp
# BCCSP config for the client. Used by GO SDK.
BCCSP:
security:
enabled: true
default:
provider: "SW"
hashAlgorithm: "SHA2"
softVerify: true
level: 256
tlsCerts:
# [Optional]. Use system certificate pool when connecting to peers, orderers (for negotiating TLS) Default: false
systemCertPool: false
# [Optional]. Client key and cert for TLS handshake with peers and orderers
client:
keyfile:
certfile:
#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
# section.
#
channels:
# name of the channel
mychannel:
# Required. list of orderers designated by the application to use for transactions on this
# channel. This list can be a result of access control ("org1" can only access "ordererA"), or
# operational decisions to share loads from applications among the orderers. The values must
# be "names" of orgs defined under "organizations/peers"
# deprecated: not recommended, to override any orderer configuration items, entity matchers should be used.
# orderers:
# - orderer.example.com
# Required. list of peers from participating orgs
peers:
peer0.org1.mango.com:
# [Optional]. will this peer be sent transaction proposals for endorsement? The peer must
# have the chaincode installed. The app can also use this property to decide which peers
# to send the chaincode install request. Default: true
endorsingPeer: true
# [Optional]. will this peer be sent query proposals? The peer must have the chaincode
# installed. The app can also use this property to decide which peers to send the
# chaincode install request. Default: true
chaincodeQuery: true
# [Optional]. will this peer be sent query proposals that do not require chaincodes, like
# queryBlock(), queryTransaction(), etc. Default: true
ledgerQuery: true
# [Optional]. will this peer be the target of the SDK's listener registration? All peers can
# produce events but the app typically only needs to connect to one to listen to events.
# Default: true
eventSource: true
peer1.org1.mango.com:
policies:
#[Optional] options for retrieving channel configuration blocks
queryChannelConfig:
#[Optional] min number of success responses (from targets/peers)
minResponses: 1
#[Optional] channel config will be retrieved for these number of random targets
maxTargets: 1
#[Optional] retry options for query config block
retryOpts:
#[Optional] number of retry attempts
attempts: 5
#[Optional] the back off interval for the first retry attempt
initialBackoff: 500ms
#[Optional] the maximum back off interval for any retry attempt
maxBackoff: 5s
#[Optional] he factor by which the initial back off period is exponentially incremented
backoffFactor: 2.0
#
# list of participating organizations in this network
#
organizations:
org1:
mspid: org1.mango.com
cryptoPath: peerOrganizations/users/{userName}/msp
peers:
- peer0.org1.mango.com
- peer1.org1.mango.com
# [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based
# network. Typically certificates provisioning is done in a separate process outside of the
# runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for
# dynamic certificate management (enroll, revoke, re-enroll). The following section is only for
# Fabric-CA servers.
certificateAuthorities:
- ca.org1.mango.com
#
# List of orderers to send transaction and channel create/update requests to. For the time
# being only one orderer is needed. If more than one is defined, which one get used by the
# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers.
#
orderers:
orderer.mango.com:
url: localhost:7050
# these are standard properties defined by the gRPC library
# they will be passed in as-is to gRPC client constructor
grpcOptions:
ssl-target-name-override: orderer.mango.com
# These parameters should be set in coordination with the keepalive policy on the server,
# as incompatible settings can result in closing of connection.
# When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
# allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs
allow-insecure: false
tlsCACerts:
# Certificate location absolute path
path: ${GOPATH}/src/github.com/hyperledger/fabric-sdk-go-api/fixtures/crypto/ordererOrganizations/tlsca/tlsca-cert.pem
#
# List of peers to send various requests to, including endorsement, query
# and event listener registration.
#
peers:
peer0.org1.mango.com:
# this URL is used to send endorsement and query requests
url: localhost:7051
# eventUrl is only needed when using eventhub (default is delivery service)
eventUrl: localhost:7053
grpcOptions:
ssl-target-name-override: peer0.org1.mango.com
# These parameters should be set in coordination with the keepalive policy on the server,
# as incompatible settings can result in closing of connection.
# When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
# allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs
allow-insecure: false
tlsCACerts:
# Certificate location absolute path
path: ${GOPATH}/src/github.com/hyperledger/fabric-sdk-go-api/fixtures/crypto/peerOrganizations/tlsca/tlsca-cert.pem
peer1.org1.mango.com:
# this URL is used to send endorsement and query requests
url: localhost:8051
# eventUrl is only needed when using eventhub (default is delivery service)
eventUrl: localhost:8053
grpcOptions:
ssl-target-name-override: peer1.org1.mango.com
# These parameters should be set in coordination with the keepalive policy on the server,
# as incompatible settings can result in closing of connection.
# When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
# allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs
allow-insecure: false
tlsCACerts:
# Certificate location absolute path
path: ${GOPATH}/src/github.com/hyperledger/fabric-sdk-go-api/fixtures/crypto/peerOrganizations/tlsca/tlsca-cert.pem
entityMatchers:
peer:
- pattern: (\w*)peer0.org1.mango.com(\w*)
urlSubstitutionExp: localhost:7051
eventUrlSubstitutionExp: localhost:7053
sslTargetOverrideUrlSubstitutionExp: peer0.org1.mango.com
mappedHost: peer0.org1.mango.com
- pattern: (\w*)peer1.org1.mango.com(\w*)
urlSubstitutionExp: localhost:8051
eventUrlSubstitutionExp: localhost:8053
sslTargetOverrideUrlSubstitutionExp: peer1.org1.mango.com
mappedHost: peer1.org1.mango.com
orderer:
- pattern: (\w*)orderer.mango.com(\w*)
urlSubstitutionExp: localhost:7050
sslTargetOverrideUrlSubstitutionExp: orderer.mango.com
mappedHost: orderer.mango.com
当然,这部分内容,也是存在优化空间的,还没研究那么深入,后面有空再改。
参考文章
Fabric go sdk初始化所需证书解析的更多相关文章
- 使用Fabric Node SDK进行Invoke和Query
前面的文章都是在讲解Fabric网络的搭建和ChainCode的开发,那么在ChainCode开发完毕后,我们就需要使用Fabric SDK做应用程序的开发了.官方虽然提供了Node.JS,Java, ...
- Hyperledger Fabric Node SDK和应用开发
Hyperledger Fabric 提供了多种语言的SDK版本,其中提出比较早.比较稳定而全面的是Node.js版本的SDK. 前面提到的fabric示例(如first-network和e2e-cl ...
- 转:Eclipse ADT的Custom debug keystore所需证书规格
转:http://blog.k-res.net/archives/1229.html Eclipse ADT的Custom debug keystore所需证书规格 三月 8, 2013 | Po ...
- Hyperledger Fabric 实战(十): Fabric node SDK 样例 - 投票DAPP
Fabric node SDK 样例 - 投票DAPP 参考 fabric-samples 下的 fabcar 加以实现 目录结构 . ├── app │ ├── controllers │ │ └─ ...
- 搭建基于hyperledger fabric的联盟社区(八) --Fabric证书解析
一.证书目录解析 通过cryptogen生成所有证书文件后,以peerOrgannizations的第一个组织树org1为例,每个目录和对应文件的功能如下: ca: 存放组织的根证书和对应的私 ...
- Fabric证书解析
一.证书目录解析 通过cryptogen生成所有证书文件后,以peerOrgannizations的第一个组织树org1为例,每个目录和对应文件的功能如下: ca: 存放组织的根证书和对应的私 ...
- 搭建RESTful API来使用Fabric Node SDK 开篇
在Balance-Transfer中,有关于Node SDK比较完备的例子. SDK的官方文档在这里:https://fabric-sdk-node.github.io/ Balance-Transf ...
- Linux内核(11) - 子系统的初始化之内核选项解析
首先感谢国家.其次感谢上大的钟莉颖,让我知道了大学不仅有校花,还有校鸡,而且很多时候这两者其实没什么差别.最后感谢清华女刘静,让我深刻体会到了素质教育的重要性,让我感到有责任写写子系统的初始化. 各个 ...
- 基于Spring注解的上下文初始化过程源码解析(一)
最近工作之余有时间和精力,加上平时对源码比较感兴趣,就开始啃起了Spring源码.为加深印象写了这篇博客,如有错误,望各位大佬不吝指正. 我看的是Spring5的源码,从同性社区download下来后 ...
随机推荐
- PL/SQL Developer import and export database method and illustrate
PL/SQL Developer import and export database method and illustrate HOW WELL DO YOU KNOW THE APPLE U ...
- 利用Surfingkeys和tampermonkey效率操作网页
tampermonkey可以实现网页载入后自动进行某些操作,适合有规律的操作,实现完全自动化. 而Surfingkeys可以实现用各种按键实现各种功能,功能全部用JavaScript写,自定义性更强.
- *Amazon problem: 234. Palindrome Linked List (reverse the linked list with n time)
Given a singly linked list, determine if it is a palindrome. Example 1: Input: 1->2 Output: false ...
- CSU计算机研究生推免
考研复习 一开始,我是没有想到能够拿到研究生推免资格的,从今年3月份到整个暑假过完,一共6个月的时间,我一直在准备考研. 具体来说,我是在准备考研数学,整整6个月时间的数学复习,给我一种感觉,把大一大 ...
- mac下登录服务器
1.先通过帐号密码登录到服务器: ssh 用户名@服务器地址 https://jingyan.baidu.com/article/546ae1853132bf1148f28c42.html 2.登录后 ...
- Hibernate注解开发示例
-------------------------------------------------------------------customer------------------------- ...
- 学大伟业 Day 3 培训总结
今天讲的字符串: 不多说,直接看题 一.表达式求值 题目大意: 输入一行一个表达式,计算其答案 表达式包含非负整数.加减乘除.括号 两种做法 ·栈 ·表达式树 这里更推荐表达式树,因为栈是先压进去,逆 ...
- SQL Error: 1064, SQLState: 42000 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version
-- ::, WARN [org.hibernate.util.JDBCExceptionReporter:] - SQL Error: , SQLState: -- ::, ERROR [org.h ...
- POJ 2533 Longest Ordered Subsequence(裸LIS)
传送门: http://poj.org/problem?id=2533 Longest Ordered Subsequence Time Limit: 2000MS Memory Limit: 6 ...
- ImportError: No module named lmdb
why? 具体原因没有查清楚.安装caffe时,按照要求安装了包,caffe用的好好的,而且我也用打好包的lmdb跑了程序了.可我今天想看一下我的打包数据是不是漏掉数据了,直接开个python窗口,i ...