在 XPages 中将富文本与 Java 托管 Bean 结合使用
Using Rich Text with Java Managed Bean in XPages
任何人都可以提供一个示例,说明如何使用带有后端 RichText 字段的托管 bean 执行基本的 CRUD 操作,因此最终结果与在标准 XPage 开发中使用文档数据源相同。
下面的代码显然是错误的或不完整的,但我找不到任何文档来进一步说明它。
我知道我还没有回收任何东西。
非常感谢。
public class RichTextTest implements Serializable {
private static final long serialVersionUID = 1L;
private String plainItem;
private RichTextItem richItem;
private String unid;
public RichTextTest ()throws NotesException {
String docID = ExtLibUtil.readParameter(FacesContext.getCurrentInstance(),"key");
if (StringUtil.isNotEmpty(docID)){load(docID);}}
public void load(String ID) throws NotesException{
Document doc = null;
setUnid(ID);
doc = ExtLibUtil.getCurrentDatabase().getDocumentByUNID(ID);
setPlainItem(doc.getItemValueString("PlainTextField"));
setRichItem ((RichTextItem) doc.getFirstItem("RichTextField"));
}
public void save() throws NotesException{
Database database = ExtLibUtil.getCurrentDatabase();
Document doc = database.getDocumentByUNID(getUnid());
doc.replaceItemValue("PlainTextField", getPlainItem());
doc.replaceItemValue("RichTextField",getRichItem());
doc.save();
}
public String getPlainItem() {
return plainItem;
}
public void setPlainItem(String plainItem) {
this.plainItem = plainItem;
}
public RichTextItem getRichItem() {
return richItem;
}
public void setRichItem(RichTextItem richItem) {
this.richItem = richItem;
}
public void setUnid(String unid) {
this.unid = unid;
}
public String getUnid() {
return unid;
}
在 XPage 上
<xp:inputText value="#{richTextTest.plainItem}" id="plainTextField1"> </xp:inputText>
<xp:br></xp:br>
<xp:inputRichText value="#{richTextTest.richItem}" id="richTextField1"></xp:inputRichText>
<xp:br></xp:br>
<xp:button value="Save" id="button1"><xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:executeScript script="#{richTextTest.save}"></xp:executeScript>
</xp:this.action></xp:eventHandler></xp:button>
首先,正如 Stephan 在评论中所说,在 XPage 中找不到 RichTextItem。 Domino 可以用两种方式存储 'Rich Text' 个字段:
- 作为 Notes 客户端通常使用的 classic 'RichTextItem'
- As Mime/Html 完全是另一种格式,由 lotus.domino.MimeEntity 的
组成
您通过 XPages access/modify 并保存的任何 "RichTextItem" 字段都将转换为 Mime。如果您打算对 sending/processing 电子邮件做任何事情,那么学习 Mime 并了解它是如何工作的是非常值得的。
如果您希望将 inputRichText 与嵌入图像一起使用,那么我认为没有人能够为您提供示例。 inputRichText 控件非常紧密地绑定到 Domino 文档数据源。
可能会想出一个解决方案,但它会涉及创建您自己的数据源类型、创建一个 DocumentAdapter、创建一个 DocumentAdapterFactory、通过 XspContributor 提供它并重新实现 DominoDocument 中的许多功能,这本身并不是微不足道的。
如果您只想允许 HTML 内容(无嵌入图像或文件),那么您可以在之前回答的堆栈溢出问题中使用以下解决方案。
Bind an inputRichText to a Bean
此答案描述了如何使用 MimeMultipart class 将 bean 绑定到 inputRichText 控件。我从来没有使用过这个解决方案,所以我不能评论它的有效性,但是它有 7 个赞成票,所以它看起来不错。
您可能希望禁用用于上传图片的编辑器工具栏图标,以便用户认为他们无法上传(因为他们将无法上传)
猜测一下,当你将 MimeMultipart 保存到 Document 时,你会有 2 个选项。
- 将其保存为字符串
- 为了省钱,我认为您可以使用 MimeMultipart 的 getHTML() 函数将 HTML 作为字符串
- 要加载,您可以使用它的静态方法创建 MimeMultipart MimeMultipart.fromHTML(yourhtml)
- 将其另存为 MimeEntity
- 要保存,请创建一个 MimeEntity (doc.createMimeEntity()),然后使用 setContentFromText(),使用 NotesStream 传入 getHTML(),请参阅帮助
中的示例
- 要加载,结合使用 getContentAsText() 和静态 MimeMultipart.fromHTML(mimeEntity.getContentAsText())
抱歉 none 以上内容很全面,但至少您有一些途径可以探索。请注意,您还应该查看 session.convertMime 设置及其工作原理 - 学习 Mime 很有趣,不是吗? :)
备选
所有这些的替代方法是使用 Document DataSource + bean 的混合方法。将文档数据源绑定到 inputRichText 控件,然后将您的 bean 绑定到其他控件。
要加载 bean 的数据,您可以使用变量解析器访问 DominoDocument。
DominoDocument 是一个 java class,它包裹了 'backend' lotus.domino.Document class。它会做很多事情,比如跟踪哪些字段发生了变化,以及自您加载文件后是否有人修改了该文件。您可以使用 DominoDocument 的 getDocument() 函数访问后端 class,但是如果您使用这种混合方法,请不要直接保存后端文档,始终通过 DominoDocument 的 save() 方法进行保存。
例如如果您的文档数据源是 'document1',请将自己设为私有函数
private DominoDocument getDominoDocument() {
Object o = ExtLibUtil.resolveVariable(FacesContext.getCurrentInstance(), "document1");
if (o == null) return null;
if (o instanceof DominoDocument) {
return (DominoDocument)o;
} else if (o instanceof DominoDocumentData) {
return ((DominoDocumentData)o).getDocument();
}
}
然后在您的 bean 中的其他一些函数中您可以使用它来加载,注意调用它的时间可能很重要(也许是 postOpenDocument?)
public void loadFromDominoDocument() {
DominoDocument ddoc = getDominoDocument();
this.someBeanVar = ddoc.getItemValueString("someBeanVar");
this.anotherBeanVar = ddoc.getItemValueString("anotherBeanVar");
}
相反,您将有一些其他功能来使用 bean 值更新到 domino 文档。
public void updateDominoDocument() {
DominoDocument ddoc = getDominoDocument();
ddoc.replaceItemValue("someBeanVar",this.someBeanVar);
ddoc.replaceItemValue("anotherBeanVar", this.anotherBeanVar);
}
注意:我还没有做任何保存,如果你使用这个混合模型,那么请注意你必须使用 'DominoDocument' class(或者中的 save() 方法)您的 bean 或标准文档保存操作 - 它调用 save() 方法)。
这是因为保存方法会跟踪 'last modified date',如果您使用后端文档保存,它会保存一次,然后如果您尝试使用 DominoDocument 保存,它将失败,因为它会认为文档已被其他人修改(因为最后修改日期与其先前已知的值不匹配)。不幸的是,'concurrency' 设置中的 none 改变了这种行为。
上面的代码是一个指南,我只是从头开始写的,所以如果有任何问题请告诉我,我会进行更深入的研究。我相信你会有一些问题! :)
任何人都可以提供一个示例,说明如何使用带有后端 RichText 字段的托管 bean 执行基本的 CRUD 操作,因此最终结果与在标准 XPage 开发中使用文档数据源相同。
下面的代码显然是错误的或不完整的,但我找不到任何文档来进一步说明它。
我知道我还没有回收任何东西。
非常感谢。
public class RichTextTest implements Serializable {
private static final long serialVersionUID = 1L;
private String plainItem;
private RichTextItem richItem;
private String unid;
public RichTextTest ()throws NotesException {
String docID = ExtLibUtil.readParameter(FacesContext.getCurrentInstance(),"key");
if (StringUtil.isNotEmpty(docID)){load(docID);}}
public void load(String ID) throws NotesException{
Document doc = null;
setUnid(ID);
doc = ExtLibUtil.getCurrentDatabase().getDocumentByUNID(ID);
setPlainItem(doc.getItemValueString("PlainTextField"));
setRichItem ((RichTextItem) doc.getFirstItem("RichTextField"));
}
public void save() throws NotesException{
Database database = ExtLibUtil.getCurrentDatabase();
Document doc = database.getDocumentByUNID(getUnid());
doc.replaceItemValue("PlainTextField", getPlainItem());
doc.replaceItemValue("RichTextField",getRichItem());
doc.save();
}
public String getPlainItem() {
return plainItem;
}
public void setPlainItem(String plainItem) {
this.plainItem = plainItem;
}
public RichTextItem getRichItem() {
return richItem;
}
public void setRichItem(RichTextItem richItem) {
this.richItem = richItem;
}
public void setUnid(String unid) {
this.unid = unid;
}
public String getUnid() {
return unid;
}
在 XPage 上
<xp:inputText value="#{richTextTest.plainItem}" id="plainTextField1"> </xp:inputText>
<xp:br></xp:br>
<xp:inputRichText value="#{richTextTest.richItem}" id="richTextField1"></xp:inputRichText>
<xp:br></xp:br>
<xp:button value="Save" id="button1"><xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:executeScript script="#{richTextTest.save}"></xp:executeScript>
</xp:this.action></xp:eventHandler></xp:button>
首先,正如 Stephan 在评论中所说,在 XPage 中找不到 RichTextItem。 Domino 可以用两种方式存储 'Rich Text' 个字段:
- 作为 Notes 客户端通常使用的 classic 'RichTextItem'
- As Mime/Html 完全是另一种格式,由 lotus.domino.MimeEntity 的 组成
您通过 XPages access/modify 并保存的任何 "RichTextItem" 字段都将转换为 Mime。如果您打算对 sending/processing 电子邮件做任何事情,那么学习 Mime 并了解它是如何工作的是非常值得的。
如果您希望将 inputRichText 与嵌入图像一起使用,那么我认为没有人能够为您提供示例。 inputRichText 控件非常紧密地绑定到 Domino 文档数据源。 可能会想出一个解决方案,但它会涉及创建您自己的数据源类型、创建一个 DocumentAdapter、创建一个 DocumentAdapterFactory、通过 XspContributor 提供它并重新实现 DominoDocument 中的许多功能,这本身并不是微不足道的。
如果您只想允许 HTML 内容(无嵌入图像或文件),那么您可以在之前回答的堆栈溢出问题中使用以下解决方案。 Bind an inputRichText to a Bean 此答案描述了如何使用 MimeMultipart class 将 bean 绑定到 inputRichText 控件。我从来没有使用过这个解决方案,所以我不能评论它的有效性,但是它有 7 个赞成票,所以它看起来不错。 您可能希望禁用用于上传图片的编辑器工具栏图标,以便用户认为他们无法上传(因为他们将无法上传)
猜测一下,当你将 MimeMultipart 保存到 Document 时,你会有 2 个选项。
- 将其保存为字符串
- 为了省钱,我认为您可以使用 MimeMultipart 的 getHTML() 函数将 HTML 作为字符串
- 要加载,您可以使用它的静态方法创建 MimeMultipart MimeMultipart.fromHTML(yourhtml)
- 将其另存为 MimeEntity
- 要保存,请创建一个 MimeEntity (doc.createMimeEntity()),然后使用 setContentFromText(),使用 NotesStream 传入 getHTML(),请参阅帮助 中的示例
- 要加载,结合使用 getContentAsText() 和静态 MimeMultipart.fromHTML(mimeEntity.getContentAsText())
抱歉 none 以上内容很全面,但至少您有一些途径可以探索。请注意,您还应该查看 session.convertMime 设置及其工作原理 - 学习 Mime 很有趣,不是吗? :)
备选 所有这些的替代方法是使用 Document DataSource + bean 的混合方法。将文档数据源绑定到 inputRichText 控件,然后将您的 bean 绑定到其他控件。 要加载 bean 的数据,您可以使用变量解析器访问 DominoDocument。 DominoDocument 是一个 java class,它包裹了 'backend' lotus.domino.Document class。它会做很多事情,比如跟踪哪些字段发生了变化,以及自您加载文件后是否有人修改了该文件。您可以使用 DominoDocument 的 getDocument() 函数访问后端 class,但是如果您使用这种混合方法,请不要直接保存后端文档,始终通过 DominoDocument 的 save() 方法进行保存。
例如如果您的文档数据源是 'document1',请将自己设为私有函数
private DominoDocument getDominoDocument() {
Object o = ExtLibUtil.resolveVariable(FacesContext.getCurrentInstance(), "document1");
if (o == null) return null;
if (o instanceof DominoDocument) {
return (DominoDocument)o;
} else if (o instanceof DominoDocumentData) {
return ((DominoDocumentData)o).getDocument();
}
}
然后在您的 bean 中的其他一些函数中您可以使用它来加载,注意调用它的时间可能很重要(也许是 postOpenDocument?)
public void loadFromDominoDocument() {
DominoDocument ddoc = getDominoDocument();
this.someBeanVar = ddoc.getItemValueString("someBeanVar");
this.anotherBeanVar = ddoc.getItemValueString("anotherBeanVar");
}
相反,您将有一些其他功能来使用 bean 值更新到 domino 文档。
public void updateDominoDocument() {
DominoDocument ddoc = getDominoDocument();
ddoc.replaceItemValue("someBeanVar",this.someBeanVar);
ddoc.replaceItemValue("anotherBeanVar", this.anotherBeanVar);
}
注意:我还没有做任何保存,如果你使用这个混合模型,那么请注意你必须使用 'DominoDocument' class(或者中的 save() 方法)您的 bean 或标准文档保存操作 - 它调用 save() 方法)。 这是因为保存方法会跟踪 'last modified date',如果您使用后端文档保存,它会保存一次,然后如果您尝试使用 DominoDocument 保存,它将失败,因为它会认为文档已被其他人修改(因为最后修改日期与其先前已知的值不匹配)。不幸的是,'concurrency' 设置中的 none 改变了这种行为。
上面的代码是一个指南,我只是从头开始写的,所以如果有任何问题请告诉我,我会进行更深入的研究。我相信你会有一些问题! :)