使用JSF框架过程中的若干典型问题及其解决方案

时间:2023-03-10 03:04:58
使用JSF框架过程中的若干典型问题及其解决方案

1.commandXxx点击后,不调用action中的方法:

原因1:xhtml后缀名的文件,最终也会转化为普通的html文件(这是熟悉JSF框架的关键。),commandXxx点击后不调用后台action属性的原因是:当前的commandXxx组件在嵌套的表单里面,而html不支持表单嵌套,所以,点击commandXxx组件后,action属性没调用后台方法。

解决办法:看情况地去掉一层表单。即<h:form>...</h:form>

总之,无论如何,必须去掉一层,否则,action属性必定不会调用后台Bean的方法,因为严格意义上来说,当前的xhtml文件中有语法错误。

原因2:当前的commandXxx组件没有放在form表单标签里面,这样也会出现commandXxx组件不调用后台方法。

原因3:当前组件写了immediate="true"这个属性。

解决办法:如果当前被点击的组件要调用后台方法(注意:是调用后台方法,而不是传值到后台),那么就不能为该组件添加immediate="true"这个属性。

2.当前表单中有个对话框D,D中有一个显示数据的UI组件,点击按钮(链接)B后,弹出对话框,显示相应的数据。数据显示正常。当第二次点击按钮(链接)B弹出该对话框时,对话框的UI组件里的数据显示部分或者全部不显示:

原因:不是特别清楚。总之应该是表单验证的问题。

解决办法:给当前按钮(链接)B加个属性:immediate = "true".

3.点击commandXxx组件后,后台方法能够正常调用,但是,当通过这个组件传对象到后台时,后台得到的对象的信息不全,也就是说,后台得到的对象中,有部分信息是前端传过来的对象的信息,但还有部分信息是Java数据类型的默认值。

解决办法:给当前组件添加属性:process="@this"属性。

4.在dataTable中传当前行的对象到后台的写法:

  1. <commandXxx action="#{后台View.要调用的方法名}" xxx1="..."  xxx2="..." ... >
  2.      <f:setPropertyActionListener value="#{当前dataTable的行变量,即dataTable的var属性的值}"
  3. target="#{后台View.一个用来存储当前行对象的所有属性值的对象}" /> //后台View的标准术语叫ManagedBean,中文俗称“托管Bean”,所有的删、改、查操作均可通过这个对象来完成。所以,后台只需要写一个这样的对象就行了。通过这种写法,后台方法可以不用写参数。
  4. </commandXxx>

5.关于更新页面的问题:

因为Primefaces的事件组件(即:commandXxx)已经封装好了ajax,所以,在点击commandXxx组件后,应该相应更新前端。

关于commandXxx组件的update属性的值常见的写法有如下几种:

①:update=“@form:要更新的组件的id”。这样写,你要更新的组件必须是form标签的子标签,否则,将无法更新,任何地方也不会给出错误提示。如果form标签和你要更新的组件的标签之间有div标签,也可以这样写。但是,如果有primefaces或者其他标签源的标签,将无法更新。

②:如果你要更新的组件是某个组件的子组件,那么,直接写update="@form:父组件的id"也是可以的。

③:如果要更新的组件不在任何一个form里面,那么,直接写update="要更新的组件的id"。

④:如果要更新的组件的和当前的commandXxx组件不在同一个form里面,那么,通过指定form的方式更新,即:update="@([id$=要更新的组件所在的表单的id]):要更新的组件的Id", 除了可以指定表单外,规则和①②一样。但是,这只是迫不得已的办法。因为这样做,点击commandXxx组件后,整个页面貌似都会刷新一下,不好。

⑤:这种方式是间接地做到刷新效果。

即:在当前的form内设置一个隐藏的按钮(通过JS的ready函数做到),同时设置好隐藏按钮的update属性,当某个必做的事件(如accordionPanel的tab被下拉)触发时,调用JS函数,JS函数中使用JQuery让隐藏按钮自动点击,以达到刷新的效果。

注意:这是所有刷新方式中最重要的一步:点击commandXxx组件后,调用后台相应的方法,如果要想在update之后改变前端的数据,那么,对应的后台的数据一定要做修改。也就是说,如果前端要更新的组件是dataTable或dataList等,当执行添加操作时,后台对应的集合一定要add当前被添加到数据库的对象.当执行删除操作是,后台对应的集合一定要remove当前被删除的对象。否则一切都是扯淡。原因:执行添加操作时,后台集合在内存中没有这个对象,就算你前端执行了update,update的结果仍然是那个没有添加新对象的集合,当然就不能把添加的对象立即显示在前端。同样,执行删除操作时,道理也一样。这也就是为什么很多时候,明明设置了update属性,可前端数据就是没有更新,偏要点击浏览器的刷新后才能更新数据。

同时,也说明一下,点击浏览器的刷新,相当于让整个程序重新跑。后台ManagedBean(即XxxView)的注释了@PostConstruct的方法会重新执行。时间不用一开始从后台跑起那么久的原因是:一开始需要先把tomcat容器跑起来。

6:对话框中再弹对话框屏幕一直处于灰色卡顿,除非手动刷新页面。

解决办法:给子对话框加个属性:appendTo="@(body)"

7:在JS代码中写了ready函数,但是当页面被加载时,ready函数里面的部分功能没实现。

原因:xhtml加载方式和普通的html文件加载方式一样,都是从上之下逐行加载。如果把<script>标签对写在所有html标签(这里把primefaces等标签通称html标签)上面,当页面被加载时,下面的html标签还没有被加载,这就导致ready函数中,需要用到下面的html标签的代码找不到相应的标签,当然也就得不到自己想要的效果。

解决办法:把<script>标签方法文件末尾。

8:JS中调用JQuery函数,但JQuery函数没有执行。

原因:因为JSF框架的原因,自己为组件设置id,最终被解释成普通的html时,id并不是自己定义的那个id,而只是最终id的后缀(通过查看源代码可以看出)。所以,JQuery选择器去获取DOM对象(也即那个标签)时,找不到相应的id,理所当然就不会调用JQuery函数。

解决办法:通过这种写法:$("[id='#{要执行JQuery函数的组件的bind属性的值.clientId}']").JQuery函数。注意:要执行JQuery函数的组件不仅要写id,而且一定要写bind属性值,否则,JQuery函数还是不会被正确调用。bind属性值就和id一样。clientId是固定的写法,通过查看页面源代码可以看出,我们在xhtml文件里面写的clientId,变成普通html代码后,要执行JQuery函数的组件的bind属性的值.clientId会被解释成组件的最终id.

9:修改了页面中某处的CSS后,刷新页面,CSS样式还是原来的。

原因:因为浏览器有CSS缓存效果,浏览器(Google Chrome)默认的刷新CSS的间隔为1小时,所以,改变了页面的CSS后,点击刷新,在页面上没显示。

解决办法:清除浏览器的网页缓存。如图:

使用JSF框架过程中的若干典型问题及其解决方案

注意:清除过程中,别把”清除所有Cookie“选项勾选了。否则,.........

10:经验:只要是能够被点击、能够从键盘输入的组件,无论点击后会有效果,都有onXxxx属性,设置这些属性,

可以调用JS函数,通过JS函数来达到自己的目的。即便不是可点击的组件,也有一些组件有onXxx属性,如果:onload,onshow,onclose。

11.后台:ManagedBean对应的View类中,所有类级成员变量必须写setter和getter。

本文属博主原创,转载请说明来源。