且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在 XPage 中将富文本与 Java Managed Bean 结合使用

更新时间:2022-04-30 18:21:48

首先,正如 Stephan 在他的评论中所说,在 XPage 中找不到 RichTextItem.Domino 可以通过两种方式存储富文本"字段:

Firstly as Stephan said in his comments, RichTextItem's are nowhere to be found in XPages. Domino can store 'Rich Text' fields in 2 ways:

  • 作为 Notes 客户端通常使用的经典RichTextItem"
  • 作为完全另一种格式的 Mime/Html,由 lotus.domino.MimeEntity 组成

您通过 XPage 访问/修改并保存的任何RichTextItem"字段都将转换为 Mime.如果您打算在发送/处理电子邮件方面做任何事情,那么了解 Mime 并了解其工作原理是非常值得的.

Any "RichTextItem" field that you access/modify through XPages and save will be converted to Mime. If you are going to do anything with sending/processing emails, it is well worth learning about Mime and understanding how it all works.

如果您希望将 inputRichText 与嵌入图像一起使用,那么我认为没有人能够为您提供示例.inputRichText 控件与 Domino Document 数据源的绑定非常紧密.可能会想出一个解决方案,但它会涉及创建您自己的数据源类型、创建 DocumentAdapter、创建 DocumentAdapterFactory、通过 XspContributor 提供它并重新实现 DominoDocument 中的许多功能,这本身并不是微不足道的.

If you are looking to use the inputRichText with embedded images then I don't think anyone will be able to provide you with an example. The inputRichText control is very tightly bound to the Domino Document data source. It may be possible to come up with a solution, but it would involve creating your own type of DataSource, creating a DocumentAdapter, creating a DocumentAdapterFactory, supplying it through an XspContributor and re-implementing a lot of the functionality that is within the DominoDocument, which itself wasn't trivial.

如果您只想允许 HTML 内容(没有嵌入的图像或文件),那么您可以在之前回答的堆栈溢出问题中使用以下解决方案.将 inputRichText 绑定到 Bean这个答案描述了如何使用 MimeMultipart 类将 bean 绑定到 inputRichText 控件.我从来没有使用过这个解决方案,所以我不能评论它的有效性,但它有 7 个赞成票,所以看起来不错.您可能希望禁用用于上传图像的编辑器工具栏图标,以便用户认为他们无法上传(因为他们将无法上传)

If you are only looking to allow HTML content (no embedded images or files) then you may be able to use the following solution in a previously answered stack overflow question. Bind an inputRichText to a Bean This answer describes how you can bind a bean to a inputRichText control using the MimeMultipart class. I have never used this solution so I can't comment on it's effectiveness however it has 7 upvotes so it looks good. You would want to disable the editor's toolbar icon for uploading images so that the user does not think they can upload (because they won't be able to)

猜测,当您将 MimeMultipart 保存到文档时,您将有 2 个选项.

At a guess, when you go to save the MimeMultipart to the Document, you would have 2 options.

  • 另存为字符串
    • 为了节省,我认为你会使用 MimeMultipart 的 getHTML() 函数来获取 HTML 作为字符串
    • 要加载,您可以使用它的静态方法 MimeMultipart.fromHTML(yourhtml) 创建 MimeMultipart
    • 要保存创建 MimeEntity (doc.createMimeEntity()) 并使用 setContentFromText(),使用 NotesStream 传入 getHTML(),请参阅帮助中的示例
    • 要加载,使用 getContentAsText() 结合静态 MimeMultipart.fromHTML(mimeEntity.getContentAsText())

    抱歉,以上内容都不全面,但至少您有一些途径可以探索.请注意,您还应该查看 session.convertMime 设置及其工作原理 - 学习 Mime 很有趣,不是吗?:)

    Sorry none of the above is comprehensive but at least you have some avenues to explore. Note you also should look into the session.convertMime setting and how it works - learning Mime is fun, no? :)

    替代方案所有这些的替代方法是使用 Document DataSource + bean 的混合方法.将文档数据源绑定到 inputRichText 控件,然后将您的 bean 绑定到其他控件.要加载 bean 的数据,您可以使用变量解析器访问 DominoDocument.DominoDocument 是一个 Java 类,它包装了后端" lotus.domino.Document 类.它做了很多事情,比如跟踪哪些字段发生了变化,以及自从你加载它以来是否有其他人修改了文档.您可以使用 DominoDocument 的 getDocument() 函数访问后端类,但如果您使用这种混合方式,请不要直接保存后端文档,始终通过 DominoDocument 的 save() 方法保存.

    Alternative An alternative to all this is to go with a hybrid approach of Document DataSource + bean. Binding the document Data Source to the inputRichText control, and then binding your bean to the other controls. To load your bean's data you would get access to the DominoDocument using the variable resolver. The DominoDocument is a java class that wraps the 'backend' lotus.domino.Document class. It does a bunch of stuff like keeping track of what fields have changed and whether or not someone else has modified the document since you loaded it. You can access the backend class using the DominoDocument's getDocument() function, but if you are using this hybrid approach, do not save the backend document directly, always save through the DominoDocument's save() method.

    例如如果您的文档数据源是document1",请将自己设为私有函数

    e.g. if your document data source was 'document1', make yourself a private function

    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?)

    Then in some other function in your bean you can use to load, note the timing of when this is called is probably important (maybe postOpenDocument?)

    public void loadFromDominoDocument() {
        DominoDocument ddoc = getDominoDocument();
    
        this.someBeanVar = ddoc.getItemValueString("someBeanVar");
        this.anotherBeanVar = ddoc.getItemValueString("anotherBeanVar");
    
    }
    

    相反,您将拥有一些其他函数来使用 bean 值更新 domino 文档.

    conversely you will have some other function to update to the domino document with the bean values.

    public void updateDominoDocument() {
    
        DominoDocument ddoc = getDominoDocument();
    
        ddoc.replaceItemValue("someBeanVar",this.someBeanVar);
        ddoc.replaceItemValue("anotherBeanVar", this.anotherBeanVar);
    
    }
    

    注意:我还没有做任何保存,如果你使用这个混合模型,那么请注意你必须使用DominoDocument"类(你的 bean 中的 save() 方法或标准文档保存操作)来完成所有的保存- 调用 save() 方法).这是因为 save 方法会跟踪上次修改日期",如果您使用后端文档保存,它将保存一次,然后如果您尝试使用 DominoDocument 保存,它将失败,因为它会认为文档已被其他人修改(因为上次修改日期与其先前已知的值不匹配).不幸的是,并发"设置都没有改变这种行为.

    Note: I haven't done any saving yet, if you use this hybrid model then note that you must do all saving using the 'DominoDocument' class (either the save() method in your bean or the standard document save action - which calls the save() method). This is because the save method keeps track of the 'last modified date' and if you save using the backend document, it will save fine one time and then if you try to save using the DominoDocument, it will fail as it will think that the Document has been modified by someone else (as the last modified date does not match it's previously known value). Unfortunately none of the 'concurrency' settings change this behaviour.

    上面的代码是一个指南,我只是从头开始写,所以如果有任何问题,请告诉我,我会更深入地研究.相信你会有一些疑问!:)

    The above code is a guide, I have only written from the top of my head so let me know if any problem with it I will have a deeper look. I'm sure you will have some questions! :)