BlogJava

研究、学习Java的地方

  DonewsBlog  |  Donews首页  |  Donews社区  |  Donews邮箱  |  我的首页  |  联系作者  |  聚合   |  登录
  161篇文章 :: 3篇收藏:: 87篇评论:: 0个Trackbacks

公告



Locations of visitors to this page

文章

收藏

相册

Java

软件工程

数据库

新闻

存档


正在读取评论……


文章翻译

翻译网上发表的计算机文章,此处翻译作品未经作者同意,如有版权问题,请及时联系我,我会马上删除。

    摘要:新本版有了很大的改变,其中BTree索引已经非常成熟,增加了新的查询模式“懒加载查询评估模式”(lazy query evaluation  mode),相比5.x版本在性能上有了很大的改进,相同时间内的内存开销下降了90%。Db4O的开发人还按照Poleposition数据库标准编写了相应的手册
由于并没有把查询的执行完全绑定到特定的客户端应用中,所以新的懒加载查询模式同样提高了C/S应用的性能。DB4O同时还发布了“ObjectManager”一个数据库查询客户端软件的6.0版本。
DB4O的官方网址:http://www.db4o.com/    (全文共458字)——点击此处阅读全文


    摘要:这篇文章是向你简单的介绍一下什么是TurboGears以及它能作什么。    (全文共4904字)——点击此处阅读全文

        SUN负责SUN平台小组的负责人Graham Hamilton在一次访谈中提到JAVA SE7(命名代码:海豚)将支持Visual Basic 。
SUN不准备克隆某个固定版本的VB,它将致力于在未来的Java平台中增加通用的VB.NET的支持。“如果你对VB.Net熟悉的话,你会发现这将是非常容易学习的语言”Hamilton说对于Basic语言支持的基础实现已经在开发中。
这意味着Java将有VB语言的特性,而不是实现VB语言本身。基于这一点,我认为SUN不会提供基于VB代码的编译器。不管怎么说这都是件好事,尤其是 对于以前从事过VB开发的人,而对于像我一样的从未使用过VB的人也不是什么坏事,毕竟这只是一个新增的特性。你怎么看?

           设计一个包含有序选择的冗长列表需要非常复杂的设计模式。这种模式需要将可选项显示在一个列表中,同时还需要在另一个地方进行选择,所以需要用户的可以方便的进行选择和修改.
这种模式通常称为双重列表或者叫双重列表框选择器.它又被称为选择概要或者列表创建者模式.按照Java Look and Feel的设计规则,它又被称为增加-移除模式。
标准的Struts实现,需要试用JSP,Java和JavaScript。JavaServerFace不需要JSP技术,但是比起Struts要简单的多。
列表1是使用Struts技术的JSP代码,列表2是使用JavaServerFace技术的JSP代码。JSF的支持Bean,配置文件和其他文件的代码可以从JDJ网站下载。
Jakarta Struts的实现方式
使用Jakarta Struts技术,JSP需要定义一个表格来显示树状列。在第一列和第三列,可选列通过<html:select>标签和<html: optionCollection>来实现。为了实现国际化要求,label标签使用了JSP标准表情库中的<fmt: message>标签。很多人发现结合Struts和JSTL标签一切使用功能非常强大。
<table border="0" cellpadding="0" cellspacing="5">
<tr align="middle" valign="center">
<td>
<fmt:message key="titles.available"/><br />
<html:select property="availableValues"
multiple="true" size="7"
style="width:80px;" styleId="available"
onchange="doUpdate( false, true );">
<html:optionsCollection
property="availableList"/>
</html:select>
</td>
...
<td>
<fmt:message key="titles.chosen"/><br />
<html:select property="chosenValues"
multiple="true" size="7"
style="width:80px;" styleId="chosen"
onchange="doUpdate( true, false );">
<html:optionsCollection
property="chosenList"/>
</html:select> </td>
</tr>
</table>
Struts的表单Bean包含了用于JSP的“可见列表”,“可见值”,“可选列表”和“可选值”属性。
private List availableList = new ArrayList();
private String[] availableValues = new String[ 0 ];
private List chosenList = new ArrayList();
private String[] chosenValues = new String[ 0 ];
...
public List getAvailableList()
public void setAvailableList( List list )
public String[] getAvailableValues()
public void setAvailableValues( String[] list )
public List getChosenList()
public void setChosenList( List list )
public String[] getChosenValues()
public void setChosenValues( String[] list )
“availableList ”和“chosenList ”属性通过标签值Bean的方式封装了列表的可见值。“availableValues ”和“chosenValues ”以字符串数组的形式存储了可选的值。
对于增加-选择模式来说,不会关心这些可选值。对于服务器来说我们只要告诉它列表中显示什么值而无需告诉它那个值被选中了。然而当表单被提交后,只有被选中的值会被提交给服务器。这是通常使用的设计方法,但是这种设计模式存在问题。如图1.
下 面有集中方法可以解决这个问题。一种方法是在每次列表内容发生变化的时候都向服务器提交一次值。者引发了过度的页面引用和网络负载。另一种方法是使用 AJAX技术与服务器进行通信。这减少了页面的刷新,但是仍然会代理网络的负载。直到用户完成列表变更之前都不应该产生网络负载。
最好的解决方案是把选中的值存储在一个隐藏字段中。使用这种方法当表单提交时只向服务器提交一次值。在这个例子中我们把选中的值存储在一个隐藏字段中。利用这个隐藏字段,两个列表中见的按钮可以这样实现:

<td>
<br />
<input type="button" style="width:100px;" id="add" onclick="
doMove( 'available', 'chosen', false );" value="<fmt:message key='add'/>" /><br />
<input type="button" style="width:100px;" id="addAll" onclick=
"doMove( 'available', 'chosen', true );" value="<fmt:message key='addAll'/>" /><br />
<br />
<input type="button" style="width:100px;" id="remove" onclick=
"doMove( 'chosen', 'available', false );" value="<fmt:message key='remove'/>" /><br />
<input type="button" style="width:100px;" id="removeAll" onclick=
"doMove( 'chosen', 'available', true );" value="<fmt:message key='removeAll'/>" />
<html:hidden styleId="chosenItem" property="chosenItem" />
</td>
这个按钮通过HTML标签<input>实现。<html:hidden>字段存储了选中的值。被选中的值通过JavaScript方法“doMove()”进行保存,所有4个按钮都执行这个方法。

/**
* Move selected items between lists.
* <p>
* @param sourceId ID of source list
* @param destId ID of destination list
* @param all true iff moving all
*/
function doMove( sourceId, destId, all )
{
// Move the items between the lists.
var sourceElem = document.getElementById( sourceId );
var destElem = document.getElementById( destId );
for( var i = 0; ( i < sourceElem.length ); )
{ if( sourceElem.options[ i ].selected || all )
{ var newOption = document.createElement( "OPTION" );
newOption.text = sourceElem.options[ i ].text;
newOption.value = sourceElem.options[ i ].value;
destElem.options[ destElem.length ] = newOption;
sourceElem.remove( i );
}
else
i++;
}
// Update the button states.
doUpdate( false, false );
// Store the chosen items in a hidden field.
var chosenItem = document.getElementById( "chosenItem" );
var chosenList = document.getElementById( "chosen" );
chosenItem.value = "";
for( var i = 0; ( i < chosenList.length ); i++ )
{ chosenItem.value += chosenList.options[ i ].value + '|';
}
}
上面的方法非常易于理解,使用起来也很方便。按钮只要在需要的时候才会显示。比如如果没有列表值被选中,那么“Add”和“Remove”按钮就无法使用。当显示列表和选择列表都是空的时候,那么“Add All”和“Remove All”按钮就无法使用。
“doUPdate()”函数根据用户的选择和列表中包含的内容判断按钮是否可以显示。如图2
“doUpdate()”方法由上面由列表控件的OnChange方法触发的“doMove()”方法调用。或者在body的onload方法中调用。

/**
* Update the button states based on whether
* lists have contents and selected items.
* Deselect list items if requested to ensure
* at most one list contains selections.
* <p>
* @param offAvailable deselect available list
* @param offChosen deselect chosen list
*/
function doUpdate( offAvailable, offChosen )
{
// Get the lists and deselect if requested.
var availableList = document.getElementById( "available" );
var chosenList = document.getElementById( "chosen" );
if( offAvailable ) availableList.selectedIndex = -1;
if( offChosen ) chosenList.selectedIndex = -1;
// Update the button states.
document.getElementById( "addAll" ).disabled =
( availableList.length == 0 );
document.getElementById( "removeAll" ).disabled =
( chosenList.length == 0 );
document.getElementById( "add" ).disabled =
( availableList.selectedIndex < 0 );
document.getElementById( "remove" ).disabled =
( chosenList.selectedIndex < 0 );
}
使用JavaScript函数,列表中包含的内容被正确的更新,用户选择的值被保存在一个隐藏字段中。在这个例子中它被用于控制两个列表中值和用户的选择。
列表中的值被存储在表单Bean中的一个“languageList”属性里。这个列表中包含了所有可能的选项。move方法利用“chosenItem”列表中的值控制了“可见”和“可选”列表中的值。

private List languageList = new ArrayList();
private String chosenItem = "";
...
public List getLanguageList()
public void setLanguageList( List list )
public String getChosenItem()
public void setChosenItem( String items )
public void move( List sourceList, String[] sourceValues, List destList )
...
"languageList" ,"chosenItem" 属性和 "move"方法通过表单提交的Action中的“execute”方法执行。在Struts中是StrutsAction类的实例。

/**
* Populate the lists from the hidden field.
* <p>
* @param mapping action mapping
* @param form action form
* @param request HTTP servlet request
* @param response HTTP servlet reponse
* @throws Exception
*/
public ActionForward execute( ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response ) throws Exception
{
// Populate available list from language list.
ExampleForm eForm = ( ExampleForm )form;
eForm.getAvailableList().clear();
eForm.getAvailableList().addAll( eForm.getLanguageList());
// Populate chosen list from hidden field.
eForm.getChosenList().clear();
eForm.move( eForm.getAvailableList(),
eForm.getChosenItem().split( "\\|" ),
eForm.getChosenList());
}
JavaServerFace实现
那么JavaServerFace中是如何实现上面的模式呢?JSF由一群曾经设计过Struts的人设计,所以我们可以较容易的从Struts过度到JSF。
JSF 中的JSP也包含了两个列表,因为JSF的标签更加紧密。代替<table>,<tr>和<td>标签,JSF使用 了<h:panelGrid>标签。代替Struts中的<fmt:message>标签JSF使用了<h: outputText>。代替<html:select>和<html:optionsCollection>标签, JSF使用了<h:selectManyListBox>和<f:selectItems>。

<h:panelGrid columns="3" rowClasses="center">
<h:outputText value="#{bundle.available}" />
<h:outputText value="" />
<h:outputText value="#{bundle.chosen}" />
<h:selectManyListbox style="width:100px; height:120px;"
id="available" value="#{example.availableValues}"
onchange="doUpdate( false, true );">
<f:selectItems value="#{example.availableList}"/>
</h:selectManyListbox>
...
<h:selectManyListbox style="width:100px; height:120px;"
id="chosen" value="#{example.chosenValues}"
onchange="doUpdate( true, false );">
<f:selectItems value="#{example.chosenList}"/>
</h:selectManyListbox>
</h:panelGrid>
就 像Struts中实现的那样,<h:selectManyListBox>标签映射了支持Bean中的“availableList” “availableValues”和“chosenList”以及“chosenValues”属性,他们等同于Struts中的相应属性。
就像Struts实现中的一样,四个按钮也由标准HTML的<input>标签实现。
在JSF中这些标签还必须附上<f:verbatim>标签。除此之外这些标签和Struts中的没什么不同。这里有一点与Struts类似的就是在每个JavaScript方法中经常需要包含一个“form:”前缀。

<h:panelGrid columns="1">
<f:verbatim>
<input type="button" style="width:100px;"
id="add" onclick="doMove( 'form:available', 'form:chosen', false );"
value="<fmt:message key='add'/>" /><br />
<input type="button" style="width:100px;"
id="addAll" onclick="doMove( 'form:available', 'form:chosen', true );"
value="<fmt:message key='addAll'/>" /><br />
<br />
<input type="button" style="width:100px;"
id="remove" onclick="doMove( 'form:chosen', 'form:available', false );"
value="<fmt:message key='remove'/>" /><br />
<input type="button" style="width:100px;"
id="removeAll" onclick="doMove( 'form:chosen', 'form:available', true );"
value="<fmt:message key='removeAll'/>" />
</f:verbatim>
<h:inputHidden id="chosenItem" value="#{example.chosenItem}" />
</h:panelGrid>
除此之外,JSF中的doMove方法和doUpdate方法没什么不同。
JSF的优势是它控制了提交事件。在JSF中你可以明确的定义一个按钮具体执行那个请求。
<h:commandButton action="#{example.submit}" value="#{bundle.submit}" />
“example:submit”方法会读取隐藏字段中内容并更新列表。因为这个方法直接关联在一个提交按钮上,所以你不必单独实现一个Action对象。
public String submit()
{
// Populate the available list from the language list.
availableList.clear();
availableList.addAll( languageList );
// Populate the chosen list from the hidden field.
chosenList.clear();
move( availableList, chosenItem.split( "\\|" ), chosenList );
...
return( "success" );
}
JSF中不需在学什么,虽然标签不同,但是通常和JSP中的类似。Java代码也差不多。
需 要强调的是JSF中的组件架构。如果你下载了免费的SUN Java Studio Creator,你会发现它包含了一整套可以在你的GUI中任意增加-删除的组件。SUN的组件包含很多功能,比如“Move Up”和“Move Down ”按钮可以改变列表中值的顺序。我们还可以列举很多这样的有用组件。
结论

这篇文章展示了一个从两个列表中取值的标准UI设计模式。通过Jakarta Struts和JavaServer Face两种方式实现。
JSF提供了一种从Struts平滑过度的方法。JSP的标签非常简单那;支持Bean的代码也和Struts类似;并且,如果你需要使用JavaScript在JSF中的用法也是一样的。
你可以把JSF当成是一个简单的,组件化的Struts。它增加了很多有用的特性,并且减少了复杂性。
对于大多数刚接触Web项目的开发人员,JavaServer Faces是一个很好的选择。对于熟悉Struts的开发人员,过度到JSF也很容易。


之前我们讲述的概念中所有操作都是在一个单独的页面上。在实际的Web应用开发中,这是不太可能的。Web应用的开发会有很多页面,我们必须提供一种方法实现不同页面之间的切换。实现从一个页面到另一个页面切换的机制被称为“导航”。

JSF中有一套非常完善的导航系统。导航控制器根据请求实现的返回值确定下一个页面跳转到哪里。对于给定的页面,一个导航规则定义了根据业务逻辑的动作事件判断页面应该如何跳转。根据导航规则发生的每一个页面跳转被称为一个导航事件。导航规则定义在JSF的配置文件中。下面这个例子演示了针对longin.jsp页面的两个导航事件:success和failure的一个导航规则。


<navigation-rule>
     <from-view-id>/login.jsp</from-view-id>
     <navigation-case>
     <from-outcome>success</from-outcome>
     <to-view-id>/mainmenu.jsp</to-view-id>
     </navigation-case>
    <navigation-case>
    <from-outcome>failure</from-outcome>
    <to-view-id>/login.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

如 你所见,每一个出口对应一个JSP页面,这里你不需要通过编码实现这些规则。如果你曾经使用过Struts你对这种定义方式一定不会陌生。你会发现,所有 的导航事件只映射一个出口(对应一个jsp),也就是说,如果将来需要进行变更你只需要修改需要变更的那一个页面就可以了而不是修改多处。

现在,JSF中的几个基本概念已经介绍完了。在随后的讲解中我们会看到更多的例子。已经这些概念集中到一起是如何使用的。


前面我们讲了JSF中包含的:组件、事件、监听器以及很多好用的组件,这些功能都使得JSF的开发变得更简单。那么这些部分的执行过程是什么样的呢?为了更容易理解,我们讲分析JSF框架的底层Servlet API,这对于你更好的理解JSF的执行过程是有好处的。了解了这些内容也有助于你开发出更好的应用程序,因为你明白底层到底是如何运行的。当然如果你是一个WEB界面开发人员,你完全可以跳过这个部分。
    在这一节中我们讲讨论JSF是如何对请求作出响应的。或者说,由包含JSF组件的页面发出的请求是如何被JSF处理的。
    图2.4是一个状态图,它显示了当接收到来自客户端发出的请求后JSF是如何处理的,即JSF的请求处理过程。这个过程开始于JSFservlet接收到一个来自客户端的请求(记住JSF是建立在Servlet基础之上的)
          

   图2.4
        列表2.2对以上每一个状态进行了注释,其中主要有六个状态,每一个状态之后多会有相应的时间产生。JSF将这些事件交给相应的监听器进行处理,不管监听 器是处理某些业务逻辑还是组件,都能够继续跳转到最终的状态,显示响应结果。监视器也可以跳过最终的状态直接显示一个响应结果,比如它可以返回一个二进制 内容,执行一个页面跳转或者返回其他与JSF有关的内容比如XML文档或者是一个HTML。
        以上六个步骤中有四个可以产生消息,它们分别是:接收请求值(Apply Request Values),执行验证(Process Validations),更新模型值(Update Model Vlaues),和提交应用程序(Invoke Application)。不管是否带有消息,这些状态都能够向用户反馈响应,除非监听器、装饰器或者组件自身直接返回响应。这些状态之后是一个依据时间 主线提交应用程序的过程。一系列的组件、校验过程、支持Bean和模型对象将被更新。简单的讲,JSF为你完成了大部分工作:它捕获了请求的详细信息并把 它们传输给包含组件和时间的高层视图,而且还更新了相关对象的属性。
表2.2 JSF 各个状态的请求响应过程
状态
描述
触发的事件
还原页面(Restore View)
为选择的页面查找或创建一个组件树。一些组件,比如HtmlCommandButton组件在此状态下将产生动作事件(或者其他事件)
状态事件
接收请求值(Apply Request Values)
比较请求传输的值并更新相应组件的值,也可以使用转换器。如果出现异常将抛出一个异常消息。同时会产生来自请求参数的事件。
状态事件
数据模型事件
动作事件
处理验证(Process Validations)
对每个组件执行验证。可能会产生验证消息。
状态事件
数据模型事件
值变化事件
更新模型值(Update Model Values)
更新与组件相关的所有模型对象和支持Bean的值。可能会产生异常消息。
状态事件
数据模型事件
提交应用程序(Invoke Application)
调用注册的监听器。缺省的监听器将执行命令组件(比如HtmlCommandButton)的事件方法或者选择下一个要显示的视图。
状态事件
动作事件
返回相应(Render Response)
显示当前逻辑指定的下一个响应页面。
状态事件

       为了让你对此有一个更清晰的了解。我们将通过一个hello world的例子展示JSF处理请求过程的整个生命周期。这个例子来自于我们前面章节讲述的hello.jsp。列表2.1显示了实际上Http的处理过程。
列表2.1 Http 的请求过程
POST /jia-hello-world/faces/hello.jsp HTTP/2.1                 (1)接收来自URL的请求
Host: deadlock:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:2.2.1)
Gecko/20021130
Accept: text/xml,application/xml,application/xhtml+xml,text/html;
q=0.9,text/plain;q=0.8,video/x-mng,image/png,
image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1
Accept-Language: en-us, en;q=0.50
Accept-Encoding: gzip, deflate, compress;q=0.9
Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66
Keep-Alive: 300
Connection: keep-alive
Referer: http://deadlock:8080/jia-hello-world/faces/hello.jsp  (2)同样是接收来自URL的请求
Cookie: JSESSIONID=58324750039276F39E61932ABDE319DF  (3)会话标记
Content-Type: application/x-www-form-urlencoded
Content-Length: 92
welcomeForm%3AhelloInput=64&                              (4)组件值
welcomeForm%3AredisplayCommand=Redisplay&
welcomeForm=welcomeForm
        我们并不打算讨论Http处理的详细过程,不过上表其中几行与我们的讨论是有关的:
(1)请求数据来源于/jia-hello-world/faces/hello.jsp 这个连接的POST数据。
(2)这里的referer(引用)是由请求页面产生的,他与/jia-hello-world/faces/hello.jsp是相同的页面。
(3)这里的Cookies将被Servlet容器使用,它用于将请求数据映射到一个指定的会话中。在这个例中JSF使用Servlet会话来存储当前的视图(页面也可以保存在由客户端控制的一个值对象中,比如隐藏字段中)。
(4)这是非常重要的一个部分,这里包含了JSF传输的实际参数值(&用于分隔不同的参数,%3A将被解析为“:”冒号)。首先是一个名为 welcomeForm:helloInput的参数,并且它的值是64,这个值是通过浏览器页面输入的,第二个参数名为welcomeForm: redisplayCommand,他的值是“Redisplay”,最后一个参数是welcomeForm,它的值也是welcomeForm。在下面 的讲解中我们将逐步介绍这些值是如何处理的。
        一旦JSF接收到请求,它就会创建并实例化一个javax.faces.context.FacesContext对象。这个对象代表当前的请求状态,并且负责处理底层Servlet request对象的各个部分,事件监听器可以通过它获得当前页面的操作句柄,以此来进行增加消息、记录事件等等操作。在JSF中它代表了请求处理生命周期的整个过程。我们将在下面的讲解中依次讨论每一个状态。


    摘要:

之前我们讨论了不同的JSF组件,那么如果发生错误是会怎样呢?现在最大的问题是如何让UI组件显示一个恰当的错误消息。这个消息可以分为两种:一种是应用程序错误(比如应用程序逻辑错误,数据库错误,连接错误等等),另一种是用户输入错误(比如文本框输入校验和空值校验等等)。

应 用程序错误一般会产生一个新的页面以便显示错误消息;而用户输入错误一般会回显原来的页面,然后把错误信息显示在一个文本中。通常你    (全文共2485字)——点击此处阅读全文



    摘要:

动作事件在用户通过一个组件发出命令时被触发。比如按钮或者超链接这样的组件可以产生动作事件,或者叫动作源。动作事件由动作监听器控制。

有两种类型的动作监听器。一种会涉及到页面的导航,一种不会。涉及到页面导航的动作事件会执行一个过程并且返回一个结果,JSF导航系统根据这个结果跳转到下一个页面(也可以时当前的页面)。不涉及导航的动作监听器负责控制当前页面的组件,或者执行一个过程来改变模型对象或者支持    (全文共7680字)——点击此处阅读全文


基于界面UI开发中的一个重要部分就是保证用户输入了合法的值-这种校验可能是诸如“必须是符合数据库要求的正确身份信息”这样的负责验证,也可能是简单的“不能为空”的简单验证。通常,为了保证输入的合法性,需要用JavaScript或者Java写很多复杂的代码。而且,如果没有框架的帮助,显示错误消息也会变的麻烦。

控制验证有三种方式:在UI组件层,通过后台Bean的验证方法,或者单独的校验器类。UI组件通常负责简单的校验,比如哪些值是必须输入的,或者组件自身的校验逻辑。当你需要校验一个表单上的一个或者多个值的时候校验器的方法是非常有用的(你无需和其他组件共享这些校验逻辑)。当你要验证诸如字段长度、数字范围时外部校验器非常有用。这种方式是插件化的,就是说你可以在其他组件上使用这些验证器。校验过程是在服务器端完成的,因为客户端不支持脚本(JSF组件支持客户端校验,但是标准组件不这么作)。

当校验器检验到错误时,比如字符串太长,或者错误的信用卡号,它会把错误消息添加到当前的错误信息列表中。这样JSF标准组件就可以很方便的向客户端用户显示错误信息。下面是一个例子:

<h:inputText>

<f:validateLength minimum="2" maximum="10"/>

</h:inputText>

如你所见使用组件的校验器非常简单。上面定义的Html输入框组件可以校验输入的字符长度在210之间。

通常,web开发中的校验是一样苦差事。JSF中的校验器提供了一个强大的框架,这使校验开发变得更简单。JSF提供了一套标准的校验器,比如校验字符长度,数字输入范围等。当然,你可以使用第三方开发的校验器或者自定义校验器。标准校验器和自定义校验器开发将在随后详细讲述。


 前端的UI 组件一般情况下并不关心如何“装饰”自己。如果组件可以自我装饰的话,我们称之为直接扩展模式,不过JSF还同时提供了另一种方式,称之为层次扩展模式,这种模式可以将装饰类从UI种分类出来。这些装饰类就是我们说的装饰器(renderders)。

装饰器一般被分包组合,特定类型的装饰器被放到一起。JSFHTML4.1提供了一套标准的装饰器,当然,除了HTML外还有其他的装饰器套件,比如WMLSVG等,甚至可以是AppletJava应用程序或者其他客户端。

你可以把装饰器看作是客户端与服务端之间的一个翻译器。在服务器端装饰器负责编码,这一过程将让组件变成客户端可以看懂的形式。当JSF接收到来自客户端的响应时,装饰器复杂解码,这一过程将解析当前请求的参数并根据这些参数设置组件的值。

比如下面的代码定义了一个Html输入框:

<h:inputText id="inputText" size="20" maxlength="30"/>

当这个组件被编码之后,在客户端将显示下面的代码:

<input id="myForm:inputText" type="text" name="myForm:inputText"

maxlength="30" size="20" />

假设,用户在这个文本框中输入“foo”这个词。解码的过程就是通过http协议传输这个值并在服务器端给组件赋值为“foo”。目前,标准html套件中的文本框装饰器负责处理这一过程。因为所有的编码和解码过程都由一个实体负责(包括组件和装饰器),组件的显示和请求响应的底层传输协议都是自包含的。

当组件使用层次扩展模式时,修改页面显示的样式只要更换组件装饰器就可以了。这意味着你可以非常容易的定义组件的显示模板,对于HTMLWMLSVG不同的格式,组件都是相同的,如果需要使用不同的扩展标记只要修改一些装饰器就可以了。

值得注意的是,使用HTML开发时,HTML装饰器已经非常完备了。所有标准HTML组件的装饰器已经具备,所以你不必再为这些担心。然而,当你想动态修改你的应用程序外观时,或者想开发自己的自定义组件时,JSF中的装饰器就变得非常重要了。我会在后续的文章中详细介绍装饰器。

第1页,共2页