首页 > 开发 > JSP > 正文

JSP和JSF双剑合并 打造完美Web应用

2020-02-05 13:48:19
字体:
来源:转载
供稿:网友

  java在最近几年逐渐升温,随着java se 5和java se 6的推出,java的未来更显得无比辉煌。但以java为基础的jsp在java se 5推出之前却一直抬不起头来,这最重要的原因就是jsp虽然功能十分强大,但最大的优点也是它的最大缺点,功能强大就意味着复杂,尤其是设计前端界面的可视化工具不多,也不够强大。因此,设计jsp页面就变得十分复杂和繁琐。不过,在java se 5推出的同时,sun为了简化jsp的开发难度,推出了新的javaserver faces(简称jsf)规范。从而使jsp走上了康庄大道。

  一、什么是jsf

  jsf和jsp是一对新的搭档。jsp是用于后台的逻辑处理的技术,而jsf恰恰相反,是使开发人员能够快速的开发基于 java 的 web 应用程序的技术,是一种表现层技术。目前,jsf1.2已经正式作为一个标准加入了java ee 5中。

  作为一种高度组件化的技术,开发人员可以在一些开发工具的支持下,实现拖拉式编辑操作,用户只需要简单的将 jsf 组件拖到页面上,就可以很容易的进行 web 开发了。这是其作为一种组件化的技术所具有的最大好处,我们能用的组件不光是一些比较简单的输入框之类,还有更多复杂的组件可以使用的,比如 datatable 这样的表格组件, tree 这样的树形组件等等。

  作为一种标准的技术,jsf还得到了相当多工具提供商的支持。同时我们也会有很多很好的免费开发工具可以使用,前不久 sun java studio creator 2 和 oracle jdeveloper 10g 作为免费的支持 jsf 的开发工具发布,给 jsf 带来了不小的生气。另外我们也有一些很优秀的商业开发工具可共选择,bea workshop (原 m7 nitrox),exadel,myeclipse 这样的基于 eclipse 的插件开发工具,为现在广大的 eclipse 用户带来了不小的便利,ibm 的 rational application developer 和 borland 的 jbuilder 也是很不错的支持 jsf 可视化开发的商业开发工具。

  jsf和传统的web技术有着本质上的差别,在传统的web技术需要用户自己对浏览器请求进行捕捉,保存客户端状态,并且手工控制着页面的转向,等等。而jsf的出现,无疑给我们带来了巨大的便利,jsf 提供了事件驱动的页面导航模型,该模型使应用程序开发人员能够设计应用程序的页面流。与 struts 的方式向类似的是,所有的页面流信息都定义在 jsf 配置 xml 文件 (faces-config.xml) 中,而非硬编码在应用程序中。这很大程度简化了开发人员开发难度,简化了应用程序的开发。

  同时jsf也是一种遵循模型-视图-控制器 (mvc) 模式的框架。实现了视图代码(view)与应用逻辑(model)的完全分离,使得使用 jsf 技术的应用程序能够很好的实现页面与代码的分离。所有对 jsf 页面的请求都会通过一个前端控制器 (facesservlet) 处理,系统自动处理用户的请求,并将结果返回给用户。这和传统的 mvc 框架并没有太大的区别。

  在jsf中不仅使用了 pojo 技术,而且还使用了类似 spring 的控制反转(ioc) (或称为依赖注入-di) 技术,在 jsf 的 backing bean 中,我们可以把视图所需要的数据和操作放进一个 backing bean 中。同时得益于 jsf 使用的 di 技术,我们可以在配置文件中初始化 managed bean,同时我们也可以通过这样的技术很方便的和使用类似技术的 spring 进行整合。

  二、如何在jsp中使用jsf

  jsf只有通过和jsp相结合,才能充分发挥它的功效。jsf是通过标签库和jsp进行集成的。标签库就相当于asp.net的服务端组件。jsf提供了非常丰富的标签库,通过这些标签库,可以生成各种客户端模型,如html、wml、xml以及javascript等。通过这些标签,你可以很容易建立大规模的客户端模型,并由这些标签自动处理客户端请求。

  接下来让我们来看一个如何使jsf和jsp在一起工作的例子。在jsf中有两个库。第一个叫做内核库,在这个库中包含了各种主要的标签,如配置组件、管理事件、验证输入信息等。第二个库的主要功能是将html和jsf的各种标签相对应。每一个jsf标签都会对应一个html组件。如uiinput标签对应了html中的文本框或密码框。

  在jsf标签中文本输入框叫做inputtext,而密码输入库叫inputsecret。下面是一个简单的jsf和jsp结合的用户接口程序。

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=gb2312">
<title>第一个jsf程序</title>
</head>
<body>
 <f:view>
 <h:form id="simpleform">
 <h:outputtext id="favoritelabel" value="请输入一个数字:"/>
 <h:inputtext id="favoritevalue" value="#{simple.longvalue}">
  <f:validatelongrange maximum="30" minimum="0"/>
 </h:inputtext>
 <p/>
 <h:commandbutton id="submit" value="提交" action="#{simple.simpleactionmethod}"/>
 </h:form>
 </f:view>
</body>
</html>

  在上面的代码中,我们可以了解到jsf是如何同jsp集成的。我们首先可以看到一个内核标签:view。然后是几个jsf组件。如form、outputtext、inputtext以及commandbutton。这几个组件被放到form中从而开成了form中的一部分。在程序的最开始,必须使用import导入两个标签库。代码如下。

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

  上面2行代码声明了jsp中要使用哪一个jsf标签库。内核库使用前缀(prefix)f声明,而html库使用前缀(prefix)h声明。这两个前缀并不是必须要使用,而只是一个建议。在程序中,内核库必须要使用,因为view在所有的jsf页中必须使用。而html标签在运行时将jsf标签转化为html组件,这个h前缀并不是必须的,而是jsf规范推荐使用的,这样,我们使我们的jsf程序更易读。

  在声明后是几行标准的html语句,本文不再详述。从<f:view>开始,是一段jsf语句。这段代码如下所示:

<f:view>
<h:form id="simpleform">
<h:outputtext id="favoritelabel" value="请输入一个数字:"/>
<h:inputtext id="favoritevalue" value="#{simple.longvalue}">
<f:validatelongrange maximum="30" minimum="0"/>
</h:inputtext>
<p/>
<h:commandbutton id="submit" value="提交"
action="#{simple.simpleactionmethod}"/>
</h:form>
</f:view>

  </f:view>标签预示着jsf的开始,而它的下一个标签form将建立一个html form。而outputtext标签相当于html中的label组件。inputtext标签相当于html中的textfield组件。而commandbutton标签相当于html中的submit按钮。运行这个jsp程序,将得到如图1所显示效果。


图1 第一个jsf程序的运行结果

  三、jsp如何响应jsf的请求

  从上面的例子我们已经知道如何在jsp中使用jsf了,在这一部分让我们来看看在jsf是如何处理请求的。

  首先让我们来看一个例子,这个例子是将华氏度转换为摄氏度。当用户点击提交按钮时程序将进行转换。

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
 <meta http-equiv="content-type" content="text/html;charset=gb2312">
<title>温度转换程序</title>
</head>
<body>
 <f:view>
 <h:form>
 <div>
  <h:outputtext id="fahrenheitlabel" value="请输入华氏温度:"/>
  <span>
   <h:inputtext id="temperature" value="#{tc.fahrenheittemp}">
   <f:validatedoublerange minimum="-100.0" maximum="100.0"/>
   <f:valuechangelistener type="tempconv.page.tcchangedlistener"/>
  </h:inputtext>
  </span>
 </div>
 <div>
  <h:outputtext id="celsiuslabel" value="摄氏温度:"/>
  <span>
   <h:outputtext id="celsiusvalue" value="#{tc.celsiustemp}">
   <f:convertnumber maxfractiondigits="3" type="number"/>
  </h:outputtext>
  </span>
 </div>
 <div>
  <h:commandbutton value="转换" action="#{tc.convert}">
  </h:commandbutton>
 </div>
 </h:form>
 </f:view>
</body>
</html>

  在程序的前两行是导入jsf核心库和html库,这个在前面已经讨论过,在这里不再详述。

  下面让我们来看看jsf标签是如何同后端进行交互的。由于我们是在jsp中使用jsf,因此,这个和正常的jsp没有什么区别;jsp实际上就是servlet,在jsp第一次运行时由jsp编译器将.jsp文件编译成servlet后再由servlet调用,然后由servlet来接收客户端传过来的数据流。但和一般的jsp程序不同的是,jsf标签是由jsf api负责调用的(这样可以做到逻辑层和表现层分离),除此之外,它们和一般的jsp标签没有任何区别。

  当uicomponent标签收到dostarttag方法时,jsf将使用这些属性来设置标签的值。如本例中的inputtext标签将按它的属性值来设置。下面是jsf的代码片段。

<h:inputtext id="temperature" value="#{tc.fahrenheittemp}">
 <f:validatedoublerange minimum="-100.0" maximum="100.0"/>
 <f:valuechangelistener type="tempconv.page.tcchangedlistener"/>
</h:inputtext>

  inputtext标签根据相应的值设置了id和value的属性。在jsf中是通过setattribute(string name, object value)设置每一个属性值的。但我们需要注意的是jsf标签可以指定相应的默认值。这有些类似java中的系统属性,如果你给了一个属性名子,那系统将返回这个属性的值,如果指定它的默认值,并且这个属性不存在的话,将返回这个默认值。

  接下来让我们来看看上面程序的最重要的部分,也就是uiinput组件的事件处理。

<f:valuechangelistener type="tempconv.page.tcchangedlistener"/>

  在jsf中事件处理是由valuechangelistener标签完成的。这个标签所表示的事件在文本框的值发生变化时引发事件。但有意思的是这个事件并不马上提交,而是要等到用户点击"提交"按钮后这个事件连同相应的数据才提交给后端。因此,这个事件请求也叫做预提交。最后,让我们看看uicommand的代码实现。

<div>
 <h:commandbutton value="转换" action="#{tc.convert}">
 </h:commandbutton>
</div>

  上面的代码将convert()方法和uicommand连接了起来,也就是说,点击"提交"按钮后,将执行convert()方法。在遇到view标签后,jsf程序结果,jsfapi最后调用doend方法来结束jsf程序。jsf引擎在解析这段程序后,将相应的jsf标签转换为html组件。

  最后,让我们来看看jsp是如何响应jsf事件的。下面是一段响应jsf事件的java代码。

public class tcchangedlistener implements valuechangelistener
{
 public tcchangedlistener()
 {
  super();
 }
 // 事件处理
 public void processvaluechange(valuechangeevent event)
throws abortprocessingexception
 {
  uicomponent comp = event.getcomponent();
  object value = event.getnewvalue();
  if (null != value)
  {
   float curval = ((number) value).floatvalue();
   map values = comp.getattributes();
   if (curval < 0)
   {
    values.put("styleclass", "red");
   }
   else
   {
    values.put("styleclass", "black");
   }
  }
}

  要想响应jsf事件,必须要实现jsf库中的valuechangelistener接口。上面的程序要注意的是最后根据输入的值来设置相应的颜色。这些值并不依赖jsp。当然,你也可以将它们设置成null,而由jsp 标签来设置它们的颜色。菜鸟学堂:
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表