快速回答:永远,永远,永远,无论出于何种原因,存储 Domino 对象的句柄的时间都不要超过单个 HTTP 请求。:)
我怀疑,因为 Domino 会话本质上是一个单例,将它存储在应用程序范围内会阻止它在每个请求结束时被回收,就像通常那样。在正常情况下,XPage 引擎在任何 HTTP 请求结束时知道的任何 Domino 对象都会自动回收。因此,为了防止您收到错误,最好不要将句柄存储在高于请求的任何范围内。
好消息是,至少对于当前的Session
and Database
,您永远不需要:您可以向变量解析器询问它。
SSJS 对变量解析器具有内在访问权限,因为所有 SSJS 代码都必须在运行时进行评估;session
因此,例如,对 的任何引用都必须询问变量解析器当前评估的“会话”是什么。这在评估整个表达式时会自动发生,但我们可以从我们自己的 Java 代码中手动访问变量解析器:
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
VariableResolver resolver = app.getVariableResolver();
Session currentSession = (Session) resolver.resolveVariable("session", context);
每次我们想要获取变量的句柄时都要输入很多废话,并且解析上下文变量通常很有用(因为这适用于在 SSJS 中也有效的任何变量,而不仅仅是 Domino 对象),所以我建议将其包装在静态实用程序方法中:
public class VariableUtils {
public static Object getVariableValue(String variable) {
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
VariableResolver resolver = app.getVariableResolver();
return resolver.resolveVariable(variable, context);
}
}
然后,您可以轻松地从任何 Java 代码中解析任何变量:
Session currentSession = (Session) VariableUtils.resolveVariable("session");
Database currentDatabase = (Database) VariableUtils.resolveVariable("database");
DominoDocument currentDocument = (DominoDocument) VariableUtils.resolveVariable("currentDocument");
如果您的应用程序加载了扩展库,那么前两个已经有一个静态方法可用:
Session currentSession = (Session) ExtLibUtils.getCurrentSession();
Database currentDatabase = (Database) ExtLibUtils.getCurrentDatabase();
该类有一堆有用的变量解析方法,你可能想看看。但是拥有自己的解决变量的便捷方法对于任何上下文检查都很有用——例如,检索视图面板、数据表或重复的当前行;查询字符串参数映射(param
);任何数据源。就像 SSJS 一样,您的 Java 代码通常在给定组件的上下文中触发(例如,onclick
按钮的事件处理程序),因此任何对该组件有效的变量都可以通过这种方式解析。
关于存储 Domino 对象的最后一点说明:只存储元数据。因此,如果您要存储数据库(不是当前的),请存储其文件路径或副本 ID,当您需要访问它时,使用存储的元数据向当前会话询问数据库的句柄。同样,存储视图的名称,但不存储视图View
本身;存储文档的 NoteID 或 UNID,而不是实际的Document
. 如果您发现您必须反复获取这些句柄,因此希望它们被缓存,请重新审视您的逻辑结构方式......代码应该被重构以建立一个句柄,做任何需要做的事情 / 到该对象,然后丢弃它(如果它不是会话、数据库或您还绑定了数据源的对象,请手动回收它)。
请记住,任何实现Serializable
但不存储指向任何 Domino 对象的指针的 Java 对象都可以根据需要存储。因此,为您的数据创建“模型”对象(并通过读取相应的 Domino 句柄来填充它们的属性),将这些对象存储在范围内,然后在适当的时候写回相应的 Domino 对象。如果 IBM 没有尝试通过为我们创建文档和视图数据源来为我们简化 XPage,这就是我们已经在做的事情(例如,我们会将所有可编辑字段绑定到 bean 类的属性如Contact
, ExpenseReport
,Facility
等,不直接标注项目)。但是因为这些数据源确实存在,我们仍然在考虑“文档”和“视图”,而不是考虑数据所代表的人、物理对象和业务流程。因此,我们在用户界面和后端数据之间维护了不必要的链接,而不是仅在需要进行初始查询和最终更新(或创建)时才接触后端数据。很抱歉变得如此哲学,但是当我们超越文档思考时,我们在 XPages 中尝试做的很多事情变得非常容易。:)