79. 视图里的计算属性——从ASP、JSP、JSF到XPages的“钻石”

“钻石”与简洁高效的视图层技术

XPages刚推出时,Domino Designer启动后的欢迎页上对这个被寄予厚望的新技术有亮点式的介绍。其中有一节以Diamonds and events为标题,写到On the Properties tab, almost everything is computable. Look for theblue diamond icon and click it to get to the script editor. By invoking theeditor, you can write a formula to compute a value. 意思就是在属性视图上,几乎所有项都是可计算的。找到任一蓝色的钻石形的图标,单击它去到脚本编辑器。在编辑器里,你可以写一段公式来计算属性的值。这些“钻石”被当成XPages亮点来介绍是有道理的。在一个XPage里选中一个控件,在属性视图里会看到该控件的分类展现的属性,它们大部分的后面都有一个(有些并不是蓝色的,当鼠标悬浮于其上时才会变成蓝色)空心的钻石形的图标,单击它会显示一个下拉式菜单,第一项是“使用静态值”,第二项是“计算值”,选择它会打开脚本编辑器,在里面输入了代码后,属性后面会显示{Computed},钻石也会变成实心的。当然这些“钻石”和脚本编辑器仅仅是Designer为了方便开发者做的视觉上的提示和工具,在XPage的源代码视图,能够直接以controlProperty="#{bean.property}"之类的格式添加计算属性,这样做不但更接近本质,而且运用的范围比图形化的方式更广——属性视图上有些属性右侧没有钻石形图标,如在视图列的显示属性标签页里,Show values in this column as link、Check box、Icon等,这并不表示它们与众不同不能设置计算属性,而仅仅是因为Designer的设计者认为它们的值需要计算的可能性不大而没有做上,然而在实际开发时,如果需要我们仍然能够在源代码视图上设置它们的计算属性。在65. XPages自定义控件(三)高级搜索之三一文里列出的条件搜索控件的代码就用到了这一点。在下面的视图列的代码里,showCheckbox属性绑定到所在的自定义控件的自定义属性showEdit,决定是否显示为链接的displayAs属性也依据showEdit来计算。这样在不同的XPage里,藉由设置这个自定义控件的showEdit属性,就可以满足不同用户或场合对这一列显示和功能上的不同需要。

		<xp:viewColumn id="viewColumn8" columnName="$8"
			showCheckbox="${javascript:compositeData.showEdit}">
			<xp:this.displayAs><![CDATA[${javascript:if (compositeData.showEdit) return "link";}]]></xp:this.displayAs>
			<xp:this.facets>
				<xp:viewColumnHeader xp:key="header"
					id="viewColumnHeader8" value="Date">
				</xp:viewColumnHeader>
			</xp:this.facets>
			<xp:this.converter>
				<xp:convertDateTime type="date"></xp:convertDateTime>
			</xp:this.converter>
		</xp:viewColumn>

这些对熟悉了经典LotusNotes开发的程序员来说是全新的概念,在DominoDesigner里对传统的各种设计元素及其上的元件设置属性时,除了字段值、视图选择等特殊的“属性”可以输入公式来计算,大部分属性都是用经典的属性框(properties box)设置静态值。XPage文件里的几乎所有属性都可以设置公式来计算,这确实给应用程序的视图开发带来了极大的灵活性,不过这在Lotus Domino平台以外并不新鲜。用HTML或XML这样的声明性语言来定义用户界面,再辅以某种简单的表达式语言来设置计算的属性值,以实现动态的界面。首先采用声明性语言定义界面比用命令型语言简洁高效。其次单独的界面定义文件彻底贯彻了界面和业务逻辑分离的原则。最后利用表达式语言和事件绑定既清晰地实现了视图(view)和模型(model)之间的信息传递和控制转换,又保持了两者的独立性。这种良好的架构在很多web开发技术的视图层都早已应用。

Active Server Pages

微软公司最初针对开发动态网站推出的ASP技术,将在服务器端运行的脚本和HTML混合在一起。输出动态内容,基本可分为两种模式:一是在一段基本的HTML代码里,插入<%=expression%>脚本表达式计算出的值。二是在大段的<%script%>脚本里用Response.Write()输出HTML。如下面的代码所示:

<!DOCTYPE html>
<html>
<body>
<%
dim h, greetingTime
h=hour(now())
If h<12 Then
	greetingTime="morning"
Else
	greetingTime="day"
end If
‘show the current time
response.write("<p>" & now())
response.write("</p>")
%>
<div>
<p>Norm 1, to use varibles to output content</p>
<p>Good <%=greetingTime%>!</p>
</div>
<div>
<p>Norm 2, to use Response.Write() to output html</p>
<%
dim h2
h2=hour(now())
response.write("<p>")
If h<12 Then
   response.write("Good Morning!")
Else
   response.write("Good day!")
end If
response.write("</p>")
%>
</div>
</body>
</html>
虽然这两种常规的模式都只涉及完整的HTML标签或作为其内容的文本,但是ASP也接受将脚本表达式嵌入在HTML标签内计算属性值。
<%
dim align
align="center"
%>
<TABLE align="<%=align%>">
上面这段代码就能生成<TABLE align="center">的有效HTML。

JavaServer Pages、JavaServer Faces与XPages

Sun公司稍后推出的一整套基于Java的企业开发方案包含的JSP技术与ASP既有相似之处,也有很多不同。仅就本文的主题而言,JSP能用和上面极其相似的代码计算HTML标签里的属性。

<%
String align="center";
%>
<TABLE align="<%=align%>">
需要指出,这样包含脚本表达式的HTML是不符合XML格式规范的,所以在JSP文档(JSP document, .JSPX文件) 里是不合规的。

随着Java Standard Tag Library发展起来的JSP表达式语言(Expression Language)使得编写这种动态属性更加简洁,上面的JSP代码可以改写为:

<TABLE align="${bean.align}">

bean指向某个后端的Java Bean。

JSF开发之初为了其技术需要创造了专门的表达式语言(后与JSP表达式语言统一成UnifiedExpression Language),以JSF为支柱的XPages继承和扩展了这种语言,并且又加入了对服务器端JavaScript的支持。在XPage内设置计算属性时,若选择ExpressionLanguage (EL),或在数据绑定时选择ExpressionLanguage (EL)、ComponentParameter和Scoped Variable,背后使用的都是表达式语言,而选择JavaScript(Server Side) 时自然用的是服务器端JavaScript。

XPages里的表达式语言

最后我们来简单看看XPages里的表达式语言,在对JSF的表达式语言根据环境需要做了一些扩展之后,它在基本要点可以罗列如下:

${exp}和#{exp}

前者在页面初次载入时计算;后者在页面的组件树每次重建,也就是页面响应任何用户事件(如提交和点击按钮)后重新显示时都计算。

原义表达(Literals)

布尔值:true、false

数字(整数和浮点型):3、2.4、-1.5

字符串:"abc"、"this includes escape chars: \‘, \‘‘, \\"

标识符(Identifiers)

JSF和XPages环境支持的隐式对象变量:facesContext、view、request、param、cookie……

在faces-config.xml里注册的Managed Beans。

运算符

算数的:+、-、*、/、div、mod

逻辑的:and、&&、or、||、not、!

关系的:==、eq、!=、ne、>、gt、<、lt、>=、ge、<=、le

条件的:condition ? actionA : actionB

类型判断:empty判断是否为null,instanceof判断类型

属性

在JSF里标志符及其属性的解析都是建立在一个可插拔的框架上。所以XPages才得以根据需要提供更多的隐式对象变量。变量属性的解析也只要遵循一定的接口就可以,在XPages里,包括1)Java Bean的getter/setter的命名习惯、2)Java的Map接口和3)com.ibm.xsp.model.DataObject接口。所以下面的属性解析都是可行的:

myBean.name --> myBean.getName();

myBean["key"] --> myBean.get("key");

myBean.customers["Apple"] --> myBean.getCustomers().get("Apple");

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。