机制
菜单栏Windows—Open EclipseViews—Package Explorer,打开一个Xpages应用,新建一个Java源文件夹(如WebContent\src),创建一个Java Class,开始编码。
这就是在版本8.5.3之前的Designer里写Java代码要经历的步骤。对于使用Eclipse的开发人员来说很普通,对于Domino开发人员来说是非典型的后门。IBM正视到在Xpages应用里使用Java的必要性,从8.5.3起新增了Java设计元素,使得添加Java不再需要专门的技巧。
那么这些Java代码怎样在Xpages应用里发挥作用呢?我们知道Xpages是基于Java ServerFace技术的。JSF本身是一个Java的采用组件模型的开发Web应用的框架。所有的XPage都是编译成Java后作为一个JSF应用运行的。和大多数流行的Web开发框架一样,JSF也采用MVC的设计原则。视图(View)使用JSP或Facelet技术,业务逻辑(Model)封装在用Java编写的Managed Bean里。两者之间通过作为控制器(Controller)的专门的FacesServlet连接起来。这个Servlet在JSF中可以在web.xml里配置,默认是指定为javax.faces.webapp.FacesServlet,在Xpages里则被隐藏起来,固定为com.ibm.xsp.webapp.FacesServlet。在实际操作中,视图需要访问和调用某个Managed Bean的属性和方法时,就使用JSF表达式语言(JSF Expression Language)引用该Bean配置好的对应变量名称,比如用户在页面上单击一个按钮,就可以调用Bean的方法响应事件。控制器将表达式语言中的调用传递到该Bean的对应方法(包括在初次调用时创建Bean的实例)。IBM为了让开发体验更接近传统的Notes客户端应用开发,在XPage的设计视图上为各个控件添加了一系列前端和后端事件,两者都可以用JavaScript编写响应程序。隐藏在服务器端事件和SSJS背后的仍然是上述的JSF机制。Xpages只是在JSF之上扩展出的针对控件普遍适用的服务器端事件(比如onClick, onKeyUp,onMouseOver,原来的JSF控件支持的事件就单纯很多,像作为按钮的UICommand就只有onClick事件),以一致的方式添加事件的EventHandler标记和采用SSJS来编写事件响应程序。至于忽视这一切简化或者说傻瓜化的努力,仍然采用Java的好处,在22. 为什么要在XPages中写Java里已经解释过了。
Bean?
回头来看这些Java代码,在Xpages应用里都是以Managed Bean的形式存在的。这个Managed Bean就是JSF里对JavaBean应用的称呼。Bean又是什么呢?像任何应用广泛的名字一样,在不同的场合里,它有不同的含义。小到一个Java对象,大到一个编程框架。在我们的Xpages上下文里,把它理解成遵守以下编程规范的Java对象就可以了:
1.有一个无参数的构造函数。
2.对字段的读写采用getField(), setField()的方法。
3.(可选)实现Serializable接口。
遵守这些规范是为了使这些Bean可以作为具备一定功能的组件合作,还能和各种自动化的工具和环境协作。第一点保证使用者可以创建一个Bean的实例;第二件使得使用者可以可靠地读取和写入实例的属性;Bean在应用中经常需要被持久化到诸如文件的各种媒介里,被存储或传输后又需要被反序列化成对象,所以需要具备第三特点。这些Bean之所以被称为Managed(被管理的),就是因为它们是受JSF框架控制,由系统自动根据不同的生命周期创建维护和销毁。用于描述它们的元信息,在JSF2.0以前(包括XPages)被描述在faces-config.xml文件里;在JSF2.0以后,改为采用更为方便灵活的Java标记。下面就是一个简单的Managed Bean配置。managed-bean-name设置在页面上使用该Bean的名称,managed-bean-scope设置该Bean的作用域,和SSJS全局变量一样,有四种选项,application, session,request, view,含义和用途参考全局变量。
<?xml version="1.0" encoding="UTF-8"?> <faces-config> <managed-bean> <managed-bean-name>app</managed-bean-name> <managed-bean-class>starrow.xsp.App</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> </managed-bean> <!--AUTOGEN-START-BUILDER: Automatically generated by IBM Domino Designer. Do not modify.--> <!--AUTOGEN-END-BUILDER: End of automatically generated section--> </faces-config>有趣的是,在创建JavaBean这一点上,IBM还是半拖半就,少有简化这一系列配置的努力。只是在8.5.3引入Java设计元素,在9.0里将faces-config.xml加入Designer视图。而其他JSF开发工具,一般都会提供对话框方便增加Bean的配置信息,不需要手工填写faces-config.xml文件。
在Xpages应用里,这些Bean可以用来实现包括下面列出的各种功能:
1.对用户输入的数据进行校验。
2.响应各个控件如按钮的事件。
3.给诸如下拉框的控件计算选项。
4.判断要转到哪一个页面。
这些在以后的文章中都可能会用实例来说明。
实例
最后来演示一下应用Java来响应一个按钮单击事件的全过程。
1.创建一个Java类。
package starrow; public class Test implements java.io.Serializable{ public void testAction() throws NotesException{ //Do something you can see the result. FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put("message", "hello"); } }2.在faces-config文件里配置Bean的信息。
<?xml version="1.0" encoding="UTF-8"?> <faces-config> <managed-bean> <managed-bean-name>test</managed-bean-name> <managed-bean-class>starrow.Test</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> </faces-config>3.在一个XPage上添加一个按钮和一个计算文本绑定到message变量。
<xp:button id="btnTest" value="test"> <xp:eventHandler event="onclick" submit="true" refreshMode="complete" action="#{test.test}"> </xp:eventHandler> </xp:button>
运行试试看吧!
值得说明的还有一点,本来我们看到xp:button有action和actionListener属性,就可以猜到在JSF里是直接设置它们来设计事件响应程序的,看Xpages对这些属性的说明证实了这一点,但是如果我们将action属性移到button里,点击按钮时却什么也不会发生。只有放在IBM专门设计的xp:eventHandler里才行。而且在表达式里,只能用#不能用$,否则也会报错找不到Bean的test方法。