Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 678|回复: 0

JSF生命周期及AJAX局部刷新

[复制链接]

该用户从未签到

发表于 2011-10-17 19:29:04 | 显示全部楼层 |阅读模式
这些时间可能一直得搞JSF...... 呵呵,这个星期天再一次的仔细的研究了一下这个所谓的6个生命周期的运行情况以及所谓的AJAX局部刷新的问题.

        看了core JSF里详细描述的JSF的生命周期,基本上可以划分为六个周期.

        1:Restore View(恢复视图)

        所谓的视图也就是一些基本的GUI组件.也就是常说的HTML控件吧.视图一般来说分为三种实例:新视图,原始视图,后视图三种.所谓的新视图就是你第一次请求所呈现给你的.而原始视图也就是你已经进入了这个页面.只是刷原有页面.而后视图呢也就是你点后退按钮回到的那个页面.(它只负责从恢复内容,不刷新内容.)Restore View phase recreates the server-side component tree when you revisit a JSF page.

        2;Apply Request Values(应用请求值)

        在这阶段主要数据接收.SUN在自己出版的core JSF中是这样说的.The Apply Request Values phase copies request parameters into component submitted values.

        3rocess Validations(执行验证)

         根据接收到的数据进行转换验证.The Process Validations phase first converts those submitted values and validates the converted value.

        4:Update Model Values(更新模型)

        开始给控件赋新值.The Update Model Values phase copies (converted and validated) values to the model, which is typically denoted in JSF pages with value reference expressions

        5:Invoke Application(调用程序)

        这个阶段主要进行actionListener 和 action 处理.先调用ActionListener 然后再进行Action 操作.The Invoke Application phase invokes action listeners and actions, in that order, for command components.

        6:Render Respose(进行响应)

         返回一个新的请求视图.the Render Response phase saves state and loads the next view.从下图你能清楚的知道JSF的六个生命周期是如何的运行的.

        在下面的测试中,你需要对faces-config.xml: 进行如下的设置:

<lifecycle>
  <phase-listener>net.emlog.fei.PhaseEventListener</phase-listener>
</lifecycle>

        在实现生命周期的监听的时候,你需要编写一个生命监听的类.PhaseEventListener他实现了javax.faces.event.PhaseListener接口.在这个接口中,需要实现这两具方法beforePhase(PhaseEvent e)和afterPhase(PhaseEvent  e).需进行后台的bean则显得简单.

       大体的,你可以根据以下几个值来更改生命周期的执行.(1).immediate="true"(2)调用FacesContext.renderResponse()(3):调用FacesContext.responseComplete()这三者是有一定的区别的.

      正常运行的情况下,它的生命周期是这样进行的:
        开始调用 APPLY_REQUEST_VALUES 2事件.
        然后,APPLY_REQUEST_VALUES 2事件响应了
        开始调用 PROCESS_VALIDATIONS 3事件.
        在getInput方法中得到input值为123
        值改变事件发生,开始设置input值为1
        在setInput方法中设置input值为1
        在setOutput方法中设置output值为1
        然后,PROCESS_VALIDATIONS 3事件响应了


  如下面的代码片段没有使用局部刷新)

          <h:form id="form">
            <h:inputText id="input" value="#{vcl.input}" valueChangeListener="#{vcl.changeAction}"
             immediate="true" onchange="submit()">
     
            </h:inputText>
            <hutputText id="abs" value="#{vcl.output}"></h:outputText>
   
           </h:form>

        public void changeAction(ValueChangeEvent vc){
                  /**
                   * FacesContext fc = FacesContext.getCurrentInstance();
                  UIViewRoot root = fc.getViewRoot();
                  String locale = vc.getNewValue().toString();
                  root.setLocale(new Locale(locale));
                 */
  
                  String string = vc.getNewValue().toString();
                  System.out.println("值改变事件发生,开始设置input值为" + string);
                  setInput(string);
                  setOutput(string);
                  FacesContext fc = FacesContext.getCurrentInstance();
                  //fc.responseComplete();
                  //fc.renderResponse();
         }

        上面的方法中,由于将immediate设为true,所以它会将
        开始调用 APPLY_REQUEST_VALUES 2事件.
        在getInput方法中得到input值为123
        值改变事件发生,开始设置input值为1
        在setInput方法中设置input值为1
        在setOutput方法中设置output值为1
        然后,APPLY_REQUEST_VALUES 2事件响应了
        开始调用 PROCESS_VALIDATIONS 3事件.
        然后,PROCESS_VALIDATIONS 3事件响应了.

        仅仅将immediate设置为true用户不大的.因为最后他还是要走完所有的六个生命周期.我们结合FacesContext.renderResponse() 和FacesContext.responseComplete()来看看他们有什么区别.

        FacesContext.responseComplete()情况:
        开始调用 APPLY_REQUEST_VALUES 2事件.
        在getInput方法中得到input值为123
        值改变事件发生,开始设置input值为1
        在setInput方法中设置input值为1
        在setOutput方法中设置output值为1
        然后,APPLY_REQUEST_VALUES 2事件响应了(后面没了,它甚至不会Render Response)所以你会看到一个空白的页面.

        FacesContext.renderResponse() 情况就不同啦:

        开始调用 APPLY_REQUEST_VALUES 2事件.
        在getInput方法中得到input值为123
        值改变事件发生,开始设置input值为1
        在setInput方法中设置input值为1
        在setOutput方法中设置output值为1
        然后,APPLY_REQUEST_VALUES 2事件响应了
        开始调用 RENDER_RESPONSE 6事件.
        在getOutput方法中得到output值为1
        然后,RENDER_RESPONSE 6事件响应了(相对于responseComplete()他进行了Render Response操作.)OK.希望说到这你能对所谓的六大生命周期有一个简单的认识.如何我们只是进行一次简单的WEB开发的话,那么,关注3,5两个阶段的实现就可,如果需要自己编写UI,则需要对生命周期有一个清楚的认识.也许,从下面的图你能看得更加的清楚.

        当然,我们的重点还是在于局部刷新.AJAX是一个时下比较时兴的技术.局部刷新有很多的好处,在此不在细说.在上面的例子里,我们需要实现在输入框里的值改变后,输入框的值也随着改变.但是我们调用的却是全局刷新.使用submit()事件来实现.接下来我们就来看看如何使用AJAX来实现局部刷新,以及局部刷的一些细节问题.如下代码段:具体的richfaces请参见        http://labs.jboss.com/jbossrichfaces/此处不细说配置.

        <h:inputText id="input" value="#{vcl.input}" valueChangeListener="#{vcl.changeAction}">
            <a4j:support event="onchange" limitToList="true" reRender="input,abs"/>
      </h:inputText>   
      <h:outputText id="abs" value="#{vcl.output}"></h:outputText>

        OK.运行代码后,我们发现结果是这样的:
        开始调用 APPLY_REQUEST_VALUES 2事件.
        在getInput方法中得到input值为123
        值改变事件发生,开始设置input值为1
        在setInput方法中设置input值为1
        在setOutput方法中设置output值为1
        然后,APPLY_REQUEST_VALUES 2事件响应了
        开始调用 RENDER_RESPONSE 6事件.
        在getOutput方法中得到output值为1
        然后,RENDER_RESPONSE 6事件响应了

        在应用值及进行响应阶段我们只是对output进行了响应.虽然在reRender设置了两个响应目标.但实现上如你所现,真正响应的只是output控件的get方法.同样的,在值改变事件前,也只是对input控件进行了get响应.这两个很重要.这也就是说.如果在两个都为input控件的时候,事件就有点复杂.因为set事件 他所取的时input = string 参数string是取决于你显示出来给用户的.正因为如何,当两个事件都进行响应的时候,两个输入控件的值是不一样的.在同为input的时候,我们需要加上<a4j:region>在开发文件中的定义是这样的:The <a4j:region> component defines an area that is decoded on the server after Ajax submission.当然.在有两个input控件的情况下,你需要按照以下形式编写.

   <a4j:region>
    <h:inputText id="input" value="#{vcl.input}" valueChangeListener="#{vcl.changeAction}">
     <a4j:support event="onchange" limitToList="true" reRender="input,abs"/>
    </h:inputText>
   </a4j:region>
    <h:inputText id="abs" value="#{vcl.output}"></h:inputText>

        这样我们就能保证在进行局部刷新提交的时候,不会将后一个input的值也提交上去,从而实现同时改变的功能.希望说到这你能明白些什么.生命周期的运行是这样的:在有事件响应的时候,只会有输入控件的get方法.在返回响应的时候,只会调用输出控件的set方法.嗯,就是这样的.

        OK.基本上完毕了.还记得开始时说的那个恢复视图里的后视图吗?这个东西他是不刷新的.如果我在后面修改了怎么办呢,返回来的结果并不会在后视图里显示出来.有两种方法,一种是页面不缓存...另一种则是载入页面的时候进行刷新.我选择了第二种.第一种有点不有好...不过对于一些很重要的权限控制还是用第一种吧.第二种的处理方法是在页面的load事件里加上javascript的刷新页面代码.经测试,下面这个代码是可行的.
function refresh(){  if(self.name != "index.faces"){
                 self.name = "index.faces";
                self.location.reload();
             }
  else{
              self.name = "";
          }
}

        但是如何在你的第一个页面里也有第二个页面的功能.则第二个页面的功能在第一个页面功能被使用后不再有效.这个是由jsf的生命周期决定的.没有找到什么好方法来解决.下图为JSF与AJAX在一起的处理流程.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-5-5 20:53 , Processed in 0.365193 second(s), 38 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表