﻿<?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/category/12815.html</link><description>坚持就是胜利!</description><language>zh-cn</language><lastBuildDate>Thu, 14 Jun 2018 07:10:14 GMT</lastBuildDate><pubDate>Thu, 14 Jun 2018 07:10:14 GMT</pubDate><ttl>60</ttl><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之通过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/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>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>业务规则与自定义规则处理库</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><item><title>需求收集、分析小结</title><link>http://www.blogjava.net/fool/archive/2017/04/28/432489.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Fri, 28 Apr 2017 06:08:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2017/04/28/432489.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/432489.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2017/04/28/432489.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/432489.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/432489.html</trackback:ping><description><![CDATA[<div>绕不过去的坎---需求分析需求.分析师也好，系统分析师也好，架构师也好乃至PM都有一道绕不过去的坎，那就是需求分析。需求分析也绕不过需求收集。</div><div>需求收集的要点：</div><div>1，参与人。很重要。广义上是指各种干系人，如客户方，自己方的.具体的软件操作员可以是直接参与人，但也可能是代理参与人，比如声讯话务员，并不是系统的直接参与者，而是代理人。嗯，可以理解成别人请话员操作软件。甚至打电话进来的也是一个代理人，他帮别人办理业务。也有可能有数据权限要求。</div><div>2，用例。描述业务场景。通俗一点讲即参与人要办的事情。</div><div>3，边界。边界有两种意义。一种是技术实现层面，比如mvc模式中的V。另一种是业务层面的，指本用例需要达到的目标。</div><div>以上三点，UML中有业务用例图表示。但是仅此还不够。俺给加上第</div><div>4，业务规则。即完成业务的约束条件。这个单独抽出非常重要。有些业务规则最终可能会实现为一个系统用例。比如出国需要办理出入境业务。如果在电脑上实现预约，当然要考虑办理中心排班情况，比如除法定节假日以外星期一至星期六都工作。因为每年的法定节假日不是固定的，那我们需要做一个日期是否工作日的排班表出来。这条业务规则即变为一个系统用例，有人机交互界面。在预约出入境时就成了预约的前置条件。还有其它的业务规则比如报表的计算公式等。可见业务规则是如此重要。可以抽出来弄成单独的文档。</div><div>系统分析员或需求分析师需要根据业务需求做出系统用例。系统用例在人机交互应用中是指人做什么，然后电脑做什么的描述。</div><div>pm会跟用户聊到需求。架构师需要了然关键需求及可能存在风险的需求，尽早考虑解决方案。需求分析师也好，架构师也好，基本上应该擅长业务领域模型建模。业务领域模型可能映射成数据架构，即数据的存储方式，比如数据库和文件等。如何正确的建立领域模型？</div><div>1，不要放过业务场景中的名词。比如合同，销售单。</div><div>2，不要放过业务场景中的动名词，比如取款。描述可能一是条取款流水记录，如某人在某个时间某个地点用某种方式取了多少款。</div><div>3， 应当收集业务中用到的一些资料如销售单，出货单，甚至是公司章程如请假制度管理等。</div><div>参与人和业务规则往往容易被忽视掉，这会带来需求变更。那么问题来了，这些东西如何映射成程序中的对象？如下图中的商场的小票联.应该怎么建数据库表呢？有没有方法呢？当然有，那就是找出发票中有哪些对象。根据对象建数据表。</div><div>分析过程：</div><div>1，问问自己，小票是对象吗? 当然是.因为它有自己的属性。比如开票人，销售的商品。在商场pos系统里这个对象其实就是销售单对象。</div><div>2,销售时间是一个对象吗？不是。因为它只是一个时间字符串，本身没有其它属性。</div><div>3,可乐汽水及商品编号当然是一个对象。这容易理解。</div><div>4，金额3.1元也是一个基本属性，它属于什么对象？销售单本身吗？显然不是。它跟可乐汽水这个商品合起来才是一个对象，描述的是销售单什么价格销售了什么产品,应当单独建立一个表。如果有多个商品？那很容易扩充，销售单有一个LIST&lt;销售明细&gt; 的属性。</div><div>对象本身具有良好的继承性，换句话讲按对象模型建立的数据库表基本上都是很容易扩展的，在增加新功能的时候不至于大动干戈。架构师则根据此设计数据架构视图，比如销售单查询响应要求，大数据量的水平，垂直分库，数据库读写分离等。<br /><br /><div><img src="http://www.blogjava.net/images/blogjava_net/fool/2.jpg" border="0" alt="" /></div></div><img src ="http://www.blogjava.net/fool/aggbug/432489.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:08 <a href="http://www.blogjava.net/fool/archive/2017/04/28/432489.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>acegi之Active Directory验证</title><link>http://www.blogjava.net/fool/archive/2009/10/30/300395.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Fri, 30 Oct 2009 09:48:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2009/10/30/300395.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/300395.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2009/10/30/300395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/300395.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/300395.html</trackback:ping><description><![CDATA[<span style="font-size: 12pt">客户要求提供Active Directory登录验证.原因是他们公司是在美国的上市公司,要求上市公司的软件必须提供统一登录认证.他们想到的解决方案就是Active Directory.呵呵.而我们开发的系统使用的是acegi登录验证.嗯,这个,首先想到的就是ldap,没的想,网上搜吧,资料还不算少.那就配吧,配好了需要测试吧,那就找服务器咧.这公司的域服务器不让用,那就openldap吧.下好了又一通查资料,openldap总得配是吧.总算给配好了,不容易呀.就拿到客户环境去试吧,嘿嘿,客户说了不可能给我们管理员帐号密码,只有用户登录帐号跟密码,傻了.acegi的ldap验证就要这个啊.<br />
回来继续搞咧,咱也没办法不是?<br />
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&gt;</p>
<p>&lt;beans&gt;</p>
<p>&nbsp;&lt;bean id="filterChainProxy"<br />
&nbsp;&nbsp;class="org.acegisecurity.util.FilterChainProxy"&gt;<br />
&nbsp;&nbsp;&lt;property name="filterInvocationDefinitionSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON<br />
&nbsp;&nbsp;&nbsp;&nbsp;PATTERN_TYPE_APACHE_ANT<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor<br />
&nbsp;&nbsp;&nbsp;&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="authenticationManager"<br />
&nbsp;&nbsp;class="org.acegisecurity.providers.ProviderManager"&gt;<br />
&nbsp;&nbsp;&lt;property name="providers"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- 自己写一个认证提供者类 我加的--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="activeDirectoryProvider" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref local="daoAuthenticationProvider" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref local="anonymousAuthenticationProvider" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref local="rememberMeAuthenticationProvider" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;<br />
&nbsp;&lt;/bean&gt;<br />
&nbsp;<br />
&nbsp;&lt;!-- 认证提供者类的配置 我加的--&gt;<br />
&nbsp;&lt;bean id="activeDirectoryProvider"<br />
&nbsp;&nbsp;class="net.omw.utility.AcegiTestProvider"&gt;<br />
&nbsp;&nbsp;&lt;property name="url" value="ldap://172.108.4.2"&gt;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="port" value="389"&gt;&nbsp;&lt;/property&gt;<br />
&lt;!--domain取值域服务器的配置--&gt;<br />
&nbsp;&nbsp;&lt;property name="domain" value="SUNTECH"&gt;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp;&nbsp;&nbsp; &lt;property name="sessionController" ref="concurrentSessionController"&gt;&lt;/property&gt; --&gt;<br />
&nbsp;&lt;/bean&gt;<br />
<br />
<br />
&nbsp;&lt;bean id="jdbcDaoImpl"<br />
&nbsp;&nbsp;class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl"&gt;<br />
&nbsp;&nbsp;&lt;property name="dataSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref bean="coreDataSource" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="usersByUsernameQuery"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;select C_OPER_ID,C_PASSWORD,1 from Operator where<br />
&nbsp;&nbsp;&nbsp;&nbsp;C_OPER_ID = ? and C_STATUS='Y'<br />
&nbsp;&nbsp;&nbsp;&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="authoritiesByUsernameQuery"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;select C_OPER_ID,C_PASSWORD,1 from Operator where<br />
&nbsp;&nbsp;&nbsp;&nbsp;C_OPER_ID = ? and C_STATUS='Y'<br />
&nbsp;&nbsp;&nbsp;&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="passwordEncoder"<br />
&nbsp;&nbsp;class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"&gt;<br />
&nbsp;&nbsp;&lt;property name="encodeHashAsBase64" value="false"&gt;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="daoAuthenticationProvider"<br />
&nbsp;&nbsp;class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;<br />
&nbsp;&nbsp;&lt;property name="userDetailsService"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="jdbcDaoImpl" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;!-- &lt;property name="userCache"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="userCache" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;--&gt;<br />
&nbsp;&nbsp;&lt;property name="passwordEncoder"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="passwordEncoder" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="cacheManager"<br />
&nbsp;&nbsp;class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" /&gt;</p>
<p>&nbsp;&lt;bean id="userCacheBackend"<br />
&nbsp;&nbsp;class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;<br />
&nbsp;&nbsp;&lt;property name="cacheManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="cacheManager" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="cacheName"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;userCache&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="userCache"<br />
&nbsp;&nbsp;class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"&gt;<br />
&nbsp;&nbsp;&lt;property name="cache"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="userCacheBackend" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="loggerListener"<br />
&nbsp;&nbsp;class="org.acegisecurity.event.authentication.LoggerListener" /&gt;</p>
<p>&nbsp;&lt;bean id="anonymousProcessingFilter"<br />
&nbsp;&nbsp;class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter"&gt;<br />
&nbsp;&nbsp;&lt;property name="key"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;foobar&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="userAttribute"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;anonymousUser,ROLE_ANONYMOUS&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="anonymousAuthenticationProvider"<br />
&nbsp;&nbsp;class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider"&gt;<br />
&nbsp;&nbsp;&lt;property name="key"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;foobar&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="httpSessionContextIntegrationFilter"<br />
&nbsp;&nbsp;class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="rememberMeProcessingFilter"<br />
&nbsp;&nbsp;class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter"&gt;<br />
&nbsp;&nbsp;&lt;property name="authenticationManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="authenticationManager" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="rememberMeServices"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="rememberMeServices" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="rememberMeServices"<br />
&nbsp;&nbsp;class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices"&gt;<br />
&nbsp;&nbsp;&lt;property name="userDetailsService"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="jdbcDaoImpl" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="key"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;springRocks&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="rememberMeAuthenticationProvider"<br />
&nbsp;&nbsp;class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider"&gt;<br />
&nbsp;&nbsp;&lt;property name="key"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;springRocks&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="logoutFilter"<br />
&nbsp;&nbsp;class="org.acegisecurity.ui.logout.LogoutFilter"&gt;<br />
&nbsp;&nbsp;&lt;constructor-arg value="/login/loginPage.jsp" /&gt;<br />
&nbsp;&nbsp;&lt;constructor-arg&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="rememberMeServices" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/constructor-arg&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="securityContextHolderAwareRequestFilter"<br />
&nbsp;&nbsp;class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" /&gt;</p>
<p>&nbsp;&lt;bean id="exceptionTranslationFilter"<br />
&nbsp;&nbsp;class="org.acegisecurity.ui.ExceptionTranslationFilter"&gt;<br />
&nbsp;&nbsp;&lt;property name="authenticationEntryPoint"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="authenticationProcessingFilterEntryPoint" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="accessDeniedHandler"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;bean<br />
&nbsp;&nbsp;&nbsp;&nbsp;class="org.acegisecurity.ui.AccessDeniedHandlerImpl"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="errorPage"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="/common/AccessDenied.jsp" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/bean&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="authenticationProcessingFilter"<br />
&nbsp;&nbsp;class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"&gt;<br />
&nbsp;&nbsp;&lt;property name="authenticationManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref bean="authenticationManager" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="authenticationFailureUrl"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;/login/Login.action?login_msg=1&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="defaultTargetUrl"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;/login/Login.action?login_msg=0&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="filterProcessesUrl"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;/j_acegi_security_check&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="rememberMeServices"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="rememberMeServices" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="authenticationProcessingFilterEntryPoint"<br />
&nbsp;&nbsp;class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"&gt;<br />
&nbsp;&nbsp;&lt;property name="loginFormUrl"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;/login/loginPage.jsp&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="forceHttps"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;false&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="serverSideRedirect" value="false"&gt;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="httpRequestAccessDecisionManager"<br />
&nbsp;&nbsp;class="org.acegisecurity.vote.AffirmativeBased"&gt;<br />
&nbsp;&nbsp;&lt;property name="allowIfAllAbstainDecisions"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;false&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="decisionVoters"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="roleVoter" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter" /&gt;</p>
<p>&nbsp;&lt;bean id="filterInvocationInterceptor"<br />
&nbsp;&nbsp;class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;<br />
&nbsp;&nbsp;&lt;property name="validateConfigAttributes" value="true" /&gt;<br />
&nbsp;&nbsp;&lt;property name="authenticationManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref bean="authenticationManager" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="accessDecisionManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="httpRequestAccessDecisionManager" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="objectDefinitionSource"<br />
&nbsp;&nbsp;&nbsp;ref="rdbmsFilterInvocationDefinitionSource" /&gt;</p>
<p>&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="rdbmsFilterInvocationDefinitionSource"<br />
&nbsp;&nbsp;class="net.omw.utility.acegi.interceptor.RdbmsFilterInvocationDefinitionSource"&gt;<br />
&nbsp;&nbsp;&lt;property name="dataSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref bean="coreDataSource" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="webresdbCache" ref="webresCacheBackend" /&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;bean id="webresCacheBackend"<br />
&nbsp;&nbsp;class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;<br />
&nbsp;&nbsp;&lt;property name="cacheManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="cacheManager" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="cacheName"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;webresdbCache&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;&lt;!--&nbsp; <br />
&nbsp;&nbsp;&lt;bean id="switchUserProcessingFilter" class="org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter"&gt;<br />
&nbsp;&nbsp;&lt;property name="userDetailsService" ref="jdbcDaoImpl" /&gt;<br />
&nbsp;&nbsp;&lt;property name="switchUserUrl"&gt;&lt;value&gt;/j_acegi_switch_user&lt;/value&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="exitUserUrl"&gt;&lt;value&gt;/j_acegi_exit_user&lt;/value&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="targetUrl"&gt;&lt;value&gt;/secure/index.htm&lt;/value&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;/bean&gt;&nbsp;&nbsp;&nbsp; <br />
&nbsp;--&gt;</p>
<p>&nbsp;&lt;bean id="authenticationLoggerListener"<br />
&nbsp;&nbsp;class="org.acegisecurity.event.authentication.LoggerListener" /&gt;</p>
<p>&nbsp;&lt;bean id="authorizationLoggerListener"<br />
&nbsp;&nbsp;class="org.acegisecurity.event.authorization.LoggerListener" /&gt;<br />
&lt;/beans&gt;<br />
<br />
AcegiTestProvider类从AbstractUserDetailsAuthenticationProvider继承,有两个方法必须实现<br />
additionalAuthenticationChecks()和retrieveUser()方法.retrieveUser返回UserDetails,UserDetails的实现可以包装更多的信息.但在本例中几乎没什么太大的作用,仅仅是为了返回而重新定义了一个类<br />
真正的验证逻辑发生在additionalAuthenticationChecks方法里抛出异常就算用户登录失败<br />
<br />
</p>
<p>package net.omw.utility;</p>
<p>import java.util.Properties;</p>
<p>import javax.naming.Context;<br />
import javax.naming.NamingException;<br />
import javax.naming.ldap.InitialLdapContext;</p>
<p>import org.acegisecurity.AuthenticationException;<br />
import org.acegisecurity.GrantedAuthority;<br />
import org.acegisecurity.GrantedAuthorityImpl;<br />
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;<br />
import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider;<br />
import org.acegisecurity.userdetails.UserDetails;<br />
import org.acegisecurity.userdetails.UsernameNotFoundException;</p>
<p>public class AcegiTestProvider extends<br />
&nbsp;&nbsp;AbstractUserDetailsAuthenticationProvider {<br />
&nbsp;&nbsp; private String url;<br />
&nbsp;&nbsp; private String port;<br />
&nbsp;&nbsp; private String domain;<br />
&nbsp;<br />
&nbsp;/*<br />
&nbsp; * 验证逻辑<br />
&nbsp; * @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#additionalAuthenticationChecks(org.acegisecurity.userdetails.UserDetails, org.acegisecurity.providers.UsernamePasswordAuthenticationToken)<br />
&nbsp; * <br />
&nbsp; */<br />
&nbsp;@Override<br />
&nbsp;protected void additionalAuthenticationChecks(UserDetails arg0,<br />
&nbsp;&nbsp;&nbsp;UsernamePasswordAuthenticationToken arg1)<br />
&nbsp;&nbsp;&nbsp;throws AuthenticationException {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</p>
<p>&nbsp;&nbsp;String URL = url+":"+port;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String username=domain+"\\"+arg0.getUsername();<br />
&nbsp;&nbsp;String password = arg0.getPassword();</p>
<p><br />
&nbsp;&nbsp;Properties env = new Properties();&nbsp;&nbsp;<br />
&nbsp;&nbsp;env.put(Context.INITIAL_CONTEXT_FACTORY, <br />
&nbsp;&nbsp;"com.sun.jndi.ldap.LdapCtxFactory"); <br />
&nbsp;&nbsp;env.put(Context.PROVIDER_URL,"ldap://172.18.0.42:389");<br />
&nbsp;&nbsp;env.put(Context.SECURITY_AUTHENTICATION,"simple");<br />
&nbsp;&nbsp;env.put(Context.SECURITY_PRINCIPAL, <br />
&nbsp;&nbsp;username); <br />
&nbsp;&nbsp;env.put(Context.SECURITY_CREDENTIALS,password); <br />
&nbsp;&nbsp;env.put("com.sun.jndi.ldap.connect.pool","true"); <br />
&nbsp;&nbsp;env.put("java.naming.referral","follow");&nbsp;<br />
&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;&nbsp; new InitialLdapContext(env,null); <br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;catch(NamingException e){<br />
&nbsp;&nbsp;&nbsp;// Authentication failed<br />
&nbsp;&nbsp;&nbsp;throw new UsernameNotFoundException(e.toString());<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}</p>
<p><br />
&nbsp;}</p>
<p>&nbsp;@Override<br />
&nbsp;protected UserDetails retrieveUser(String arg0,<br />
&nbsp;&nbsp;&nbsp;UsernamePasswordAuthenticationToken arg1)<br />
&nbsp;&nbsp;&nbsp;throws AuthenticationException {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;GrantedAuthority[] authorities = new GrantedAuthority[1];<br />
&nbsp;&nbsp;authorities[0] = new GrantedAuthorityImpl("ROLE_SUPERVISOR");<br />
&nbsp;&nbsp;String password = (String) arg1.getCredentials();&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*String username = "";<br />
&nbsp;&nbsp;Object obj = arg1.getPrincipal();<br />
&nbsp;&nbsp;if (obj instanceof UserDetails) {<br />
&nbsp;&nbsp;&nbsp;username = ((UserDetails) obj).getUsername();<br />
&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;username = obj.toString();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;UserDetails userDetails = new UserDetailsImpl(authorities, password,<br />
&nbsp;&nbsp;&nbsp;&nbsp;arg1.getName(), true, true, true, true);<br />
&nbsp;&nbsp;//if(true)<br />
&nbsp;&nbsp;&nbsp; // &nbsp;throw new AuthenticationCredentialsNotFoundException("t");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;return userDetails;<br />
&nbsp;}</p>
<p>&nbsp;public String getUrl() {<br />
&nbsp;&nbsp;return url;<br />
&nbsp;}</p>
<p>&nbsp;public void setUrl(String url) {<br />
&nbsp;&nbsp;this.url = url;<br />
&nbsp;}</p>
<p>&nbsp;public String getPort() {<br />
&nbsp;&nbsp;return port;<br />
&nbsp;}</p>
<p>&nbsp;public void setPort(String port) {<br />
&nbsp;&nbsp;this.port = port;<br />
&nbsp;}</p>
<p>&nbsp;public String getDomain() {<br />
&nbsp;&nbsp;return domain;<br />
&nbsp;}</p>
<p>&nbsp;public void setDomain(String domain) {<br />
&nbsp;&nbsp;this.domain = domain;<br />
&nbsp;}</p>
<p>&nbsp;<br />
}<br />
<br />
</p>
<p>package net.omw.utility;</p>
<p>import org.acegisecurity.GrantedAuthority;<br />
import org.acegisecurity.userdetails.UserDetails;</p>
<p>public class UserDetailsImpl implements UserDetails {<br />
&nbsp;GrantedAuthority[] authorities;</p>
<p>&nbsp;String password;</p>
<p>&nbsp;String username;<br />
&nbsp;boolean isAccountNonExpired;</p>
<p>&nbsp;boolean isAccountNonLocked;</p>
<p>&nbsp;boolean isCredentialsNonExpired;</p>
<p>&nbsp;boolean isEnabled;</p>
<p>&nbsp;UserDetailsImpl(GrantedAuthority[] authorities, String password,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String username, boolean isAccountNonExpired,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean isCredentialsNonExpired, boolean isEnabled,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean isAccountNonLocked) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.authorities = authorities;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.isAccountNonExpired = isAccountNonExpired;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.isAccountNonLocked = isAccountNonLocked;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.isEnabled = isEnabled;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.password = password;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.username = username;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.isCredentialsNonExpired = isCredentialsNonExpired;</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;<br />
&nbsp;@Override<br />
&nbsp;public GrantedAuthority[] getAuthorities() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;return authorities;<br />
&nbsp;}</p>
<p>&nbsp;@Override<br />
&nbsp;public String getPassword() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;return password;<br />
&nbsp;}</p>
<p>&nbsp;@Override<br />
&nbsp;public String getUsername() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;return username;<br />
&nbsp;}</p>
<p>&nbsp;@Override<br />
&nbsp;public boolean isAccountNonExpired() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;return isAccountNonExpired;<br />
&nbsp;}</p>
<p>&nbsp;@Override<br />
&nbsp;public boolean isAccountNonLocked() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;return isAccountNonLocked;<br />
&nbsp;}</p>
<p>&nbsp;@Override<br />
&nbsp;public boolean isCredentialsNonExpired() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;return isCredentialsNonExpired;<br />
&nbsp;}</p>
<p>&nbsp;@Override<br />
&nbsp;public boolean isEnabled() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;return isEnabled;<br />
&nbsp;}</p>
<p>}<br />
</p>
<p><br />
</p>
<p><br />
<br />
<br />
&nbsp;</p>
</span>
<img src ="http://www.blogjava.net/fool/aggbug/300395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2009-10-30 17:48 <a href="http://www.blogjava.net/fool/archive/2009/10/30/300395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle 嵌套游标以及java,oracle的时间处理</title><link>http://www.blogjava.net/fool/archive/2009/03/09/258559.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 09 Mar 2009 02:50:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2009/03/09/258559.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/258559.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2009/03/09/258559.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/258559.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/258559.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
create or replace procedure test is<br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ids VOD_CMS_OPERATION_REGION.id%type; //变量ids与VOD_CMS_OPERATION_REGION表的id字段的类型一致<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor cur_region is&nbsp;&nbsp;&nbsp; select id from VOD_CMS_OPERATION_REGION; //定义游标<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; phoneId VOD_CMS_OPERATION_REGION2PHONE.id%type;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor cur_phone is select id from&nbsp;&nbsp; VOD_CMS_OPERATION_REGION2PHONE&nbsp; //第二个游标<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where VOD_CMS_OPERATION_REGION2PHONE.REGION_ID=ids ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; open cur_region;&nbsp; //打开游标<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loop&nbsp;&nbsp;&nbsp; //循环<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fetch cur_region&nbsp; into ids;&nbsp;&nbsp;&nbsp; //逐行处理游标把值放入变量 ids<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit when cur_region%notfound; //没找到游标退出循环<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; open cur_phone; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loop&nbsp;&nbsp;&nbsp;&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 />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fetch cur_phone into phoneId;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit when cur_phone%notfound;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; update VOD_CMS_OPERATION_REGION2PHONE set creater=1 where VOD_CMS_OPERATION_REGION2PHONE.id=phoneId;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end loop;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close cur_phone;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end loop;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close cur_region; 关闭游标<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commit;<br />
end test;<br />
<br />
<br />
程序处理oracle时间<br />
<br />
&nbsp;&nbsp;Calendar ca = Calendar.getInstance(Locale.CHINA);<br />
&nbsp;&nbsp;ca.setTime(new Date());<br />
&nbsp;&nbsp;ca.set(Calendar.HOUR_OF_DAY, 0);<br />
&nbsp;&nbsp;ca.set(Calendar.MINUTE,0);<br />
&nbsp;&nbsp;ca.set(Calendar.SECOND, 0);<br />
&nbsp;&nbsp;SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");<br />
&nbsp;&nbsp;StringBuffer buffer = new StringBuffer();<br />
&nbsp;&nbsp;buffer.append("select cmsAssetObject.regionIds from CmsAssetObject cmsAssetObject where cmsAssetObject.validdate &gt;= " );<br />
&nbsp;&nbsp;buffer.append("to_date('"+sdf.format(ca.getTime())+ "','yyyy-MM-dd hh24:mi:ss') ");<br />
&nbsp;&nbsp;ca.set(Calendar.HOUR_OF_DAY, 23);<br />
&nbsp;&nbsp;ca.set(Calendar.MINUTE,59);<br />
&nbsp;&nbsp;ca.set(Calendar.SECOND,59);<br />
&nbsp;&nbsp;buffer.append(" and cmsAssetObject.expiredate &lt;= ");<br />
&nbsp;&nbsp;buffer.append("to_date('"+sdf.format(ca.getTime())+ "','yyyy-MM-dd hh24:mi:ss') ");<br />
&nbsp;&nbsp;buffer.append(" and cmsAssetObject.isWeather = 1");<br />
<img src ="http://www.blogjava.net/fool/aggbug/258559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2009-03-09 10:50 <a href="http://www.blogjava.net/fool/archive/2009/03/09/258559.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>访问者模式实战:构建通用的数据库插入操作</title><link>http://www.blogjava.net/fool/archive/2006/08/14/63474.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Mon, 14 Aug 2006 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2006/08/14/63474.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/63474.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2006/08/14/63474.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/63474.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/63474.html</trackback:ping><description><![CDATA[
		<p>
				<br />在做一些简单的JDBC的API应用时，就老想只用一个方法向数据库不同的表做插入操作，省得<br />用一大堆的insert语句。访问者模式可以实现对未知的类进行操作，于是就用了这个简化了的模<br />式的实现方案。请高手指正。 在使用访问者模式之前先叙述一点概念性的东西。<br />静态类型的概念：变量被申明时的类型。实际类型：变量的实际类型。<br />比如 Object object=new String(); object静态类型是Object,实际类型是String.<br />观察者模式是一个比较难理解的模式，在理解观察者模式之前当然应该先理解双重分派的概念。<br />java语言支持静态的多分派跟动态的单分派。java通重载支持静态的多分派。书上的例子：<br />public class Mozi {<br />    <br />    public void ride(Horse h){<br />        System.out.println("ridding a horse");<br />    }<br />    public void ride(WhiteHorse w){<br />        System.out.println("ridding a white horse");<br />    }<br />    public void ride(BlackHorse b){<br />        System.out.println("rdding a black horse");<br />    }</p>
		<p>    public static void main(String[] args){<br />      Mozi mozi=new Mozi();<br />      Horse w=new WhiteHorse();<br />      Horse b=new BlackHorse();<br />      mozi.ride(w);<br />      mozi.ride(b);<br />    }<br />}  <br />程序打印输出:<br />ridding a horse<br />ridding a horse<br />原因就是对两次ride方法的调用传入的参量不同，但是它们的静态类型是一样的，都是 Horse;<br />这个过程在编译时期就完成了。<br />java通过方法置换支持动态分派。比如 String s1="ab"; Object o=s1+"c"; String s="abc";<br />o.equals(s) 打印true  o.equals()方法执行的是String类的equals()方法.java调用对象的<br />真实类型的方法，这就是动态分派。<br />双重分派:<br />public abstract class Vistor{</p>
		<p>protected void processStrig(Object e){<br /> if(e instanceof String){<br />     String tmp=(String) e;<br />     String need="'"+e+"'";<br />     System.out.println(nedd);<br />   }else if(e instanceof Integer){<br />       String need=e.toString();<br />       System.out.println(need);<br />    }else if(e instanceof Date){<br />             Date tmp=(Date) e;<br />             String need="'"+tmp.toString()+"'"; <br />        }<br />      ....<br />    }</p>
		<p>}</p>
		<p>public class ConcreteVisitor extends Visitor{</p>
		<p>protected void processString(Object e){<br />     super.processString(e);<br />   }   <br />}<br />方法的调用Visitor v=new ConcreteVisitor(); v.processString(new String("tt"));<br />v.processString()方法在调用的时候会检察v的真实类型，调用真实类型的方法，这个时候就<br />发生了一动态的单分派过程.当子类调用超类的方法的时候明显的根据instanceof判断的真实类<br />型去执行不同的方法，又发生了一次动态分派的过程.这个就是双重分派的实现。这种方法实现的<br />程序比较冗长和容易出错.<br />“返传球”方案:<br />public abstract class Vistor{</p>
		<p>   public abstract String processStrig(Object e);</p>
		<p>}</p>
		<p>public class ConcreteVisitor extends Visitor{</p>
		<p>  public String processString(WrapperString e){<br />    String tmp= t.toString();<br />    System.out.println(tmp);<br />   }   </p>
		<p>  public String processInteger(WrapperInteger e){<br />    String tmp=e.toString();<br />    System.out.println(tmp);</p>
		<p>   }</p>
		<p>}</p>
		<p>public class abstract Wrapper{<br />  public abstract String processString(Vistor v);<br />}</p>
		<p>public class WrapperString extends Wrapper{</p>
		<p>  public String processString(Vistor v){<br />    v.processString(this);<br />   }<br />  public String toString(){<br />   ...<br />   }<br />}</p>
		<p>public class WrapperInteger extends Wrapper{<br />    public String processInteger(Visitor v){<br />     v.processString(this);<br />    }<br />    public String toString(){<br />     ...<br />    }<br /> }<br />方法的调用：<br />Visitor v = new ConcreteVisitor(); <br />Wrapper wrapper= new WrapperString();<br />wrapper.processString(v);<br />当wrapper.processString()方法执行的时候会检察wrapper的真实类型，这个就产生了一次<br />动态单分派，processString()里面的语句v.processString（）在执行的时候也会检察v的真<br />实类型，动态双重分派就发生了。<br />访问者模式的核心就是“返传球“方案的双重分派。其示意性类图:(注:虚线箭头划错了)<br /><br /><br /><br /><img height="292" alt="visitor.jpg" src="http://www.blogjava.net/images/blogjava_net/fool/visitor.jpg" width="447" border="0" /><br /><br />在一个方法内实现向不同的表插入不同数据的具体实现方案(简化了的）：因为整个方案里只需<br />要一个访问者对象，因此使用简化了的访问者模式。因为java基本类型及对应的类是不变模式的<br />实现：因此包装一下这些基本类型和类并实现访问者模式需要的方法。<br />public abstract class Wrapper {<br />    public Wrapper() {<br />    }<br />    public abstract String action(Visitor visitor);</p>
		<p>}</p>
		<p>包装Date类:<br />import java.util.Date;<br />public class WrapperDate extends Wrapper {<br />    private Date date;<br />    public WrapperDate(Date date) {<br />        this.date=date;<br />    }<br />    public String action(Visitor visitor){<br />         return( visitor.visit(this));<br />    }</p>
		<p>    public String toString(){<br />        if (date==null){<br />            return "null";<br />        }<br />        return "'"+date.toString()+"'";<br />    }</p>
		<p>}</p>
		<p>
				<br />包装Integer类:<br />public class WrapperInteger extends Wrapper {<br />    private Integer value;</p>
		<p>    public WrapperInteger(Integer value) {<br />        this.value=value;</p>
		<p>    }<br />    public WrapperInteger(int value){</p>
		<p>        this.value=new Integer(value);<br />    }<br />    public WrapperInteger(String value){</p>
		<p>      this.value=new Integer(value);<br />    }</p>
		<p>    public String action(Visitor visitor){<br />       return( visitor.visit(this));<br />    }<br />    public String toString(){<br />        if(value==null){<br />            return "null";<br />        }<br />        return value.toString();<br />    }<br />}</p>
		<p>包装String类:<br />public class WrapperString extends Wrapper {<br />    private String wrapper;<br />    public WrapperString( String wrapper) {</p>
		<p>        this.wrapper = wrapper;<br />    }</p>
		<p>    public WrapperString( char[] wrap) {<br />        wrapper = new String(wrap);<br />    }</p>
		<p>    public String action(Visitor visitor) {<br />        return (visitor.vistit(this));<br />    }</p>
		<p>    public String toString() {<br />        if(wrapper==null){<br />            return "null";<br />        }<br />        return "'" + wrapper + "'";<br />    }</p>
		<p>
				<br />}</p>
		<p>具体访问者的实现：<br />public class Visitor {<br />    public Visitor() {<br />    }</p>
		<p>
				<br />    public String vistit(WrapperString wrap){<br />       return wrap.toString();<br />    }<br />    public String visit(WrapperInteger value){<br />        return value.toString();<br />    }<br />    public String visit(WrapperDate date){<br />        return date.toString();<br />    }<br />}</p>
		<p>具体应用类的实现:</p>
		<p>import java.util.*;</p>
		<p>public class Test {</p>
		<p>
				<br />    private Visitor visitor = new Visitor();</p>
		<p>    public Test() {<br />    }</p>
		<p>    public Visitor getVisitor() {<br />        return visitor;<br />    }</p>
		<p>  </p>
		<p>
				<br />    public int insertData(String tablename, List columNameCollection,<br />                          List values) {</p>
		<p>        StringBuffer query = new StringBuffer("insert into " + tablename + " (");</p>
		<p>        int count = 0;</p>
		<p>        for (Iterator it = columNameCollection.iterator(); it.hasNext(); ) {<br />            String columName = (String) it.next();<br />            query.append(columName);<br />            query.append(",");<br />        }<br />        query.deleteCharAt(query.length() - 1);<br />        query.append(") values(");<br />        for (Iterator it = values.iterator(); it.hasNext(); ) {<br />            Wrapper wrapper = (Wrapper) it.next();<br />            String tmp = wrapper.action(getVisitor());<br />            query.append(tmp);<br />            query.append(",");<br />        }<br />        query.deleteCharAt(query.length() - 1);<br />        query.append(")");</p>
		<p>        System.out.println(query.toString());<br />        return count;<br />    }</p>
		<p>
				<br />    public static void main(String[] args) {<br />        Test test = new Test();<br />        String tableName = "cutomer";<br />        List columNameCollection = new ArrayList();<br />        String columName = "name";<br />        String columAge = "age";<br />        String columFunctionTime="fuctiontime";<br />        columNameCollection.add(columName);<br />        columNameCollection.add(columAge);<br />        columNameCollection.add(columFunctionTime);<br />        List values = new ArrayList();<br />        String name=null;<br />        Wrapper wrapper1 = new WrapperString(name);<br />        Wrapper wrapper2 = new WrapperInteger(1);<br />        Wrapper wrapper3= new WrapperDate(new java.util.Date());<br />        values.add(wrapper1);<br />        values.add(wrapper2);<br />        values.add(wrapper3);<br />        test.insertData(tableName,columNameCollection,values);<br />        </p>
		<p>
				<br />    }<br />}</p>
		<p>程序打印结果：<br /><br />insert into cutomer (name,age,fuctiontime) values(null,1,'Sat Aug 12 13:46:58 CST 2006')<br /><br />这个输出是满足MSSQL执行插入的语法要求的.虽然这样就实现了想要的结果,<br />但是insertData(String tablename, List columNameCollection, List values) 方法在每次调<br />用的时候需要输入表名跟该表的列的集合,还是很麻烦,不尽人意,而且不同的数<br />据库的表名是不一样的,因此最好用配置文件来解决这一个问题.<br /></p>
		<p>欢迎加入QQ群:30406099 </p>
		<p> </p>
		<p>
				<br /> </p>
<img src ="http://www.blogjava.net/fool/aggbug/63474.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2006-08-14 14:39 <a href="http://www.blogjava.net/fool/archive/2006/08/14/63474.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在java中改变菜单的外观</title><link>http://www.blogjava.net/fool/archive/2006/07/06/56921.html</link><dc:creator>傻  瓜</dc:creator><author>傻  瓜</author><pubDate>Thu, 06 Jul 2006 03:24:00 GMT</pubDate><guid>http://www.blogjava.net/fool/archive/2006/07/06/56921.html</guid><wfw:comment>http://www.blogjava.net/fool/comments/56921.html</wfw:comment><comments>http://www.blogjava.net/fool/archive/2006/07/06/56921.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/fool/comments/commentRss/56921.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fool/services/trackbacks/56921.html</trackback:ping><description><![CDATA[
		<p>在java中改变菜单的外观,想必只有傻瓜才会这么干吧,哈哈哈~~~你不许笑,只许我笑.因为随便笑人家是傻瓜不是一个礼貌的孩子:) 好了,说实现思路吧 .javax.swing包中的组件都是继承JComponent组件 JComponent组件中有一个方法setBorder(Border border) 用来设置组件的边框 Boder是一个接口,在avax.swing.border包中<br />那么改变菜单的外观就可以首先从这个来着手了.因此我们需要一个实现这个接口的类.好了,来看看这个接口的方法吧 :<br />void paintBorder(Component c,<br />                 Graphics g,<br />                 int x,<br />                 int y,<br />                 int width,<br />                 int height)按指定的位置和尺寸绘制指定组件的边框。 </p>
		<p>参数：<br />c - 要为其绘制边框的组件<br />g - 绘制的图形<br />x - 所绘制边框的 x 坐标位置<br />y - 所绘制边框的 y 坐标位置<br />width - 所绘制边框的宽度<br />height - 所绘制边框的高度<br /></p>
		<p>//附注:边框就是在这个方法中给画出来的<br />--------------------------------------------------------------------------------</p>
		<p>
				<br />Insets getBorderInsets(Component c)返回该边框的 insets。 <br /></p>
		<p>//附注一下:该类是容器边界的表示形式。<font style="BACKGROUND-COLOR: #ffffff" color="#ff1493">它指定容器必须在其各个边缘留出的空间</font>。这个空间可以是边<br />//界、空白空间或标题。 <br />参数：<br />c - 要应用此边框 insets 值的组件</p>
		<p>--------------------------------------------------------------------------------</p>
		<p>isBorderOpaque<br />boolean isBorderOpaque()返回此边框是否透明。如果边框为不透明，则在绘制它时将用自身的背景来填充。 <br /></p>
		<hr />
		<br />首先来看看效果图: 请注意右上角是椭圆的噢,这个就暗示了我们可以把菜单弄成任意形状,只要你愿意!<br />按照这种思路,同样的,你也可以改变右键弹出菜单的外观<br /><br /><p align="center"><img height="145" alt="menu.gif" src="http://www.blogjava.net/images/blogjava_net/fool/menu.gif" width="125" border="0" /></p><p align="left"></p><hr /><p align="left">接口的实现类  至于画图用到的方法,详见JAVA API.<br />import java.awt.*;<br />import java.awt.geom.*;</p><p align="left">import javax.swing.*;<br />import javax.swing.border.*;</p><p align="left">public class MyBorder implements Border<br />{<br /> //设置边框四周留出的空间<br />  protected int m_w=6;  <br />  protected int m_h=6;<br />  protected int m_left=16;<br />//设置边框的前景色跟背景色<br />  protected Color m_topColor = Color.white;<br />  protected Color m_bottomColor = Color.gray;</p><p align="left">  public MyBorder() {<br />    m_w=6;<br />    m_h=6;<br />    m_left=16;<br />  }</p><p align="left">  public MyBorder(int w, int h) {<br />    m_w=w;<br />    m_h=h;<br />  }</p><p align="left">  public MyBorder(int w, int h, Color topColor,<br />   Color bottomColor) {<br />    m_w=w;<br />    m_h=h;<br />    m_topColor = topColor;<br />    m_bottomColor = bottomColor;<br />  }</p><p align="left">  public Insets getBorderInsets(Component c) {<br />    return new Insets(m_h, m_left, m_h, m_w);<br />  }</p><p align="left">  public boolean isBorderOpaque() { return true; }</p><p align="left">  public void paintBorder(Component c, Graphics gd,<br />   int x, int y, int w, int h) {<br />    Graphics2D g = (Graphics2D) gd;<br />    w--;<br />    h--;<br />    g.setColor(m_topColor);<br />    g.drawLine(x, y+h, x, y+m_h);<br />    g.drawArc(x, y, 2*m_w, 2*m_h, 180, -90);<br />    g.drawLine(x, y, x+w-m_w, y);<br />    g.drawArc(x+w-2*m_w, y, 2*m_w, 2*m_h, 90, -90);<br />    int stringHeitht = y+h-5;</p><p align="left">    Point2D.Float  p1 = new Point2D.Float(x,y+h);<br />    Point2D.Float p2 = new Point2D.Float(x,y);<br />    GradientPaint gradient = new GradientPaint(p1,Color.blue,p2,Color.gray,false);<br />    //g.setColor(Color.YELLOW);<br />    //g.drawRect();<br />    g.setPaint(gradient);<br />    g.fillRect(x,y,x+m_left,y+h);</p><p align="left">    g.setColor(Color.GRAY);<br />    g.drawString("瓜",((x+m_left)-g.getFontMetrics().charWidth('傻'))/2,stringHeitht);<br />    int simpleFontHeitht = g.getFontMetrics().getHeight();<br />    stringHeitht-=simpleFontHeitht;<br />    g.drawString("傻",((x+m_left)-g.getFontMetrics().charWidth('傻'))/2,stringHeitht);</p><p align="left">    g.setColor(m_bottomColor);<br />    g.drawLine(x+w, y+m_h, x+w, y+h);<br />   // g.drawArc(x+w-2*m_w, y+h-2*m_h, 2*m_w, 2*m_h, 0, -90);<br />   g.drawLine(x, y+h, x+w, y+h);<br />    //g.drawArc(x, y+h-2*m_h, 2*m_w, 2*m_h, -90, -90);<br />  }</p><p align="left">}<br /><br /></p><p align="left"></p><hr /><p align="left">剩下的就是把这个边框给它装上去了.在JMenu中有一个方法getPopupMenu()得到弹出菜单对象JPopupMenu;<br />然后调用这个JPopupMenu对象的setBorder方法就行了.下面是完整的测试程序<br /><br />import java.awt.Toolkit;<br />import javax.swing.SwingUtilities;<br />import javax.swing.UIManager;<br />import java.awt.Dimension;</p><p align="left">public class Application1 {<br />  boolean packFrame = false;</p><p align="left">  /**<br />   * Construct and show the application.<br />   */<br />  public Application1() {<br />    MenuFaces frame = new MenuFaces();<br />    // Validate frames that have preset sizes<br />    // Pack frames that have useful preferred size info, e.g. from their layout<br />    if (packFrame) {<br />      frame.pack();<br />    }<br />    else {<br />      frame.validate();<br />    }</p><p align="left">    // Center the window<br />    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();<br />    Dimension frameSize = frame.getSize();<br />    if (frameSize.height &gt; screenSize.height) {<br />      frameSize.height = screenSize.height;<br />    }<br />    if (frameSize.width &gt; screenSize.width) {<br />      frameSize.width = screenSize.width;<br />    }<br />    frame.setLocation( (screenSize.width - frameSize.width) / 2,<br />                      (screenSize.height - frameSize.height) / 2);<br />    frame.setVisible(true);<br />  }</p><p align="left">  /**<br />   * Application entry point.<br />   *<br />   * @param args String[]<br />   */<br />  public static void main(String[] args) {<br />    SwingUtilities.invokeLater(new Runnable() {<br />      public void run() {<br />        try {<br />          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());<br />        }<br />        catch (Exception exception) {<br />          exception.printStackTrace();<br />        }</p><p align="left">        new Application1();<br />      }<br />    });<br />  }<br />}<br /><br /></p><p align="left"></p><hr /><p align="left">import java.awt.*;<br />import java.awt.event.*;<br />import javax.swing.*;</p><p align="left">public class MenuFaces<br />    extends JFrame {<br />  JPanel contentPane;<br />  BorderLayout borderLayout1 = new BorderLayout();<br />  JMenuBar jMenuBar1 = new JMenuBar();<br />  JMenu jMenuFile = new JMenu();<br />  JMenuItem jMenuFileExit = new JMenuItem();<br />  JMenuItem jMenuItem1 = new JMenuItem();<br />  JMenuItem jMenuItem2 = new JMenuItem();<br />  JMenuItem jMenuItem3 = new JMenuItem();<br />  JMenu jMenu1 = new JMenu();<br />  JMenuItem jMenuItem4 = new JMenuItem();</p><p align="left">  public MenuFaces() {<br />    try {<br />      setDefaultCloseOperation(EXIT_ON_CLOSE);<br />      jbInit();<br />    }<br />    catch (Exception exception) {<br />      exception.printStackTrace();<br />    }<br />  }</p><p align="left">  /**<br />   * Component initialization.<br />   *<br />   * @throws java.lang.Exception<br />   */<br />  private void jbInit() throws Exception {<br />    contentPane = (JPanel) getContentPane();<br />    contentPane.setLayout(borderLayout1);<br />    setSize(new Dimension(400, 300));<br />    setTitle("Frame Title");<br />    jMenuFile.setText("File");<br />    jMenuFileExit.setText("Exit");<br />    jMenuFileExit.addActionListener(new MenuFaces_jMenuFileExit_ActionAdapter(this));<br />    jMenuItem1.setText("open");<br />    jMenuItem2.setText("save");<br />    jMenuItem3.setText("save as");<br />    jMenu1.setText("other");<br />    jMenuItem4.setText("tt");<br />    jMenuBar1.add(jMenuFile);<br />    jMenuBar1.add(jMenu1);<br />    jMenuFile.add(jMenuItem3);<br />    jMenuFile.add(jMenuItem2);<br />    jMenuFile.add(jMenuItem1);<br />    jMenuFile.add(jMenuFileExit);<br />    jMenu1.add(jMenuItem4);<br />    JPopupMenu tt = jMenuFile.getPopupMenu();<br />    MyBorder myBorder = new MyBorder();<br />    tt.setBorder(myBorder);</p><p align="left">    setJMenuBar(jMenuBar1);<br />  }</p><p align="left">  /**<br />   * File | Exit action performed.<br />   *<br />   * @param actionEvent ActionEvent<br />   */<br />  void jMenuFileExit_actionPerformed(ActionEvent actionEvent) {<br />    System.exit(0);<br />  }<br />}</p><p align="left">class MenuFaces_jMenuFileExit_ActionAdapter<br />    implements ActionListener {<br />  MenuFaces adaptee;</p><p align="left">  MenuFaces_jMenuFileExit_ActionAdapter(MenuFaces adaptee) {<br />    this.adaptee = adaptee;<br />  }</p><p align="left">  public void actionPerformed(ActionEvent actionEvent) {<br />    adaptee.jMenuFileExit_actionPerformed(actionEvent);<br />  }<br />}<br /><br /><br />欢迎加入QQ群:30406099 <br /><br /></p><p align="center"><br /><br /><br /></p><p align="left"> </p><img src ="http://www.blogjava.net/fool/aggbug/56921.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fool/" target="_blank">傻  瓜</a> 2006-07-06 11:24 <a href="http://www.blogjava.net/fool/archive/2006/07/06/56921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>