终于到本文的最后一节了,本节内容主要讲JSF也是面对接口编程的,作者举了个简单的例子。然后在JSF安全问题上,使用了类似于ASP.NET的viewstate概念的东东。最后谈到了头痛的Portlet程序开发问题,作者指出Portlet问题远不止这些,而且问题都出在Portlet本身,非常同情Portlet开发人员。
基于接口编程
JSF鼓励“包含与扩展”的设计原则。因此JSF组件模型广泛基于接口。下面的这个例子中,“ImplementationDependentManagedBean.java”却没有使用接口。好吧,我需要对它做些小小的修正。
import org.apache.myfaces.component.html.ext.HtmlInputHidden;
import org.apache.myfaces.component.html.ext.HtmlInputText;
import org.apache.myfaces.component.html.ext.HtmlOutputText;
public class ImplementationDependentManagedBean {
private HtmlInputText input ;
private HtmlInputHidden hidden ;
private HtmlOutputText output ;
/* 省略getters和setters方法 */
public boolean recordTotal(ActionEvent event) {
long total = ((Long)input.getValue()).longValue();
total += ((Long)hidden.getValue()).longValue();
total += ((Long)output.getValue()).longValue();
return new JmsUtil().broadcastTotal(total);
}
}
这个bean绑定了三个组件作为其属性,业务逻辑部分将这三个组件封装到一个action listener里去了。(action listener指的就是这里的recordTotal方法)。这三个类(这里指的是HtmlInputText,HtmlInputHidden,HtmlOutputText)都是MyFaces包自带的。这段代码中需要注意的是这个类的业务逻辑部分recordTotal方法只会调用每个组件的getValue方法。而通过JSF的API,你又会发现这些组件的getValue方法又承继于它们的父类。因此我决定要重构一下代码,将这几个导入的包给换掉:
import javax.faces.component.ValueHolder;
public class RefactoredManagedBean {
private ValueHolder input ;
private ValueHolder hidden ;
private ValueHolder output ;
/* getters & setters ommitted */
public boolean recordTotal(ActionEvent event) {
long total = 0;
for(ValueHolder valued : new ValueHolder[] {input, hidden, output})
total += ((Long)valued.getValue()).longValue();
return new JmsUtil().broadcastTotal(total);
}
}
现在我要说一下,ValueHolder是HtmlInputText, HtmlInputHidden 和 HtmlOutputText父类实现的一个接口。通过这次重构,我们只要一个ValueHolder接口就可完成原本需要三个类(上面提到的HtmlInputText, HtmlInputHidden和 HtmlOutputText)才能完成的工作,代码也干净整洁。你会发现使用Polymorphism(多态)对于基于接口编程的业务逻辑代码整理是相当优雅的。(注:不论是JDK本身还是,目前主流的开源框架,接口,多态运用的非常广泛)
请记住,JSF的优点之一就是让你自由自在的在POJO里编写的你的业务逻辑,开发人员并不要实现任何接口或继承任何类!这一点并没有意味着我们失掉了面向对象的编程原则。当你有机会在基于标准的接口上编程的话,大胆去做吧。
最后,你有没有注意到recordTotal这个action listener 。JSF规范规定Action的listener方法返回值要为void,但咱们这里却返回一个boolean。实际上MyFaces相对规范来说,宽松了点,但允许你这么做,但实际上还是会忽略返回值的。但尽量还是避免这样,因为根据JSF的实现参考来说,有返回值是应该抛异常的,也许别的JSF实现可能与MyFaces不同了吧。
View State(视图状态)加密
一个普遍的错误观念就是许多开发人员觉得View State加密根本不需要SSL。很显然嘛,SSL和View State加密根本没有共同点——它们在各自不同的网络协议中解决属于各自的问题,互不相干。
好,我们来再来举个例子。假设Manfred是个银行,Sean是个在线客户,而Mike是媒介。在使用普通的HTTP的情况下,Mike可以截取Sean发送给Mannfred的请求,偷偷记下Sean的密码,然后再转发给Manfred。这一系列动作对于Manfred或Sean任何一方来说,都是神不知,鬼不觉的。
如果在网络传输层上Manfred和Sean使用了SSL的话,就可以有效阻止Mike窃取他们之间的信息。
SSL提供的是点到点的安全保障,这样从Sean发送到Manfred的请求就不会被Mike截取了。但如果应用程序在客户端保存状态的话,SSL就法保证一定是安全的了。当使用客户端状态保存时,JSF会创建一个数据结构,它是一个控件树的序列化Base64编码,用来表示绑定组件的响应状态值,这个数据结构就是view state,并且此时view state是被序列化和加密过的,然后隐藏在的一个HTML hidden字段中。 当HTML表单提交时,它会将view state的值作为一个HTTP参数传到服务器后台。JSF利用该参数的值,进行反序列化,解密等逆向操作来还原先前的视图是的状态值。这对所有的JSF实现来说都是一个很大安全性挑战,因为Sean是可以自由的改变view state值的(因为它只是一个隐藏的hidden字段)。 我强烈推荐在你的产品中使用view state加密,因为这样可以防止web客户端被恶意篡改view state的值。我也建议在开发和功能测试阶段关闭view state加密(因为Base64编码后的数据量很大,反序列化或解密操作估计有性能损耗)。要想使用view state加密,去好好看看你使用的JSF实现文档吧。
Portlet问题 我有点同情Portlet开发人员。确实,他们总是在邮件列表或论坛上不断的提出一个接一个问题,而这些问题本身来自Portlet,与他们无关。如果一定要说有这么一批人不得不对标准低头,被迫屈服的话,那非Portlet开发人员莫属了。(同情中………………)
有些JSF API在基于Portlet的应用程序中表现的行为是不同的。如果你的Portlet应用程序运行在一个普通的Servlet容器里,那么有一些假设需要去避免。现在假设下面的这段代码在Servlet容器里运行的好好的:
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext externalContext = ctx.getExternalContext();
ServletRequest request = (ServletRequest) externalContext.getRequest();
String id = request.getParameter("id");
如果现在你想运行Portlet应用程序,就必须取消显式的对javax.servlet.ServletRequest or javax.servlet.ServletResponse进行转换。在Portlet应用程序中,ExternalContext.getRequest 返回的是一个javax.portlet.PortletRequest,结果可想而知,当然会抛出ClassCastException异常。我这里有一个通用的好办法,也可以获取request中的属性值,请看:
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext externalContext = ctx.getExternalContext();
externalContext.getRequestParameterMap().get("id");
(全文完)
分享到:
相关推荐
JSF框架充分利用了多种设计模式,这些模式有助于提高代码的可复用性、可维护性和可扩展性。以下是JSF框架中使用的一些关键设计模式的详细解释: 1. **Singleton模式**: Singleton模式确保一个类只有一个实例,并...
**JSF与Hibernate整合** 的目的是将JSF的UI处理能力与Hibernate的数据访问能力结合起来,创建出既具有良好用户体验又能够高效处理数据的Web应用。在本项目中,“JSF与Hibernate整合的登陆”可能涉及到以下关键知识点...
JSF是一种用于构建Java Web 应用程序的标准框架(是Java Community Process 规定的JSR-127标准)。JSF(Java Server Faces)技术为开发基于网络用户界面的Java开发者提供了标准的编程接口API以及标签库。就像Struts框架...
jsf实例 JSF学习 JSF jar包 JSF jsf实例 JSF学习 JSF jar包 JSFjsf实例 JSF学习 JSF jar包 JSF jsf实例 JSF学习 JSF jar包 JSF
通过这三份资料的学习,开发者将全面了解JSF的各个方面,从基本概念到高级特性,从理论到实践,为成为JSF开发专家奠定坚实基础。在学习过程中,建议结合实际编程练习,以加深理解和提高应用能力。同时,JSF社区提供...
**JSF框架的优势** 包括丰富的组件库(如PrimeFaces、IceFaces等)、MVC架构模式、易于测试和调试,以及良好的可扩展性。然而,它也有一些挑战,比如性能问题和学习曲线较陡峭。 **中文教程** 对于非英语背景的学习...
JSF架构基于MVC(Model-View-Controller)模式,由以下核心组件组成: - **模型(Model)**:业务逻辑,通常由JavaBeans(也称为管理Bean)实现,存储和处理应用程序数据。 - **视图(View)**:用户界面,由JSF...
在IT行业中,`JSF(JavaServer Faces)`、`EJB(Enterprise JavaBeans)`和`JPA(Java Persistence API)`是三个重要的Java技术,常用于构建企业级的应用系统,特别是拍卖系统这样的业务流程复杂的场景。这里我们将深入...
为了实现JSF的大文件上传,开发者通常需要借助第三方库,如Apache Commons FileUpload或者PrimeFaces的FileUpload组件。这些组件提供了分块上传的能力,将大文件切割成小块进行传输,从而避免一次性加载整个文件到...
4. **MVC架构**:JSF遵循MVC模式,有助于分离关注点,提高代码可维护性。 5. **支持AJAX**:JSF 2.0及更高版本提供了内置的AJAX支持,可以实现部分页面更新,提升用户体验。 **jar包**:在给定的文件列表中提到了...
它们与JSF页面通过EL(Expression Language)进行交互。 5. **EL(Expression Language)**:EL是用于获取和设置Managed Beans属性的简洁语法,常用于JSF页面中绑定组件的值。 6. **jsf架包**:JSF相关的库通常被...
JavaServer Faces (JSF) 是一个用于构建用户界面的Java框架,主要应用于Web应用程序开发。JSF基于模型-视图-控制器(MVC)架构,提供了丰富的组件库和生命周期管理,使得开发者能够更加便捷地创建动态、数据驱动的...
《JSF_实战》非常好的JSF学习书《JSF_实战》非常好的JSF学习书《JSF_实战》非常好的JSF学习书《JSF_实战》非常好的JSF学习书《JSF_实战》非常好的JSF学习书《JSF_实战》非常好的JSF学习书《JSF_实战》非常好的JSF...
JSF遵循MVC(Model-View-Controller)设计模式,将业务逻辑、视图呈现和用户交互分离开来,使得开发者能够更专注于各自领域的代码编写。JSF的核心组件包括UI组件、事件处理、数据绑定和转换验证。 ### 2. UI组件库 ...
综上所述,JSF分页是一个涉及前端UI和后端数据处理的复杂过程,但借助组件库和良好的设计模式,可以轻松实现高效且用户友好的分页功能。通过合理优化和灵活扩展,可以适应各种复杂的分页场景。在实际开发中,应根据...
JavaScript Server Faces(JSF)是Java平台上的一种用于构建Web应用程序的服务器端框架。它提供了一种组件化的开发方式,使得开发者可以使用可重用的UI组件来构建用户界面,极大地提高了开发效率。在这个主题中,...
1. **JSF架构**:JSF采用MVC(Model-View-Controller)设计模式,它提供了组件化UI开发的能力。模型负责业务逻辑,视图负责展示,控制器负责处理用户请求并更新模型。 2. **JSF组件**:JSF的核心是UI组件库,如`h:...
JavaScript Faces (JSF) 是Java平台上的一种用于构建用户界面的模型-视图-控制器(MVC)框架,它简化了Web应用程序的开发。本资源包包含了JSF从入门到进阶的多个方面,包括基础教程、核心组件库(LIB)、Ajax4JSF的使用...