`

seam的对话conversaction问题

阅读更多

对seam的研究使用已经有很长一段时间了,整体感觉是相当的不错,虽说中间也碰到了各种各样、大大小小的问题,但最终也都能一一解决了,逐渐对它的信心越来越坚定了。

 对话是seam的一个亮点,seam很多内置组件也是利用了对话的特性,比如message,持久化,重定向等等很多都是利用对话来实现的。下面来说说我们项目中使用对话的一些概况。

1)列表翻页后编辑后再返回当前页

2)类似多窗口的工作区切换,和1)相似就是任何时候进入指定页面都能保留最后一次在该页面操作的条件(描述的不太好)

这些功能不用seam对话也可是做的,想必大家也为此做过不少工作,应该说是相当麻烦的,并且每个查询条件都要特定来写。而使用了对话那就是非常的简单了,跟具体的列表没有关系。

 

大家也都知道对话是seam的一大特色,但对它强大的功能表示怀疑,对它的第一怀疑就是性能问题,而性能是web系统的最大忌讳,所以就将信将疑地浮云掠过。主要还是对对话这种方式不太习惯,因为这是seam特有的机制,基于session和request之间,还要就是对话的原理还是比较复杂的,需要慢慢的来理解深入。

 

对话的基本原理:对话范围的对象按照“对话id+变量名称”来存储在session中,每个jsf请求的第一阶段都会去恢复当前对话及它的父对话,这样中间的阶段就可以使用前一个request中的对话范围的对象,在请求的第6阶段回去保存当前长久对话,并且结束所有超时的长对话。

对话最关键的就是要明确的开始和结束,如果不明确的开始对话,那就与普通的request没有什么区别;还要明确的来结束对话,当然你也可以不结束对话而是让他自然超时,但是这样明显会带来性能问题。

seam提供了多种开始结束(嵌套算是子对话的开始)的方式

1)第一阶段,通过s:link s:button标签来开始、嵌套、结束对话,他们的本质就是通过在url中传递cid或对话传播类型来使用、结束、开始对话等

没有propagation:当前cid

propagation="none" 传播类型和cid都没有

 

propagation="end"Propagation=end&cid=25

propagation="begin"pagation=begin'

propagation="nest"conversationPropagation=nest&cid=25

propagation="join"Propagation=join&cid=29

propagation="join22":错误的传播类型,传播类型和cid都没有

由于s:link s:button最终也是生成html,通过url传递cid或对话传播类型的,所以我们也可以在普通的链接上添加pagation=begin'参数来启动长对话,这对帧结构的菜单非常有用,这样我们就可以在帧中方便地使用对话了

2)在第5阶段,通过action来开始结束对话,可以直接调用对话方法 #{conversation.begin},也可以调用普通方法,只是该方法需要@Begin注释而已.

3)在第6阶段,通过page.xml配置文件来开始结束对话<begin-conversation/> <end-conversation/>注意,同一页面配置begin-和end-只能配置一个。

我的感觉最方便的应该是第1种方式,毕竟直接在页面上写要直接的多,第3种可能会导致对话的多长执行,因为进入该页面时需要执行一次对话,而faces提交时还要执行对话,而我们可能faces提交时并不想执行对话。

 

 

一个对话是由多个request组成的,我们大部分的概念是一连串的request,比如用户注册分成了多个步骤,还有就是复杂的页面流,很多朋友一提到对话就与页面流联系上,说我们没有那么复杂的页面流程用不上对话,其实页面流只是使用对话机制来实现的,而不是对话只能用在页面流上,我们项目中使用对话来解决的问题都跟页面流无关。其实一个对话也可以不连续,一个对话的中间也可以执行其他的对话。就比如用户注册的例子,用户注册需要3步来完成,而如果操作者执行到第2步却去执行其他的操作了,这是我们无法控制的,由于web访问的随意性,我们没办法来强制用户的操作。当操作者做完其他事情了,又想继续刚才的注册(这里只是打个比方,想说明的是一个中断的任务如何继续而已),这时如何恢复还没有结束的对话就显得非常的必要了。 seam给出的解决方案就是工作区管理,我们可以在页面上列出所有未结束的长久对话,想继续那个对话就直接点击对话链接就行了,这样就进入了该对话最后一次操作时保留的状态。具体内容请参考满江红文档,里面的工作区管理写的还是比较详细的。

并不是每个没有结束的长久对话我们都需要恢复的,要做到能恢复我们还必须给对话设置个描述(参见seam文档),不设置对话描述的对话我们是没法再使用的,这样就会产生个问题,那些对话没法来显示关闭了,只能等待对话超时,不知不觉就会积累出性能问题,因为这些操作可能会非常频繁,只开始对话而不结束对话,相当与把很多request的内容都保存到了session,这是相当可怕的。所以在我们没有很好的掌握对话的前提下要避免使用对话。还有就是上步提到的工作区管理也存在同样的问题,由于用户操作的习惯性(或者误操作),用户更习惯于点击注册菜单来注册,而不会去工作区里去恢复中断的注册对话,这样也会产生很多我们不再使用的长对话 。

通过深入研究seam对话,我们通过jsf事件机制来解决了上面两种问题,保证了对话的及时关闭

不需要操作者通过关闭操作来关闭对话(一般操作者也不会听你的话去点关闭操作,对他来说这个步骤是多余的)

public class SeamConversationPhaseListener implements PhaseListener{
 /**
  *
  */
 private static final long serialVersionUID = 1L;

 public void afterPhase(PhaseEvent event) {

  System.out.println("--Conversation.size:"+ConversationEntries.getInstance().size());
 }

 public void beforePhase(PhaseEvent event) {
  if(event.getPhaseId()==PhaseId.RENDER_RESPONSE){
   endLongConversationEntryList();
   isInLongConversation(Pages.getCurrentViewId());
  }
 }

 public PhaseId getPhaseId() {
  return PhaseId.ANY_PHASE;
 }

 

//将不需要恢复的长对话结束

public void endLongConversationEntryList()
    {
  String currentConversationId=org.jboss.seam.core.Conversation.instance().getId();
       ConversationEntries conversationEntries = ConversationEntries.getInstance();
       if (conversationEntries==null)
       {
          return ;
       }
       else
       {
          Set<ConversationEntry> orderedEntries = new TreeSet<ConversationEntry>();
          orderedEntries.addAll( conversationEntries.getConversationEntries() );
          for ( ConversationEntry entry: orderedEntries )
          {
             if ( !entry.getId().equals(currentConversationId)&&!entry.isDisplayable() && !Session.instance().isInvalid() )
             {
                ConversationEntries.instance().removeConversationEntry(entry.getId());
             }
          }

       }
    }

//点击需要恢复的长对话菜单会转到已经存在的长对话,与直接在工作区里点击对话的效果一样
 public boolean isInLongConversation(String viewid){
  ConversationEntries conversationEntries = ConversationEntries.getInstance();
       if (conversationEntries==null)
       {
          return false;
       }
       else
       {
          Set<ConversationEntry> orderedEntries = new TreeSet<ConversationEntry>();
          orderedEntries.addAll( conversationEntries.getConversationEntries() );
          int count=0;
          ConversationEntry firstEntry=null;
          for ( ConversationEntry entry: orderedEntries )
          {
             if ( entry.isDisplayable() &&entry.getViewId().equals(viewid)&& !Session.instance().isInvalid() )
             {
              count++;
              if(count==1){
               firstEntry=entry;
               
              }else{
               ConversationEntries.instance().removeConversationEntry(firstEntry.getId());
               entry.select();
               return true;
              }
             }
          }

 

       }
  return false;
 }


}

 

如果同一功能需要不同的对话,比如同样的列表查询我们要保留不同的查询条件,这样就要根据具体需求来修改 isInLongConversation方法。

最后我们还剩下一些长对话没有关闭,这必须要操作者的参与才能完成的,就像操作者打开来多个窗口,他必须手工来关闭,我们可以在工作区中的对话列表上增加关闭对话的操作,就像操作者要关闭窗口一样。

 

 

分享到:
评论

相关推荐

    Seam框架文档简述

    Seam扩展了Java Servlet规范中的上下文模型,引入了对话上下文和业务流程上下文的概念。这些上下文扩展有助于更好地管理组件的状态。 ##### 5. 双向注射(Bijection) Seam使用Java 5的注解实现了双向注射机制。...

    jboss seam 教程

    - **理解Seam对话**:深入探讨了Seam对话机制的工作原理及其在多步骤交互中的应用。 - **Seam UI控件库**:介绍了一套专门为Seam设计的UI控件,用于增强用户界面的功能性。 - **Seam调试页面**:提供了一个调试工具...

    seam的注解和标签

    在Seam中,对话范围允许在多个页面之间共享数据,直到对话结束。 - `&lt;s:property&gt;`: 在JSF视图中,这个标签用于显示由Seam管理的组件的属性值。 - `&lt;s:form&gt;`: 是Seam提供的增强版的JSF表单标签,它可以自动处理...

    seam_in_action

    - **生命周期管理**:Seam 对应用程序的生命周期进行了细致的管理和控制,支持多种不同的生命周期模式,如对话式、会话式等。 - **绝对控制反转**:Seam 引入了绝对控制反转(Absolute Inversion of Control, AIOC)...

    jboss seam 学习资料,seam in action和官方手册

    **JBoss Seam 学习资源概述** JBoss Seam 是一个开源的应用程序框架,它整合了JavaServer Faces (JSF)、Enterprise JavaBeans (EJB)、Java Persistence API (JPA) 和其他Java EE技术,旨在简化开发过程,提高开发...

    SEAM 中文开发指南

    - **理解Seam业务对话**:通过对话管理来控制业务流程。 - **Seam的UI控制库**:提供了一组用于 UI 控制的组件。 - **Seam调试页面**:用于辅助开发者进行调试和问题定位。 ##### 1.7 使用Seam和jBPM的完整示例:...

    JSF项目中seam的配置

    在JSF项目中配置Seam,可以充分利用其优势,如组件管理、对话管理、事件处理等。 首先,配置Seam的关键在于以下几个方面: 1. **阶段监听器配置**:在`faces-config.xml`中添加`SeamPhaseListener`。这是Seam启动...

    seam参考手册中文版

    - **宾馆预订系统**: 一个较为复杂的Seam应用实例,涵盖了多种Seam特性,如业务对话、UI控件等。 - **DVD商店**: 展示了Seam与jBPM的集成,以及如何构建业务流程驱动的应用程序。 - **IssueTracker**: 介绍了Seam...

    seam_carving 代码实现 seam

    **Seam Carving 技术详解** Seam Carving,又称图像拉链,是一种基于能量最小化的图像调整方法,主要用于图像大小的动态调整,而不仅仅是简单的等比例缩放。它能够在保持图像主要结构不变的情况下,根据需要增加或...

    为Seam做好准备

    "为Seam做好准备"这个标题暗示我们即将探讨的是关于Seam框架的入门与准备工作。Seam是一个Java EE集成框架,它将JavaServer Faces(JSF)、Java Persistence API(JPA)、Enterprise JavaBeans(EJB)3.0以及其他...

    JBOSS SEAM组件中文手册

    **JBoss Seam组件中文手册** **一、Seam框架概述** Seam是一个开源的企业级Java框架,由JBoss公司开发,旨在简化Java EE应用程序的开发。它将多种技术如JavaServer Faces (JSF),Java Persistence API (JPA),EJB 3...

    MATLAB_Seam_Carving_seamcarving_

    MATLAB_Seam_Carving_seamcarving_ 是一个与图像处理相关的项目,主要涉及到一种称为“seam carving”的技术,这是一种动态图像调整大小的方法,它可以在不改变图像整体视觉效果的情况下,增加或减少图像的宽度和...

    Jboss Seam中文版

    6. **使用Seam工作空间管理的完整范例:IssueTracker**:介绍了一个问题追踪系统的实现过程,强调了Seam在多用户协作方面的优势。 7. **结合Seam和Hibernate的范例:Hibernate系统**:展示了一个利用Seam和Hibernate...

    近两个星期seamtest的学习

    在过去的两周里,我深入学习了SeamTest,这是一个用于Java EE应用测试的强大...在实际使用过程中,遇到的问题和错误是学习过程的一部分,通过解决这些问题,我们可以更深入地理解SeamTest和Seam框架的内部工作原理。

    jboss-seam2.0文档

    `fwvv.net说明.txt`可能是指向Seam社区或者论坛的链接,那里有开发者分享经验、解决问题的讨论,也是获取最新资讯和更新的重要来源。 总结,JBoss Seam 2.0是一个强大的开发框架,它通过集成多种Java EE技术,提高...

    JbossSeam中文开发指南.docx

    Seam对话是一个基于对话的编程模型,能够帮助开发者快速构建企业级应用程序。Seam对话提供了一个统一的编程模型,能够将JSF、EJB、JPA等技术整合在一起,提供了一个强大且灵活的开发环境。 Seam工作区管理 Seam...

    seam需要的jar包

    Seam框架是一个全面的Java企业级应用开发框架,它整合了JSF(JavaServer Faces)、EJB、CDI(Contexts and Dependency Injection)以及许多其他Java EE技术,为开发者提供了强大的组件模型和丰富的功能,旨在简化...

    JBoss Seam入门介绍

    Seam扩展了Servlet规范中的三个上下文(请求、会话、应用程序),引入了两个新上下文:对话(conversation)和业务流程。这一特性允许开发者以声明式的方式管理组件状态,简化了复杂应用的开发。 #### 5. Bijection...

    Seam Carving的C++实现代码

    Seam Carving是一种图像内容感知的尺寸调整方法,它能够在保持图像主要结构不变的情况下,智能地减少或增加图像的宽度和高度。这种方法是由Amit Agarwal和Matthieu Salzmann于2007年提出的,其核心思想是通过找到...

Global site tag (gtag.js) - Google Analytics