Chinaunix首页 | 论坛 | 博客
  • 博客访问: 821048
  • 博文数量: 754
  • 博客积分: 7000
  • 博客等级: 少将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-12 12:54
文章分类

全部博文(754)

文章存档

2011年(1)

2008年(753)

我的朋友
最近访客

分类:

2008-09-12 13:09:47

     Apache MyFaces项目提供了以下的功能:     Server Faces的实现(MyFaces API和MyFaces Impl模块)     用于构建JSF相关的web应用程序的组件库,例如MyFaces Tomahawk、MyFaces Trinidad、MyFaces Tobago。
     Server Faces扩展包,例如MyFaces Orchestra。
     与其他技术和标准的集成模块。(用于开发移动客户端,在本文和后续文章中对这部分功能不进行介绍。)     可以在如下位置和MyFaces Impl及其各个子项目的发布包及样例程序。MyFaces API在JSF的子项目中,Core子项目视JSF规范的一个实现,其他的项目实现了相关的规范,例如Portlet Bridge,或者为其他的JSF实现添加了扩展,注意,不仅仅是MyFaces Core。同时,MyFaces的扩展,例如Tomahawk,可以和任意的JSF实现协同工作,例如Sun Reference Inplementation。
     MyFaces Core1.1.x可以在Tomcat 5.5下工作,但是MyFaces Core 1.2.x要求 Tomcat 6.0环境。
     MyFaces项目不依赖于其他的项目。它是一个独立的程序。

        JSF FAQ     1.     javax.faces.STATE_SAVING_METHOD的值为client和server时的区别?     简而言之,server端状态降将UI组件的持有的信息在HTTP Session中保存,而client状态将UI组件持有的信息保存在返回给用户的页面的隐藏域(hidden field)。
     client端状态对于非常大数量的用户来说比较实用,因为不需要在端保存用户的状态,从而节省了内存。但是缺点是在网络中为每个请求传送了更多的数据。
     即使选择的是client端状态,任何一个session-scoped实体仍然存在于http session中,这个标记只是影响JSF实现将UI组件持有的数据存放在什么位置。
     任何实现了StateHolder的组件,必须实现saveState(FacesContext)和restoreState(FacesContext, Object)方法,来帮助JavaServer Faces Implementation来保存和恢复跨越多个请求的组件的状态。
     为了设置值,必须实现saveState方法。这个方法在render响应阶段被调用,在这期间响应的状态被设置,用来处理后需的请求。下面是MapComponent组件的该方法的实现:
     public Object saveState(FacesContext context)
{        
Object values[] = new Object[2];
         values[0] = super.saveState(context);
         values[1] = current; 
        return (values); 
    }
     该方法初始化了一个数组,用来持有保存了的状态,然后保存所有与MapComponent关联的状态的所有内容。
     实现StateHolder的组件必须提供restoreState方法,该方法用来恢复保存在saveState方法中保存的组件的状态。restoreState方法在恢复视图阶段被调用,在此期间,JavaServer Faces Implementation会检查是否在最后render response阶段保存了状态,并判断是否需要恢复,以便进行下次的后退。下面是MapComponent组件的restoreState方法。
     public void restoreState(FacesContext context, Object state)
{        
Object values[] = (Object[]) state; 
         super.restoreState(context, values[0]); 
        current = (String) values[1]; 
    }    
该方法的参数为FacesContext和Object实例,表示组件状态的数组。这个方法将Object数组中保存的数据进行设置。
     当在自定义的组件类中实现这些方法时,确保在部署描述符中指定了需要将这些状态保存在哪里,即client还是server。如果状态时保存在client,整个视图的状态都被提供给页面的一个hidden field。
     可以通过设置javax.faces.STATE_SAVING_METHOD上下文参数(context-parameter)。
     2.     浏览器总是显示一个到上一个页面的链接?
     默认情况下,JSF在内部使用forward操作来在页面之间导航。
     所以当一个用户首先访问页面A,然后取回一些内容。这些内容会被包装在表单中,表单以页面A作为提交的地址。
     当用户接着执行操作,提交页面,这时JSF收到post请求,回复页面A的视图,并执行postback处理。作为postback处理的一部分,页面A的逻辑可能通知JSF框架应该显示页面B。
     默认情况下,JSF会执行一个内部forward到页面B,使页面B被取回,作为用户提交表单的结果。
     这时用户在屏幕上看到页面B。但是浏览器只知道它将数据发送给了页面A,所以,浏览器导航栏上显示的URL是页面A的URL,虽然显示的内容是页面B。不幸的是,HTTP/HTML不能使浏览器知道应该显示页面B的URL。因此,作为JSF的默认行为,浏览器的URL经常是实际显示内容的页面的上一页。
     不仅仅对于用户来说是奇怪的,同时加入收藏夹的时候也比较困难,注意,收藏夹的位置一般来说是没有关系的。因为JSF应用程序通常是可交互的,并且是状态丰富的。
     另外一个缺点是在JSF视图中使用关联链接是不的。(例如样式表的相对路径或者图标)。当浏览器提交内容到A,并获取数据共页面B使用时,在返回页面中的relative links都会被作为相对于它(浏览器)所知道的最后的url。所以第一次查看页面B时,所有相对链接都是相对于页面A的,如果A和页面B不在一个目录中,那么就会出现问题。
     这个问题的一个解决办法就是使用标记来定义导航规则。这样,会使用http redirect命令来告诉浏览器获取新页面,从而取代执行内部的forward。 但是,这样做效率比较低,因为浏览器需要使用第二次请求来获取它的内容,而不是在针对初始的post请求,在响应时立即获取它的内容。另外一个重要的问题就是,获取页面B的内容是在一个单独的请求中,这样就没有办法从A页面中传递任何的请求范围(request-scoped)数据,在这样的目的使用request范围的变量非常方便,也是很常用的。
     Tomahawk sandbox库中包含了s:redirectTracker组件,可以临时将request-scoped变量保存在http session中,这样使用规则就可以在不丢失request范围变量的情况下使用,但是这要求存在http session,并且效率低下。
     MyFaces FAQ
     1.     什么是shared项目?
     如果myfaces-core、tomahawk、tobago、trinidad都是完全独立的项目,那么就不需要shared代码项目,每个项目都在各自的名称空间内维护代码。但是,会存在大量的重复代码,并且工作量的浪费。因为它们都属于myfaces项目,所以多个子项目可以共用的代码放在shared项目中,以便减少开发和维护的工作量。
     但是,这些子项目又都有各自的独立释放周期。并且,tomahawk/tobago/trinidad都应该运行在任意的JSF实现上,而不仅仅是myfaces-core。目前使用的解决办法是重命名shared的类的报名。代码被重命名成org.apache.myfaces.shared_impl、org.apache.myfaces.shared_tomahawk等等。这样每个子项目就可以在发布的时候包含所有的支持类,而不是一个独立的共享jar文件,也不需要关心相同类的定义的冲突。对于特定项目的升级不会影响到相同环境下的其他项目。
     注意最近的MyFaces项目的释放都是用了shared库,并在源代码的jar文件中包含了shared项目的源代码,所以不需要添加额外的源代码jar文件
。     2.     如何从MyFaces获取格式良好的HTML输出?
     JTidy项目提供了一个ServletFilter,可以将响应的消息在输出前进行重新的格式化。Mozilla Firefox浏览器提供了一个扩展的View Formatted Source功能。
     在一些版本的MyFaces中,可以通过设置org.apache.myfaces.PRETTY_HTML来在web.xml文件中启用pretty输出。但是,这个选项从来都没有被很好的支持,因为需要所有的renderer来支持,以便其工作。可能在以后的MyFaces发布中移除。
     3.     MyFaces Core和tomahawk发布包中的版本号表示什么?
     MyFaces Core使用三个部分来表示版本,例如1.1.1。但是这个值和普通的版本号计数是不同的。强两个数字表示了JSF规范的版本。因为二进制的JSF规范的API没有改变,前两位数字相同的发布包被认为是兼容的,所有使用JSF指定特征的既存代码会同样可以使用。
     Tomahawk库也适用相同格式的版本号。但是因为JSF 1.2规范是向后兼容的,即兼容JSF 1.1规范,所有Tomahawk发布的版本中,1.1.x同样可以工作在JSF 1.2上。注意,tomahawk释放不保证二进制向后兼容。
     4.     为什么DataModel不是可序列化的?
     DataModel类(在UIData组件中使用)在显示和恢复视图阶段不需要保存任何任何状态。因此,不需要将它定义为可序列化的。
     如果需要定义可序列化的managed bean,并且它包含一个DataModel类型的成员变量,那么将成员变量定义为transient。
     5.     为什么时间显示不正确?
     JSF规范要求默认的date->String转换器使用标准的UTC时区,也叫做GMT时区。
     MyFaces 1.1.0或者早期的发布并没有遵循JSF规范,它们默认的使用了的时区。     可以通过显示试用转换器来进行时区的控制,例如:
          或者          #{bean.timeZone}返回字符串id或者TimeZone实例。
     当然,也可以注册自定义的converter来覆盖标准的converter,使自定义代码适用于所有的时间到字符串的转换。
     6.     如何在一个managed bean中访问另外一个managed bean?
     有两种方法来实现访问同一个webapp中的其他managed bean:
     使用依赖注入:在faces配置文件中定义managed beans,managed bean的属性可以被声明成到其他managed bean的引用:
             neededBean        fqn.to.NeededBean        session     

                 usingBean        fqn.to.UsingBean        request                  neededBean          #{neededBean}             
     限定条件如下:
     using bean必须的生命周期小于或者等于被引用的needed bean     using bean必须具有setter方法,以needed bean作为参数     beans不能管理彼此的依赖。
     使用查询机制:下面的代码可以在MyFaces 1.1中来显示的通过名字查询任意的managed bean。
     FacesContext facesContext = FacesContext.getCurrentInstance();
     NeededBean neededBean 
        = (NeededBean) facesContext.getApplication() 
            .getVariableResolver().resolveVariable(facesContext, "neededBean");
     在MyFaces 1.2中,不使用上述的方法,而是推荐使用:
     ELContext elContext = FacesContext.getCurrentInstance().getELContext();
     NeededBean neededBean 
        = (NeededBean) FacesContext.getCurrentInstance().getApplication()  
           .getELResolver().getValue(elContext, null, "neededBean"); 
    同样,可以使用这个代码来计算任意的JSF表达式:
     FacesContext facesContext = FacesContext.getCurrentInstance();
     NeededBean neededBean
         = (NeededBean)facesContext.getApplication()
           .createValueBinding("#{neededBean}").getValue(facesContext);
  

[1]   

【责编:landy】

--------------------next---------------------

阅读(631) | 评论(0) | 转发(0) |
0

上一篇:闭包会简化Java吗

下一篇:java 常用IO操作

给主人留下些什么吧!~~