pe框架简介5--CoreController

1、CoreController

1)刚进入类CoreControllerImpl.java

会看到:private static ThreadLocal if = new ThreadLocal(); 

ThreadLocal 在execute()方法起始的地方:setContext(var1); 意思是将context放入ThreadLocal,那么context就可以在该线程的任何地方可见,不用再通过传参的方式将其往下传。(常见例子:public void init(Context context){...}  context直接可以拿来用)

finally结束的地方:setContext((Context)null); 意思是释放掉ThreadLocal线程结束,context也随之消失。

2)CoreController.execute()方法如下:

public void execute(Context var1)throws PeException {....}

下面我们详细分析下execute()方法:

1)  由pe框架简介4--MainController可知,var1的类型为LocalServletContext,通过下面的类图可以看出LocalServletContext实现了TransactionConfigAware,所以execute()方法上来进入if分支,此时 var1 为localServletContext。

2)由var2 = (TransactionConfig)this.getApplicationContext().getBean(var1.getTransactionId()) 知, var2 为transaction中的id所指明的bean。例如下图的PrintBillByQRCodeQuery。

问题:Context.setTransactionId();在哪里体现??

我们需要注意:((TransactionConfigAware)var1).setTransactionConfig(var2); 将Context.TransactionConfig属性已经设置为transaction中的id,后续会用Context.getTransactionConfig()获取相应的transaction。

3)最关键的便是:Chain var3 = var2.getTemplate().getChain();

该句是指找到 template.xml 中的相应模板的chain,对应下图的例子就是找到 template.xml  中 id="queryTemplate" 的chain : chain="chainForRoleControlMV" 。

问题:Context.setTemplate().setChain()在哪里体现??

4) var3.execute(var1, (Map)null); 便是调用 Chain.execute()方法,由于Chain接口的实现类只有一个:ChainImpl,所以执行的方法为为ChainImpl.execute()

其中实现类ChainImpl实现了Chain、Command接口。

2、ChainImpl.execute()方法关键步骤如下:

图2-1
图2-2

1)var3 = var12.execute(var1,this.else);

其中 var12 为 var9 的子集,而 var9  为 this.new ,this.new (见下图)就是chain.xml中的各个command

到此,我们就可以执行各个command.execute()方法了。

图2-3

2)if (case ||char || var3) {  break; } 我们注意到:

(a)在循环执行各个command.execute()方法时,如果execute()方法返回结果为true;则跳出循环,不再执行后续的command。即如果chain中的commond在按顺序执行时,遇到一个返回true,则剩余的commond不再继续执行。所以开发的时候需要注意,如果想让commond都执行一遍,程序中commond的实现类必须要返回false,返回true和异常的场景,不会继续执行接下来的commond。

  (b)如果execute()方法抛出异常,则catch住(见图2-1),并跳出循环,之后对异常的处理都转化为PE框架的异常,见图2-2

(c)对于图2-2的上半部分,我们可以看到还有一个对var9的循环处理,var9 此时为 this.try,this.try(见图2-3)即实现Terminator的commond,其中this.new中已经排除它,在这里单独处理这些类型的commond。


3)我们来看个Commod的例子:DateStyleCommod例子如下:

(a)根据DateStyleCommod找到实现类:com.ceb.wap.mgmt.core.DateStyleCommod

  (b)执行DateStyleCommod.execute()方法,即执行父类AbstractChannelCommand.execute()方法

(c)父类的execute()调用抽象的channelExecute(),通过策略模式,让各个子类自己实现channelExecute()方法


图2-4
图2-5
图2-6

4)特殊的commond:DelegateCommand

每一个Chain必须有一个而且仅限于一个DelegateComand(但是DelegateComand并不一定能执行到,一旦有一个Command返回true或者跑异常,则不会继续执行剩余的Command,证明代码有异常或者校验不通过的情况);

 当Chain执行到DelegateCommand时,开始执行Template,所以DelegateCommand要放在所有Command的最后;

图2-7

5)由DelegateCommand源码可以看出,当执行到DelegateCommand时,开始执行Template.execute(),即执行tempalte.xml中对应class的execute()。

我们选取Template的其中一个实现类ExecutableSequenceTemplate来看一下。

(a) ExecutableSequenceTemplate 继承AbstractSequenceTemplate ,所以执行父类AbstractSequenceTemplate .execute()。

  (b) AbstractSequenceTemplate .execute()方法:见图2-10  。首先它获取template.xml中的actions,如果actions为空,则取transaction里的action执行,否则执行Template里的action。 

  (c)    由图2-11可知,  如果var2不为空,即 transaction里的action,或者Template里的action有一个不为空,就循环执行:

          Action var4 =this.getAction((String)var3.next(), var1);      具体逻辑见  图2-12

  (d)  图2-12 便是 怎么从Template里的actions 执行到  transaction里的actions 里的关键

         Map var3 = var2.getTransactionConfig().getActions();  //首先获取transaction里的action

         // 如果 transaction里的action 为空,返回Template里的actions     

        if (var3 == null) { var4 = this.getActions().get(var1); return (Action)var4;} 

       //  如果 transaction里的action 不为空

        var4 = var3.get(var1);   

        if (var4 == null) {  

                var4 = this.getActions().get(var1);

            } 

// 由图2-11可知 ,var1 为 transaction里的action 的ref的name,如:aftaction、action、preAction等,var3  是 Template里的actions的map(ref的name,ref的值) ,这句话是说,从 var3 ( Template里的actions  )中取出与var1(  transaction里的action )的ref相同的name,一般 : 

       transaction :Placeholder       var1 :  action 

      Template  :PrintBillByQRCodeAction     var3: map(action ,PrintBillByQRCodeAction)  

     也就是说,获取 var3:map( action ,PrintBillByQRCodeAction) 中key为 var1的value,即将Template   中ref.name 与transaction 中 ref.name 相同的action替换为  transaction 的action,这样便开始执行transaction .action。

     如果var4 == null 还继续执行Template  中的action。

     为了最后执行transaction .action,必须先将 Template  中的action执行完,那么 Template  中与transaction 重名的action(ref.name相同,即action)必须写在最后。

图2-8
图2-9
图2-10


图2-11


图2-12


3、DelegateCommand执行完后,返回到MainController中,开始执行this.resolveViewName(var4);  返回响应的jsp页面。详见pe框架简介4--MainController



你可能感兴趣的:(pe框架简介5--CoreController)