JSF和Facelets最佳实践

我使用的是jsf1.2在使用后总结了一些经验:


一.不要在get/set方法中写入任何逻辑,只写简单的赋值和取值,而是把逻辑写到Action中去(除非你有非常充分的理由)

原因:

1.get和set方法不会仅调用一次,而会多次调用,例如以下代码中的get方法就会被调用两次,如果你在get方法中写入查询数据库的逻辑那么会运行多次,产生多条查询语句,

 

 

      


2.不能保证在还原视图时只调用set方法同样也不能保证在呈现视图时只调用get方法,例如以下代码中会在还原视图时调用get方法:

 

3.如果在get/set中写入的逻辑中出现的异常会使代码看起来难以理解,因为如果在还原视图时发生了异常JSF会不调用Action方法,而去呈现视图,而且在set时发生的异常也不方便处理。

二.BackingBean不应该按页来定义(即不应该一个jsp/xhtml页一个BackingBean)而应该按功能来划分BackingBean

原因:如果按页来划分BackingBean那么会生成大量的重覆代码,这样违反的DRY原则,而这是代码的坏味道中最坏的实践。

三.功能BackingBean应尽量定义为request范围的,而那些须要为session的BackingBean应从功能BackingBean中抽取出来定义一个session范围的backingBean再注入到request范围的功能BackingBean中去。

原因:

     1.JSF是不允许在一个session范围的Bean中注入一个request范围的Bean的(准确的说是不允许把一个生命周期短的Bean注入到一个生命周期长的Bean中,这么设计的原因用心想想就明白了),如果你把一个BackingBean定义为session时,那么在你发现它要注入别的BackingBean时那么会发现这个Bean也必须定义成session,这样会导致项目中的Session范围的Bean以几何数量增加。

     2.如果你使用Hibernate的话,而且还使用的OpenSessionInView那么如果你的BackingBean为session的话,那么你不可避免的遇到Hibernate的延迟加载错误(no session or session was closed),这样又要写好多代码还处理这种情况,而且有时可能不容易发现,而是在不确定的时间莫名奇妙的出现来刺激你的神经,要是你使用request范围的功能BackingBean的话,那么就没有这些烦脑了,因为你的BackingBean和Hibernate的session的生命周期是一样的。

四.能使用Facelets自定义组件就不使用ui:include

原因:

    因为Facelets自定义组件有一份配置文件,这样就方便了以后的重构,想像一下如果你要把你的一个页面改名,并且要把它从一个目录移至另一个目录,如果你使用的是facelets自定义组件,那么只要改一下配置文件就可以了,而如果你使用的是ui:inclued方式的呢?

    另外Facelets可以有多分自定义组件配置文件,这样方便了项目中的功能划分,而且可以在这份配置文件中注解这个组伯的用法,及应有的属性.

 

五,自定义组件要传递一个backingBean为参数的话,那么为这个BackingBean定义接口

 

原因:

    因为Facelets不可以将一个BackingBean的Action方法做为属性传递给Facelets自定义组件,所以有的时候需要为Facelets自定义组件传递一个带有Action方法的BackingBean做为属性,这时候为这个BackingBean定义一个接口并在Facelets组件定义的配置文件注明要使用这个组件要实现XX接口,那么以后要使用这个Facelets自定义组件的话就不用到页面中去查找自已的Bean要定义那些方法了。   

 

 

 

 

 

六.Facelets组件一定要使用ui:composition/ui:component

 

 

 

原因:

      在使用ui:inclue方式时你的页面可以不定义ui:composition/ui:component,而且在一些浏览器中也没有问题发生,但是要记住加入这个定义,因为如果不加那么会把你定义的页全部引用到页面中去,包括<html>和之前的定义,这样页中就会出现<html>中又嵌了一个<html>及页面定义,而这样的页在某些浏览器中是不允许的,如google的chrome就会出错:XML declaration allowed only at the start of the document(大该是基于安全性的考虑),但是在IE和fireFox中就没事。

 

 

七.一定要为你的Facelets自定义组件加个id属性,并在Facelets自定义组件内部所有要自定义一个ID的JSF组件的id加上此自定义ID,包括定义的js方法名,如:<h:inputText id="name_input_#{uuid}"/>

 

原因:

      因为你的Facelets自定义组件有可能会在一个页面出现多次,如果你不这么做的话,会报ID重覆的错误,但有时也可使用<f:subview/> 来解决这个问题,但是有也<f:subview> 也是不行的,如你使用了非jsf组件,或js方法名,再或者你使用了<rich:modalPanel/>.

 

 

 

     

八.Facelets自定义组件内最好不要出现From,而在应该使用Form的地方使用<a4j:region/>(如果你使用a4j的话)

 

原因:

      因为Facelets自定义组件内并不知道自已是否已在一个Form内了,如果已经在Form内的话会出现From的嵌套,这样在外层Form提交时可能会遇到麻烦。所以最好在Facelets自定义组件内都不定义Form,在组件的说明中注解此组件需要一个form,而由引用页统一加入Form并决定Form的大小。

 


九.Facelets定义组件功能要小要独立,然后在定义大的功能组件中引用这些小的功能组件

 

原因:

      这么做会加强组件的重用

十.在页面含有逻辑时使用<c:set>

原因:

      虽然说要把页面显示逻辑写入到BackingBean中去,但因为有<c:if />,<c:forEach/>的存在,使的页面中也可能存在少量的逻辑,这时候应该使用<c:set/>将这些少量的逻辑集中到一起,以符合DRY原则,如:

 

改为:

 

 

 

总结:所谓规律就是用来打破的,况且以上几点只是我在使用时的几点经验,如果你在开发中有足够的理由的话,那么请直接无视以上几点,但在做之前最好想一下你的理由是否足够冲足,并且你有方法回避我所说的可能会出现的问题。

 

以上纯属个人观点,示例的代码也是一时之间随意敲的,并末测试只为表达意思,有错误怪。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值