Dorado 5 : 3.DoradoContext对象 (T1A)

与页面流思维模式不同,在dorado结构的服务器端进行代码编程时,或者说当服务器接收到dorado客户端的一个AJAX请求的时候,不会再有ActionForm,由于请求的信息已经xml格式化,我们直接通过HttpServletRequest获取其中的信息是比较徒劳的。况且良好的开发模式也不建议您应用系统中的逻辑代码与HttpServletRequest建立耦合。大量的成熟系统的框架都采用上下文方式,进行Request的解耦,同样在dorado系统中也提供了一个上下文对象用以解决这个问题,就是这节我们要说的DoradoContext。
上下文在很多情况下是指一种语境,是默认情况下的一种约定。在编程模式中它就是在某一种约定范围内的环境信息(通常情况下,我们都是通过一个名字对应一个对象的方式进行存取操作)。
通常情况下,DoradoContext操作的上下文都是指一个视图模型的生命周期,就如同我们MSN交流一样,指的是打开的那个MSN窗口情况下的交流,不关闭这个窗口之前所有的交流都在一个上下文中,Dorado中就对应为浏览器中打开一个Dorado页面,在关闭这个页面之前,服务器端和客户端的所有交互过程都处于一个会话期内(Dorado中的术语为VIEW会话期)。
这种会话期特点,在很多编程的情况下会被利用为描述页面状态,就是通常我们开发写代码时使用的全局变量。例如在DORADO开发模式下,很多情况下新增,修改,删除业务功能的页面都是由一个页面来完成,例如一个合同的内容,我们新增操作的时候可以看到如下界面:

而当我们要修改一个具体存在的合同页面时,我们又可以通过同样这个页面实现:

可以看到,上述的新增合同与编辑合同页面的内容是完全一样的,只是数据不同而已(这儿只是描述通常情况,还有一些例外暂不描述)
对于这种类型的视图,在Dorado中我们就已利用上下文,用来描述不同的操作状态。从而后台的代码编程和业务逻辑依据上下文中的不同状态完成合同维护工作。
示例代码:

public void init(int state) throws Exception { 
	if (STATE_VIEW==state){ 
		DoradoContext.getContext().setAttribute(DoradoContext.VIEW, "state", "ADD"); 
	} 
	super.init(state); 
}

上述代码在视图模型初始化的过程中,完成对上下文state的状态赋值工作。由于View的生命周期中,ViewModel的init方法会多次触发,应此我们在视图模型的状态为STATE_VIEW的时候,就实现对合同维护时的状态设定。这样我们在保存合同的时候,就可以直接从上下文中取出state,从而得知这是一个新增合同的操作还是合同更新操作。

public void saveContract(ParameterSet parameters, ParameterSet outParameters) 
throws Exception { 
	DoradoContext context = DoradoContext.getContext(); 
	String state = context.getAttribute("state"); 
	if ("ADD".equals(state)){ 
		//执行新增合同操作 
	} 
	else if ("UPDATE".equals(state)){ 
		//执行合同更新工作 
	} 
}

为了保持对web应用程序开发的支持,DoradoContext还提供了对HttpServletRequest,HttpSession,HttpServletContext对象的存取支持,在DoradoContext中是通过SCOPE来区分的。
同样前面的state保存,如果将代码修改为如下,则表示将state信息维护在HttpServletRequest范围的上下文中:

DoradoContext.getContext().setAttribute(DoradoContext.REQUEST, "state", "ADD");

而要从DoradoContext中获取HttpServletRequest中的state信息则可以通过如下的代码实现:

DoradoContext.getContext().getAttribute(DoradoContext.REQUEST, "state");

DoradoContext的getAttribute与setAttribute方法通过第一个参数指定上下文的范围,可选值有:

取值

说明

DoradoContext.REQUEST

HttpServletRequest范围

DoradoContext.VIEW

Dorado的View范围

DoradoContext.SESSION

HttpSession范围

DoradoContext.APPLICATION

HttpServletContext范围

在DoradoContext使用时,特别需要注意的是对DoradoContext.REQUEST范围的上下文的使用。看下图:

在我们打开contract.jsp,并且维护合同基本信息的所有过程中,会有多次的与ViewModel的交互过程。如果是一个已有合同的编辑页面,一般而言我们会在请求contract.jsp的时候,自动的将被编辑的合同号作为参数传递给该页面,便于服务器端的ViewModel准备数据,在页面返回之后我们就可以直接根据现有的合同信息编辑修改。而对于在这个页面编辑修改过程中发生的flushData和upate等AJAX请求,服务器端获得的HttpServletRequest已经与第一次请求完全不一样了。此时我们如果视图再次的从HttpServletRequest中获取contract_id,显然是愚蠢的。因此在代码编写时尤其需要注意这种Request依赖症。解决的办法就是将contract_id放在上下文中,而所有的业务逻辑代码都只依赖于上下文中的contract_id。这样我们就可以保证在页面请求之后,客户端发出的各种AJAX请求可以顺利的获取contract_id信息。
上下文中contract_id的存储一般来说建议的实现代码为在ViewModel的init方法中实现:

public void init(int state) throws Exception { 
	if (state == STATE_VIEW){ 
		String contractId = DoradoContext.getContext().getAttribute(DoradoContext.REQUEST, "contract_id"); 
		DoradoContext.getContext().setAttribute(DoradoContext.VIEW, "contractId", contractId); 
	} 
	super.init(state); 
}

DoradoContext的详细使用请参考<<dorado5 用户手册.doc>>。