??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV永久无码精品水牛影视,亚洲人成亚洲精品,亚洲av永久无码精品表情包http://m.tkk7.com/zlsunnan/category/5745.html世界L反反覆覆错错落落地飘?来不及叹?生活不是q_^淡E从从容容的东?不能攑ּzh-cnFri, 02 Mar 2007 03:33:14 GMTFri, 02 Mar 2007 03:33:14 GMT60JavaServer Faces in Actionhttp://m.tkk7.com/zlsunnan/archive/2005/12/10/23243.html☆蓝色梦想☆☆蓝色梦想☆Sat, 10 Dec 2005 03:09:00 GMThttp://m.tkk7.com/zlsunnan/archive/2005/12/10/23243.htmlhttp://m.tkk7.com/zlsunnan/comments/23243.htmlhttp://m.tkk7.com/zlsunnan/archive/2005/12/10/23243.html#Feedback0http://m.tkk7.com/zlsunnan/comments/commentRss/23243.htmlhttp://m.tkk7.com/zlsunnan/services/trackbacks/23243.htmlhttp://realzar.5u6.net



☆蓝色梦想☆ 2005-12-10 11:09 发表评论
]]>
选择JSF不选Strutshttp://m.tkk7.com/zlsunnan/archive/2005/12/08/22940.html☆蓝色梦想☆☆蓝色梦想☆Thu, 08 Dec 2005 01:44:00 GMThttp://m.tkk7.com/zlsunnan/archive/2005/12/08/22940.htmlhttp://m.tkk7.com/zlsunnan/comments/22940.htmlhttp://m.tkk7.com/zlsunnan/archive/2005/12/08/22940.html#Feedback0http://m.tkk7.com/zlsunnan/comments/commentRss/22940.htmlhttp://m.tkk7.com/zlsunnan/services/trackbacks/22940.html    ȝ来说Q我在新目中优先考虑JSF。虽然常常有一些商业上的因素迫使我们ؓ现有的项目选择了StrutsQ而且那些解决Ҏq有待考验Q但是,让我们面对一个事实:JSF比Struts好多了?

    下面是我选择JSF而不选Struts的十大理由:

  • 1.Components(lg)
  • 2.Render Kits
  • 3.Renderers
  • 4.Value Binding ExpressionsQ值绑定表辑ּQ?
  • 5.Event ModelQ事件模型)
  • 6.Extensibility(可扩展?
  • 7.Managed Beans(Dependency Injection 依赖注入)
  • 8.POJO Action Methods
  • 9.JSF is the standard Java-based web app framework (JSF是java web应用E序的标准框?
  • 10.There's only one Struts(只有一个Struts)

    10.There's only one Struts(只有一个Struts) Struts 是一个开源品,然而JSF是一个标准。这个细节常常被新的JSF学习者忽略,其实q是显而易见的Q因为我们有多个JSF的实现。虽然JSFq很不成熟,但是我们已经有了2个优U的JSF实现可以选择QSun的参考实现和Apache的MyFaces。另一斚wQ我们只有一个Struts?

    9.JSF is the standard(JSF是标? JEE 5.0要提供一个JSF的实玎ͼq表明JSF不久会无处不在。这可能与你无关Q但是和工具供应商密切相兟뀂现在大概有50个java web应用E序框架Q工具供应商不会情愿L持一个特别的框架Q但是他们会毫不犹U的去支持一个标准。而且不止供应商,开源项目也会迅速的聚集在JSF的四周,争先恐后的去实现相同的功能。比如说Q直到我们去实现本质上和Shale的Tapestry差不多的视图的时候,我才知道Facalets。(从长q来看,我相信这U冗余是件好事,会给我们带来好处Q?

    8.POJO Action Methods Struts的行为是?Struts的APIl定在一LQ但是JSF的行为方法可以在POJPO中实现。这意味着你不用在表单和模型对象之间实C个多余的行ؓ层。顺便说一下,在JSF里面没有行ؓ对象Q行为在模型对象中实现。但是也h意一点:如果你愿意你也可以生成与JSF独立的行为对象。在Struts里面Q你?Form Bean和Action Bean。Form Bean包含数据而Action Bean包含逻辑。OO狂会惛_合ƈ?者,在Struts你办不到。但是在JSF中,你可以分开数据和逻辑Q也可以合ƈC个对象中Q一切由你决定?

    7.Managed Beans(Dependency Injection 依赖注入) 和Spring一PJSF也用了依赖注入QDJQ(或控制反转(IoCQ)d例化和初始化Bean。Struts的确Z生成了Form Bean和Action BeanQ但是JSF可以Z生成各种各样的Managed Bean?

    6.Extensibility(可扩展? q个很重要。JSF?个对象实Cq个框架的大部分功能Q而且你可以很Ҏ的用你自q实现代替原有实现。比如你惛_一个自定义参数在JSF表达式语a里面Q或是添加一个自q视图控制器以便于区分lg和HTML。事实上Shale实现了上面的功能。如果你q没有满IJSF提供了几个地方你可以L的控制JSF的生命周期。Shalel你的会更多?/P>

    5.Event ModelQ事件模型) JSF的事件模型你可以对值改变,动作QJSF生命周期阶段变换{作出反应。在JSF1.1中,那些事g都是在服务器端处理的Q这肯定是一个缺P好在JSF2.0计划支持客户端事Ӟ拭目以待吧?

    4.Value Binding ExpressionsQ值绑定表辑ּQ?在Struts 中,你负责把数据从Form传递到模型对象。你实现的Action的executeҎ是把Form作ؓ一个参数。然后你再手动的把数据从Form Bean里面取出攑ֈ模型对象里面。你要ؓ应用里面的每个Form做这些事情,然而在JSF里面Q你只需像这P#{model.property} 够了,其他的交lJSF来处理?

    3.Renderers 你有看过Struts的标{源代码吗Q它直接生成HTML。JSFlg标签什么都不生成,它和服务器上的一对component-renderer对应。Componentl护lg状态,rendered负责获得视图。重Ҏrenderers是可插拔的,即你可以Ҏ自己需求实现然后替代掉默认实现。比如说我在NFJS上面的Felix谈话中D例说明了怎么dC个自定义的label renderer。你只需要配|你的rendererQJSF׃自动在你的应用程序里面用他?

    2.Render Kits 在几q前我曾l有份Struts咨询工作Q我们必d时支持浏览器和无U设备,非常痛苦。但是用JSF来完成那个Q务非常容易,因ؓ你可以生成你自己的render kitQؓ一U特定显C技术的renderers的集合-然后配置到JSF里面?

    1.Components(lg) lg是Struts和JSF之间最大的区别。就像Swing一PJSF提供丰富的底层构件去开发组件然后添加到标准的组仉。那些底层构件让你很Ҏ的生成自qlgq且和别人共享。现在我们到处都能看到自定义lg跛_来,比如说Oracle的ADF和MyFacesQ两者都提供了丰富的lg集,像 javascript日历Qtree{等。当Ӟlg只是一部分。典型的是,lg都和一个独立的renderer对应Q这l我们带来了真正的好处(看第3 条)。但是和JSF中的很多东西一P你不一定要墨守成规。只要你愿意Q你可以实现render自己的组Ӟ虽然q样你会失去l组件加入别?renderer的能力?



☆蓝色梦想☆ 2005-12-08 09:44 发表评论
]]>
集成 Struts、Tiles ?JavaServer Faceshttp://m.tkk7.com/zlsunnan/archive/2005/12/08/22939.html☆蓝色梦想☆☆蓝色梦想☆Thu, 08 Dec 2005 01:26:00 GMThttp://m.tkk7.com/zlsunnan/archive/2005/12/08/22939.htmlhttp://m.tkk7.com/zlsunnan/comments/22939.htmlhttp://m.tkk7.com/zlsunnan/archive/2005/12/08/22939.html#Feedback0http://m.tkk7.com/zlsunnan/comments/commentRss/22939.htmlhttp://m.tkk7.com/zlsunnan/services/trackbacks/22939.html您是否想?JavaServer Faces (JSF)的强大前端功能、Tiles 的内Ҏ式编排优势和 Struts controller 层的灉|性都加入到您的J2EE Web 应用E序中?企业U?Java 专家 Srikanth Shenoy ?Nithin Mallya 为您展示了如何将q三者的功能集成C赗本文演CZ如何?Struts-Faces集成库中定制cM使得它们可以?Tiles ?JSF 一同用,q用一个实际的例子解释了这个过E背后的基本原理以及如何使用新的一l类的细节?/BLOCKQUOTE>

?Struts、Tiles ?JavaServer Faces (JSF) 一起用,开发h员可以实现易于管理和重用的、健壮的、界面清晰的 Web 应用E序?/P>

Struts 框架推出已经有一D|间了Q它已经成ؓ在开?J2EE Web 应用E序时开发h员所采用的事实上的标准。Tiles 框架是在 Struts 之后不久出现的,它通过为开发h员提供用lgl装展示面的能力开拓了自己的生存环境。JSF ?Web 应用E序框架中最新的成员Q它提供了验证用戯入和处理用户事g的机Ӟ最重要的是Q这是一U以协议无关的方式呈现用L面组件的Ҏ(有关q些 技术的概况Q参见本文相关页面?The major players??

管 Struts ?JSF 中有一些功能是重叠的,但是它们在其他方面vC互ؓ补充的作用。这三种技术的l合可以为开?Web 应用E序、组l其展示和以协议无关的方式呈现定制的用户界面(UI)lg提供一U高效的途径?/P>

Zq行本文中的CZ代码Q需?Struts 1.1、Tiles、JavaServer Faces Reference Implementation (JSF-RI) Early Access Release 4.0 以及 Struts-Faces 0.4。Jakarta 目提供?Struts 1.1 发行版本?Struts ?Tiles 捆绑发布。还可以?Jakarta 目上下?Struts-Faces 集成库。JSF-RI ?Sun ?Web 开发工具包(Web Services Developer Pack)的一部分(?参考资?/FONT>中有q些下蝲和示例代码的链接)?

现在回到集成三种技术的l节上。首先有个坏消息Q在本文发表的时候,q三U技术是不能直接互操作的。好消息是:在本文中Q我们展CZ集成 Struts、Tiles ?JSF 的方法。我们假设您已经了解 Struts ?Tiles。对 JSF 有一些了解会有帮?参阅 参考资?/FONT>中提供的 developerWorks 上的 JSF 教程的链?Q但是不了解也不妨碍Ҏ文的理解?

JSF ?/FONT>

JSF 应用E序是?JSF 框架的普?J2EE Web 应用E序QJSF 框架提供了丰富的 GUI lg模型Q这些模型体C真正?GUI 框架内涵。您可能听h们说q,管某种技术不错,但是它的外观仍然需要改q。是的,?HTML lg构徏qxE无奇的页面的日子已经q去了,如果使用 JSF 的话Q具有更高 GUI 外观的日子就在眼前。您会问Q怎么做呢Q树形组件、菜单组件和囑Ş是已l存在的 UI lgQ这?JSF 一定要提供。更q一步,JSF 通过提供Ҏ使用?API 鼓励创徏自定义组件?/P>

? q里所提到?UI lg?Sun 提供的示例的一部分。像所有规范一P实际的实现由不同的提供商完成?

在传l的使用模型-视图-控制?MVC)?Web 应用E序中,GUI lg是由处理展示和业务逻辑的自定义标记所表示的。这样就出现了必Z编写与客户备打交道的代码”的问题Q这会生重复的代码。?JSF ׃会有q个问题?/P>

JSF l构?展示逻辑 (“什么??UI lg?业务逻辑 (“ؓ什么”和“如何?分离。通过?JSP 面中?JSF 标记Q就可以?renderer ?UI lg兌在一赗一?UI lg可以用不同的 renderer 从而以不同的方式呈现。特定于 UI lg的代码在服务器上q行Qƈ且响应用h作所产生的事件?

JSF-RI 提供了一?render kitQ它带有一个自定义标记库,用以?UI lg呈现 HTML。它q提供了Ҏ需要定制这些组件外观的能力。如果需要特D的lgQ那么可以ؓ特定的客h讑֤构造定制的标记q让它与一个子 UI lg和定制的 renderer 相关联。对于不同的讑֤Q您所需要做的就是指定不同的 renderer?/P>

JSF ?UI lg

您可能已l用 Java AWT 或?Swing API 创徏q?Java GUI 应用E序Q所以您应该熟悉 JSF ?UIComponent (它与 AWT 或?Swing lg很相?。它储存其子lg的树(如果有的?qؓ客户端发生的动作生成标准事gQ例如单M个按钮以提交表单。这些事件缓存在 FacesContext 中。您可以用自定义标记兌每一个这U事件的处理E序。例如,用一个自定义?ActionListener 处理用户单击或者表单提交?

JSF UIComponent ?Renderer 和标记L共同工作的。所?JSP 自定义标记都是通过l承 UIComponentTag 创徏的?doStart ?doEnd ҎL?UIComponentTag cM实现。您只需在这些标记类中提供其他的功能?

?1展示了自定义标记、UI lg?renderer 之间的关pR客h览器访问用 JSF 标记( jsf:myTag )表示 UI lg( MyComponent )?JSP 面。这?UI lgq行在服务器上,q用适当?renderer ( MyRenderer )?HTML 的Ş式呈现给客户。这?JSP 面表现了在 JSF-RI 中用带自定义标记的用户界面lg而不是在 HTML 中对它们q行~码?

例如Q图 1 展示?h:panel:group 标记的用。这个标记用于将一个父lg下面的各个组件组l到一赗如果与?panel_grid ?panel_data q样的其他面板标记共同用,那么它会在运行时生成 HTML 表中的列的标记。JSF-RI-提供?html_basic 标记库用于表C像文本字段、按钮这L HTML lg?


?. 呈现一?JSF 面
Rendering a JSF page

JSF 生命周期

JSF 生命周期包括六个阶段Q一个传入的h可能会经历全部阶D,也可能不l历M阶段Q这取决于请求的cd、在生命周期中发生的验证和{换错误以及响应的cd。JSF 框架处理?JSP 는成的 Faces hQƈq回 faces或?non-faces 响应?

在提交一?JSF 表单Q或者当用户单击指向?URL 中具?/faces 前缀?URL 的链接时Q就会出?faces 响应。所?faces h都由一?FacesServlet 处理 -- q是 JSF 中的控制器?

发送给一?servlet 或者一个没?JSF lg?JSP 面的请求称?non-faces h。如果结果页中有 JSF 标记Q那么它q?faces 响应Q如果没?JSF 标记Q就?non-faces 响应?

JSF 生命周期有六个阶D:

  • 重徏h?
  • 应用h?
  • q行验证
  • 更新模型?
  • 调用应用E序
  • 呈现响应

Ҏ JSF 规范Q每一阶段表示h处理生命周期的一个逻辑概念。不q在 JSF-RI 中,q些阶段是由h对应名字的实际类表示的。下面一节描qC每一阶段是如何对hq行处理q生成响应的。您首先看到的是处理一?faces h所涉及的阶D,然后是处?faces 响应所涉及的阶Dc?/P>

处理 faces h

Z理解 JSF h处理Q请?FlightSearch.jspQ这?清单 1中的一个简单的 JSF 表单。一?JSF 面基本上就是这个样子的。这?JSF 表单有输入文本字D?from?to cities?departure ?return datesQ还有提交和重设表单的按?我们会在E后分析清单1中每一个标记的意义)。现在,假设提交q个表单产生了一?faces h?

q个h?FacesServlet 所接收、ƈ在向客户发回响应之前通过不同的阶Dc??2展示了如何对 JSF hq行处理。让我们看一看这是如何进行的?

1. 接收h
FacesServlet 接收hq从 FacesContextFactory 得到 FacesContext 的一个实例?

2. 委托生命周期处理
FacesServlet 通过对在 faces 上下文中传递的 Lifecycle 实现调用 execute Ҏ生命周期处理委托给 Lifecycle 接口?

3. Lifecycle 执行每一阶段
Lifecycle 实现执行从重建组件树阶段开始的每一阶段?

4. 创徏的组件树
在重建组件树阶段Q用 travelForm 中的lg创徏一个组件树。这个树?UIForm 作ؓ根,用不同的文本字段和按钮作为其子组件?

fromCity 字段有一个验证规则,它规定其不能为空Q如 validate_required 标记所C。这个标记将 fromCity 文本字段与一?JSF Validator 链接h?

JSF 有几个内建的验证器。相应的 Validator 是在q个阶段初始化的。这个组件树~存?FacesContext 中、ƈ且这个上下文会在后面用于讉K树及调用M一个事件处理程序。同?UIForm 状态会自动保存。所以,当刷新这一|Q就会显C单的原始内容?

5. 从树中提取?/B>
在应用请求值阶D,JSF 实现遍历lg树ƈ?decode Ҏ从请求中提取|q在本地讄每一个组件。如果在q个q程中出CM错误Q那么它们就?FacesContext 中排队ƈ在呈现响应阶D|C给用户?

同时Q在q个阶段排队的所有由像单L钮这L用户操作产生的事Ӟ都广播给注册的侦听器。单?reset 按钮会将文本字段中的值重新设|ؓ它们原来的倹{?/P>

6. 处理验证
在处理验证阶D,对在应用h值阶D设|的本地D行所有与各组件相关的验证。当 JSF 实现Ҏ一个注册的验证器调?validate Ҏ时就会进入此阶段?

如果M一w证失败,那么生命周期׃q入呈现响应阶段Q在那里呈现带有错误信息的同一面。在q里Q所有在q一阶段排队的事件同样都会广播给注册的侦听器?/P>

JSF 实现处理源字D上的验证器。如果数据是无效的,那么控制׃l呈现响应阶D,在这个阶D重新显C?FlightSearch.jsp q带有相关组件的验证错误。通过?JSP 面中声?output_errorsQ?/CODE> Q页面中的所有错误都会显C在面的底部?

7. 讄模型对象?/B>
在更新模型值阶D,成功处理了所有验证后QJSF 实现通过Ҏ一lg调用 updateModel Ҏ用有效D|模型对象倹{如果在本地数据{换ؓ由模型对象属性所指定的类型时出现M错误Q那么生命周期就q入呈现响应阶段Qƈ错误显C出来。来自表单字D属性的g填充为模型对象的属性倹{?

8. 可以调用 ActionListener
可以一?ActionListener 与一个用h作,如单L交按钮相兌Q如 清单 1所C。在调用应用E序阶段Q对 FlightSearchActionListener 调用?processAction Ҏ。在实际应用中, processAction Ҏ在调用后会搜索数据以扑և满条g的航班,q从lg?action 属性中提取输出?

在本文提供的q个CZ Web 应用E序中,我们使用了静态数据表C班表。这个方法还提取的 action 属性发送给 NavigationHandler 实现?NavigationHandler 查询 faces-config.xml 文g -- q是 JSF 的默认应用程序配|文?-- 以根据这一输出定下一|什么?

9. 呈现响应 在呈现响应阶D,如果?faces 上下文中没有错误Q就昄由查询配|文件得到的q一?FlightList.jsp。如果是因ؓ前面M阶段的错误而到达这一阶段的,那么׃重新昄带有错误信息?FlightSearch.jsp?

?2. 处理一?JSF h
单击q里以观看该图?


清单 1. FlightSearch.jspQ一个简单的 JSF 表单

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

<f:use_faces>
 <h:form id="flightForm" formName="flightForm" >
   <h:input_text id="fromCity" valueRef="FlightSearchBean.fromCity">
  	<f:validate_required/>
   <h:input_text/>

   <h:input_text id="toCity" valueRef="FlightSearchBean.toCity">
   <h:input_text id="departureDate" 
     valueRef="FlightSearchBean.departureDate">
   <h:input_text id="arrivalDate" 
     valueRef="FlightSearchBean.arrivalDate">

   <h:command_button id="submit" action="success" 
     label="Submit" commandName="submit" >
       <f:action_listener 
         type="foo.bar.FlightSearchActionListener"/>
   </h:command_button>
   <h:command_button id="reset" action="reset" label="Reset" 
     commandName="reset" />

   <h:output_errors/>
 </h:form>
</f:use_faces>

在这D代码中使用了两?JSF-RI 的标记库?html_basic 标记库定义了 HTML lg常用的标讎ͼ?jsf-core 标记库包含用于注册侦听器和验证器的标记。其他标记有Q?

  • f:use_faces 标记?JSF 实现表明后面的标记是 faces 标记?
  • f:validate_required 标记表明它所在的字段(?FlightSearchBean 中是 fromCity 字段)在提交表单时应该有倹{?
  • h:form ?h:input_text 标记分别表示一个名?flightSearchForm ?HTML 表单和各U文本字Dc?
  • h:command_button 标记用于表示提交和重设按钮?
  • 最后, h:output_errors 标记cM?Struts html:errors 标记Q用于显C在表单字段验证中出现的M错误?

一个名?FlightSearchBean ?JavaBean 表示在更新模型值阶D는 UIComponent 数据更新的模型。通常?JSP 中 JavaBean 是用 jsp:useBean 标记声明的。您可能注意C?FlightSearch.jsp 中没有这样做。这是因为可以?JSF 的一个名?Managed Beans 的功能,?faces 配置文g中声明所?JSP 面使用?JavaBeans lg。在开始时Qservlet 容器会初始化q些 JavaBeans lg。faces-config.xml 文g中的 FlightSearchBean 入口如清?2所C:


清单 2. faces-config.xml ?TravelInfoBean入口

<managed-bean>
  <managed-bean-name>FlightSearchBean</managed-bean-name>
  <managed-bean-class>
    foo.bar.FlightSearchBean
  </managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

现在让我们看一看这些阶D|如何处理响应的?/P>

呈现 faces 响应

一?faces 响应是由 Faces 应用E序在生成包?JSF 标记?JSP |生成的。这个响应可以是 JSF 应用E序?faces 或?non-faces 响应?/P>

在我们的例子中,清单 1 中页面的呈现是一?faces 响应。您可能熟悉 Tag 接口?doStartTag() ?doEndTag() Ҏ。在 JSF ?Struts-Faces 中,每一个标记都是从 UIComponentTag 扩展的?UIComponentTag 实现?doStartTag() ?doEndTag() Ҏ?

它还有两个抽象方?getComponentType() ?getRendererType()?/CODE> 通过在具体的标记cM实现q两个方法,可以分别指定组件和 renderer 的类型?

考虑一个带有文本字D늚?JSF 表单。在呈现 JSF 表单时执行以下一pd步骤?/P>

1. 调用 doStartTag() Ҏ
Servlet H口?FormTag 调用 doStartTag() Ҏ?

2. 得到 UIComponent
FormTag ?getComponentType() Ҏ得到?UIComponent?/CODE> UIComponentTag ( FormTag 的父lg)使用 getComponentType() 以从 faces-config.xml 文g中查询这个组件的cdQƈ创徏 UIComponent(FormComponent )的一个实例?

3. 得到 renderer
下一步, FormTag ?getRendererType Ҏ中得到其 renderer 。与lgcd一Prenderer 名是?faces-config.xml 文g中查询的?

4. 调用~码Ҏ
在创Z FormComponent ?FormRenderer 后,?FormComponent 调用 encodeBegin() Ҏ。每一个标记的呈现都由 encodeBegin() 开始、由 encodeEnd() l束?encodeBegin() Ҏ是按嵌套的顺序调用的?

5. l束标记和呈?HTML
servlet 容器Ҏ记调?doEndTag() Ҏ。以嵌套的反序Ҏ一个组件调?encodeEnd() Ҏ。在最后,表单和所有嵌套的lg都呈Cؓ HTML。这ӞHTML q成完毕,q呈现出对应?JSP ?HTML?

?3 昄构成生成 faces 响应的事件序列?/P>

?3. 呈现一?faces 响应
单击q里以查看该图?



回页?/FONT>


Z么将q三者集成ؓ一体?

随着 JSP 和相兌范的不断发展Q像 JSF ?JSP 标记?或?JSTLQ它使用单的标记装许多 JSP 应用E序常用的核心功?q样的新标准正在不断出现。下面是使用集成Z个整体的新技术一些好处:

  • 更清晰地分离行ؓ和展C?/B> 标记?renderer 和组件分,可以更好地定义开发周期中的页面作者和应用E序开发h员的作用?
  • 改变一个组件的展示不会有雪崩效应?/B>现在您可以容易地只对 renderer 作出改变。在传统?MVC 模型中,׃没有q种分离Q对于标记的M改变都需要改变业务逻辑。现在再不需要这样了?
  • renderer 无关性?/B> 也可以说是协议无x,通过对带有多?renderer 的多U展C备重复用组仉辑实现。用不?renderer 的能力得不再需要对特定的设备编写整个表C层代码?
  • l装和重用自定义lg的标准?/B>JSF 的考虑范围出了“表单和字段”,它提供了丰富的组件模型用以呈现自定义 GUI lg。用 JSF 可以定制每一个组件在面中的外观和行为。开发h员还拥有创徏他们自己?GUI lg(如菜单和?的能力,q些lg可以用简单的自定义标记容易地加入CQ?JSP 面中。就?AWT ?Swing 所提供?Java 前端 GUI lg一P我们可以在我们的 Web 而中有自定义的组Ӟ它们使用自己的事件处理程序ƈ有定制的外观。这?Web 层的 GUI 天堂Q?

Struts 是一U已l拥有大量客户基的框架。许?IT 部门认识到这U?MVC 框架的h值ƈ使用它有一D|间了。JSF 没有?Structs q样强大的控制器l构Q也没有像它那样标准化的 ActionForm ?Actions Q及它们声明的能力)。将 Tiles 集成到集合体中,q了自己重复用和以无~的方式改变公司布局的能力?

UL支持 JSF ?Struts 应用E序的挑战是双重的。首先,Struts 标记不是 JSF 兼容的。换句话_它们没有?JSF 规范所规定的那h?UIComponentTag Q所以,JSF 不能解释它们q关联到 UIComponent ?Renderers ?

其次Q在 FacesServlet ?Struts RequestProcessor 之间没有链接。在 Struts 应用E序中, RequestProcessor 负责?ActionForm ?Actions cM的回调方法显C?ActionForm 属性和 validate() ?getter ?setter ?ActionForm 中的回调Ҏ。对?Action Q?execute() 是回调方法。除非调用了 RequestProcessor Q否?Struts ActionForm ?Actions cM的回调方法没有机会调用业务逻辑?



回页?/FONT>


?Struts ?JSF ?Struts-Faces 集成

q里Q您可能会问是否有Y件可以帮助将 Struts ?JSF 集成Q或者是否必自q写集成Y件?/P>

好消息是已经有这L软g了?Struts-Faces 是一个早期发布的 Struts JSF 集成库。这个库是由 Craig McClanahan 创徏的,它得将现有 Struts 应用E序UL?JSF 变得Ҏ?保留了对现有 Struts 投资的h?。Struts-Faces q力图与 JSF q行z的集成Q这样就可以在前端?JSFQ同时后端仍然有熟悉?Struts lg?

?4 展示?Struts-Faces ?JSF cM间的关系。蓝色的cd?Struts-Faces?/P>

?4. Struts-Faces cd
单击q里以查看该图?

下面?Struts-Faces 的主要组Ӟ

  • FacesRequestProcessor c,它处理所?faces h。这个类l承了常?Struts RequestProcessor Qƈ处理 faces h。Non-faces h发送给出其父类 -- RequestProcessor ?
  • ActionListenerImpl c,它处理像提交表单或者单击链接这L ActionEvent 。这个类用于代替?JSF-RI 提供的默?ActionListener 实现。只要在一?faces h中生?ActionEvent Q就会对 ActionListenerImpl 调用 processAction() Ҏ、ƈ?ActionEvents 转送给 FacesRequestProcessor 。这很有意思,因ؓ RequestProcessor 通常只由 ActionServlet 调用以处?HTTP h?
  • FormComponent c,它扩展了 JSF Form lgQ但是是?Struts 生命周期内调用的?
  • FormComponent ?renderer 和标记?
  • 只用于输出的数据标记?renderer Q这里不需要分ȝ件。例如, ErrorsTag ?ErrorsRenderer 用于?HTML 中显C单错误?
  • ServletContextListener 的名?LifeCycleListener 的实现。它用于在初始化时注册相应的 RequestProcessor ?
  • faces-config.xml 文g。这个文件已l捆l在 struts-faces.jar 文g中?

清单 3 展示了?Struts-Faces 标记?FlightSearch.jsp。它cM于在 清单 1中展C的 JSF 例子。这里用_体H出了区别之处。在q里Q您会发现增加了一个新标记?tags-faces。这个标记库定义声明q些标记?Struts-Faces API 所使用?


清单 3. FlightSearch.jsp 使用 Struts-Faces 标记

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-faces" 
  prefix="s" %> 

<f:use_faces>
    <s:form action="/listFlights">
     <h:input_text id="fromCity" valueRef="FlightSearchForm.fromCity"/>

     <h:input_text id="toCity" valueRef="FlightSearchForm.toCity"/>
     <h:input_text id="departureDate" 
       valueRef="FlightSearchForm.departureDate">
     <h:input_text id="arrivalDate" 
       valueRef="FlightSearchForm.arrivalDate">

     <h:command_button id="submit" action="success" label="Submit" 
       commandName="submit" />
     <h:command_button id="reset" action="reset" label="Reset" 
       commandName="reset" />

     <s:errors/>
    </s:form>
</f:use_faces>

s:form 标记用于创徏q个 HTML 表单。表单的 action 属性是 /listFlights而不是像 清单 1那样指定单名 flightForm。在 JSF 中,表单名只是指定给 UIForm 的名字而没有更多的意义?

FlightSearchBean ?JSF 表单的模型,q在更新模型值阶D得到其倹{不q在 Struts 中,表单 action 指向 Struts 配置文g struts-config.xml 中的 ActionMapping 。ؓ了理解它是如何v作用的,q必ȝ一下清?4 中显C的 struts-config.xml 文g?

您会看到 /listFlights ?ActionMapping 表明q个 URI 路径?ActionForm ?foo.bar.FlightSearchForm Q?Action cL foo.bar.FlightSearchAction 。换句话_ ActionForm ( FlightSearchForm )本n是 Struts-Faces 中的 HTML 表单的模型,它的 action 间接地指向这个模?您可以在清单 3 中看到这一点,那里文本字段标记指向 FlightSearchForm 。在普?Struts 应用E序中这会是 <html:text property="fromCity"/> )?


清单 4. ?struts-config.xml 中声?Action

<form-bean  name="FlightSearchForm"
               type="foo.bar.FlightSearchForm"/>

<!-- ========== Action Mapping Definition ========================= -->
<action-mappings>

<!-- List Flights action -->
 <action path="/listFlights"
    type="foo.bar.FlightSearchAction"
    name="FlightSearchForm"
    scope="request"
    input="/faces/FlightSearch.jsp">
    <forward name="success" path="/faces/FlightList.jsp"/>
 </action>

</action-mappings>

您会注意到在 action 属性中~少熟悉?.do。这是因?Struts-Faces 使用表单 action 本n作ؓ表单?它还应该?Struts 配置文g中的 ActionForm 名相匚w)?

集成 Struts ?Tiles 的五个步?/B>

以下五步可以?Struts 1.1 ?Tiles 共同工作Q?
1. 创徏一?JSP 以表C站点的布局。这是主 JSPQƈ带有头、页体和脚的占位符。分别用 Tiles 标记dC JSP 面中?
2. 创徏一?Tiles 定义文gq定义每个集成页面的每个占位W中必须包括哪个 JSP 面。用惟一的名U标识出每一个合成页面定义?
3. ?struts-config.xml 文g中改变全局和本地{发以使用上一步骤中给出的惟一名称而不是别名?
4. 在启动时?TilesPlugIn 装蝲 Tiles 定义文g。将 TilesPlugIn 加入到 struts-config.xml 文g中?
5. ?TilesRequestProcessor Ҏ加到 struts-config.xml 文g中。这是支?Tiles ?Struts 应用E序的默认请求处理程序?

q要注意我们在这里没有?JSF validation 标记。这是因为在 Struts 中,验证是在 ActionForm cM?validate() Ҏ中进行的Q有可能是通过使用 Commons-Validator?s:errors 标记cM?Struts 错误标记q用于显C在验证时出现的错误消息?

另一件要注意的事情是没有 ActionListener 昑ּC提交按钮相关联。这是因为在 Struts-Faces 中已l提供了 ActionListener q且L?faces h?ActionEvent s 一同{交给 FacesRequestProcessor Q在那里Ҏ struts-config.xml 文g请求分z相应?Action cR?



回页?/FONT>


Struts 应用E序UL?JSF

Z?Struts Web 应用E序?JSF 集成Q遵循以下步骤:

  • ?struts-faces.jar 文g与特定于 JSF ?JAR(jsf-api.jar、jsf-ri.jar) d?Web 应用E序?WEB-INF/lib目录中?
  • 如果准备使用 JSF ?JSTLQ则特定于 JSTL ?JAR(jstl.jar、standard.jar)d?WEB-INF/lib 文g夹中。这一步只有在部v到常?Tomcat 时才会需要。JWSDP 已经提供了这?JAR?
  • 修改 Web 应用E序部v描述W?( /WEB-INF/web.xml)以便有一?Faces Servlet , 如清?5 所C?
  • 修改 JSP 面以?JSF ?Struts-Faces 标记而不?Struts 标记。特别是?Struts-Faces 相应标记替换 html、b ase?/CODE> form ?errors 标记。用 JSF 相应标记替换 text ?textarea ?radio 标记。Struts-Faces 没有单独针对q些的标记。尽没有要求,但是您可能还会考虑?JSTL 标记替换 Struts Logic 标记?
  • 对于每一个?JSF 标记?JSPQ修?struts-config.xml 文g以在指向?JSP ?Action Mapping 中的 global-forwards?local-forwards中加入前~ /faces?
  • 如果 Web 应用E序使用了Q何您创徏的自定义lgQ那么您需要用 JSF 实现的默?RenderKit 注册它们。可以通过?WEB-INF 文g中创Z?faces-config.xml 文g、ƈ增加每一个组件和 renderer 的项做到q一炏V不q,要记?faces-config.xml 文g已经l定?struts-faces.jar 文g中了。您必须?struts-faces.jar 文g中提出它、加入自q内容q将它放?WEB-INF文g夹中?

清单 5. ?web.xml 中声?FacesServlet

<!-- JavaServer Faces Servlet Configuration -->
<servlet>
<servlet-name>faces</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<!-- JavaServer Faces Servlet Mapping -->
<servlet-mapping>
  <servlet-name>faces</servlet-name>
  <url-pattern>/faces/*</url-pattern>
</servlet-mapping>



回页?/FONT>


集成 Struts-Faces ?Tiles 的挑?/FONT>

Struts-Faces 库提供了 Struts ?JSF 之间的一个高效的桥梁Q得在 J2EE Web 应用E序中拥有丰富的表示层成为现实。您可以通过在组合体中添?Titles 使表C层更丰富,q样不仅得到?Struts ?JSF l合的好处,而且q可以高效地重复使用不同?JSP 面Q因为它们将由可以根据需要添加或者删除的lg部分或?tiles 所构成?/P>

本文已经展示?Struts ?JSP 的集成,您会惛_ Tiles 加入到组合中只是事一桩,是不是?

不幸的是QJSF 仍然处于早期阶段Q还没有l出最后的发布。基于这一考虑QStruts-Faces 集成软g开发仍然在不断地发展以包括 JSF 的不同的功能Qƈ且还没有支持 Tiles?/P>

Struts ?Tiles 可以无缝地共同工作,但是在集成之路上您会遇到路障。在下面几小节中Q您会看到在?Tiles 共同使用 Struts-Faces 集成库时l常遇到的问题的汇怅R对于每一个问题,我们详细说明了一个修?Struts-Faces cȝ解决Ҏ。我们将用一个航班搜索示例解释这个解x案?/P>

清单 6 展示了航班搜索页面的布局。注意我们称它ؓ航班搜烦面而不?FlightSearch.jsp。这是因?FlightSearch JSP 是用户在 foobar 旅行 Web 站点看到的合成页面的M?/P>

现在Q我们保持实际的 FlightSearch.jsp 不变。我们将随着q展改变它。在您这边,也需要用航班搜烦늚定义创徏一?Tiles 定义文g。清?7(紧接着清单 6)展示?Tiles 定义文g中航班搜索页的一V注意对带有 extends 属性的d局模板的重复用?

在清?6 ?7 后是每一个可能的挑战?/P>
清单 6. 航班搜烦例子?Tiles 布局

<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-faces"prefix="s" %>

<!-- Layout component parameters: header, menu, body, footer -->
<s:html>
<head>
  <title> <tiles:getAsString name="title"/></title>
  <s:base/>
</head>
<body>
  <TABLE border="0" width="100%" cellspacing="5">
    <tr>
     <td><tiles:insert attribute="header"/></td>
    </tr>

    <tr>
     <td><tiles:insert attribute="body"/></td>
    </tr>

    <tr><td><hr></td></tr>

    <tr>
     <td><tiles:insert attribute="footer" /></td>
    </tr>
  </TABLE>
</body>
</s:html>



清单 7. 航班搜烦늚 Tiles 定义

<!-- Master Layout definition  -->
<definition name="foobar.master-layout" 
  path="/faces/layout/MasterLayout.jsp">
      <put name="title"  value="Welcome to Foo Bar Travels" />
      <put name="header" value="/faces/common/header.jsp" />
      <put name="footer" value="/faces/common/footer.jsp" />
      <put name="body"   value="" />
</definition>

  <!-- Definition for Flight Search Page -->
<definition name="/foobar.flight-search" 
  extends="foobar.master-layout">
      <put name="body"   value="/faces/FlightSearch.jsp" />
</definition>

响应已经提交

q是您在试图讉K航班搜烦表单旉上会看到的第一个问题。小心查看堆栈跟t。您会看到问题出在类 com.sun.faces.lifecycle.ViewHandlerImpl 上。这是一个实C ViewHandler 接口?JSF-RI cR?

?2展示?ViewHandler 所扮演的角艌Ӏ这是一个将h转发l下一늚cR在转发hӞ它不在{发前查响应的状?-- q只有在使用 Tiles 时才会发生,因ؓ Tiles 内部?JSP 面包括在响应内Q?JSF-RI 在第一ơ{发后提交响应、然后试囑ֆơ{发给下面的包?JSP ?Tiles?

要解册个问题,必须创徏一个自定义?ViewHandler 实现Q它检查响应的状态以定它是否提交过。如果响应没有提交过Q那么请求就转发l下一,否则Q就加入hq显C相应的 JSP。我们将创徏一个名?STFViewHandlerImpl 的类Q它实现?ViewHandler 接口q实C所需要的Ҏ renderView()?/CODE> 清单 8 展示?STFViewHandlerImpl 中的 renderView() ҎQ?


清单 8. STFViewHandlerImpl 中的 renderView()Ҏ

RequestDispatcher rd = null;
Tree tree = context.getTree();
String requestURI = context.getTree().getTreeId();
rd = request.getRequestDispatcher(requestURI);

/** If the response is committed, include the resource **/
if( !response.isCommitted() ) {
   rd.forward(request, context.getServletResponse());
}
else {
   rd.include(request, context.getServletResponse());
}

现在您实C自己?ViewHandler Q如何通知 JSF-RI 使用您的 ViewHandler 而不是默认的实现呢?要回{这个问题,必ȝ?FacesServlet 的工作过E?

?Faces 初始化过E中Q?FacesServlet 会让 LifecycleFactory 实现q回 Lifecycle cȝ一个实玎ͼ如清?9 所C:


清单 9. FacesServlet ?Faces 的初始化

//Get the LifecycleFactory from the Factory Finder
LifecycleFactory factory = (LifecycleFactory) 
  FactoryFinder.getFactory("javax.faces.lifecycle.LifecycleFactory");

//Get the context param from web.xml
String lifecycleID = 
getServletContext().getInitParameter("javax.faces.lifecycle.LIFECYCLE_ID");

//Get the Lifecycle Implementation
Lifecycle lifecycle = factory.getLifecycle(lifeCycleID);

Lifecycle 实现对象拥有在呈现响应阶D要使用?ViewHandler 。您可以通过?Lifecycle 实现调用 setViewHandler Ҏ让自q ViewHandler 实现成ؓ默认的?

现在问题变ؓ如何得到默认 Lifecycle 实现Q回{是不需要这样做。只要创Z个新的实现ƈ用一个惟一 ID 注册它,如清?10 所C:


清单 10. 注册自定?ViewHandler ?Lifecycle

//Get the LifecycleFactory from the Factory Finder
LifecycleFactory factory = (LifecycleFactory) 
  FactoryFinder.getFactory("javax.faces.lifecycle.LifecycleFactory");

//Create a new instance of Lifecycle implementation - 
//com.sun.faces.lifecycle.LifecycleImpl
//According to the documentation, factory.getLifecycle("STFLifecycle") 
//should work, but JSF-RI has a defect.
//Hence this workaround of creating a RI class explicitly.
LifecycleImpl stfLifecycleImpl = new LifecycleImpl();

//Create a new instance of our STFViewHandler and set it on the Lifecycle
stfLifecycleImpl.setViewHandler(new STFViewHandlerImpl());

//Register the new lifecycle with the factory with a unique 
//name "STFLifecycle"
factory.addLifecycle("STFLifecycle", stfLifecycleImpl);

您可以看?lifecycleId 编码ؓ STFLifecycle 。实际上不是q样。当您回q头分析 清单 9时就会清楚?FacesServlet 从在 web.xml 文g中声明的上下文参C得到名ؓ javax.faces.lifecycle.LIFECYCLE_ID ?lifecycle IDQ如下所C:


    <context-param>
        <param-name>javax.faces.lifecycle.LIFECYCLE_ID</param-name>
        <param-value>STFLifecycle</param-value>
    </context-param>

因ؓ FacesServlet 取决于其初始化时?Lifecycle 实现Q在 清单 10中展C的代码应该?FacesServlet 初始化之前执行。通过创徏另一?servlet q在 FacesServlet 之前初始化它而做到这一炏V?

但是一U更聪明的办法是实现一?ServletContextListener 接口。这个类声明两个ҎQ?contextInitialized() ?contextDestroyed() Q在 Web 应用E序被创建及 Web 应用E序被销毁之前会分别调用它们。因?清单 10中的代码?contextInitialized() Ҏ中执行,而自定义 ViewHandler 已经用标识名 STFLifecycle 注册?Lifecycle Qƈ且可?FacesServlet 使用?ServletContextListener cLw是?web.xml 文g中声明的Q如下所C:


<listener>
  <listener-class>foo.bar.stf.application.STFContextListener
  </listener-class>
</listener>

q不是注册一个带有自定义 ViewHandler ?Lifecycle 惟一Ҏ。事实上 FactoryFinder 实现了自q发现法以发?Factory 对象Q包?LifecycleFactory 。这些机制按照顺序包括在pȝ属性中查看工厂实现cd的机制、faces.properties file、或?1.3 Services 发现机制( META-INF/services/{factory-class-name} )。不q,我们讨论的这U机制是最Ҏ的,也是最不具有破坏性的一U?

404 Resource Not Found

在解决了提交响应的问题后Q单MQ何一?Tiles 特定的链接或者输入一个会呈现 Faces 响应?URL。在q里Q可以输入显C?FlightSearchForm ?URL?

在这样做了以后,您会得到一?foobar.flight-search - 404 Resource Not Found 错误?foobar.flight-search 是航班搜索页面的 Tiles 定义的名字?FacesRequestProcessor 不能处理 Tiles h(因ؓ它扩展的?RequestProcessor 而不?TilesRequestProcessor )Q所以会得到错误?

册个问题,我们创Z个名?STFRequestProcessor (表示 Struts-Tiles-Faces Request Processor)的新的请求处理程序。现在我们将拯 FacesRequestProcessor 的所有代码到q个新类中。惟一的区别是 STFRequestProcessor l承的是 TilesRequestProcessor 而不是承常规的 RequestProcessor 。这个新?RequestProcessor 可以处理 Tiles h。清?11 详细列出了这?STFRequestProcessor Q?


清单 11. STFRequestProcessor.java

正如您所知道的, Struts 框架?RequestProcessor 是在 struts-config.xml 文g中指定的。将下面的项d?struts-cinfig.xml 文g中后Q?STFRequestProcessor 成为处理程序:


<controller processorClass="foobar.stf.application.STFRequestProcessor" />

表单提交昄q回同一个表?/FONT>

׃ STFRequestProcessor 的作用,q时您就可以览q查看航班页面了。不q,在提交航班搜索表单时Q您会得到返回来的同一个表单,而且没有头和页脚!q且没有验证错误。事实上Q根本就没有q行验证Q?

Z了解到底发生了什么事情,我们用浏览器回到航班面q检?HTML 源代码。您会看到像下面q样的一:


<form name="FlightSearchForm" method="post" 
  action="/flightapp/faces/FlightSearch.jsp">

注意表单 action 是指?JSP 而不是一?.do 的。啊哈!q就是问题!q不是由于同时?Tiles ?Struts-Faces 而带来的新问题,Struts-Faces 的默认行为是?JSP 与表?action 有同L名字。这U行为在有单一?JSP ?如在前面?Struts-Faces 例子?时没有问题?清单 3展示了原来的 FlightSearch.jspQ让我们l箋q像下面q样修改 actionQ?


<s:form action="/listFlights.do>

当然Q光有这U修改ƈ不能解决问题。作了这U改变后Q您׃发现 STFRequestProcessor 不能扑ֈ ActionForm 。显然还需要其他的改变?

不过Q在l箋往下之前,看一下图&#160 5。它昄了在呈现负责 Struts-Faces 表单?faces 时相关的一pd事g。这??3相同Q除了在 FormComponent 中突出显C的Ҏ createActionForm()?/CODE> ?Struts-Faces API 提供?FormComponent cL javax.faces.component.UIForm 的特D子c,它支持请求或者会话范围的表单 Bean?

?5. 呈现 Struts-Faces 响应
单击q里以查看该图?

正如您所看到的, createActionForm() Ҏ使用 action 名以?Struts 配置文g中得?ActionMapping 。因为没有对?/listFlights.do ?ActionMapping Q所?Struts 不能扑ֈ ActionForm?/CODE>

q个问题的解x法是使用 org.apache.struts.util.RequestUtils ?RequestUtils 中的 static Ҏ getActionMappingName() h_的智能解析映到正确 ActionMapping 的\? /x/y/z)或者后~( .do)?

清单 12 以粗体显C对 createActionForm Ҏ的改变。我们没有对 Struts-Faces 中的 FormComponent 作这些改变,而是通过l承 FormComponent q覆?createActionForm() Ҏ创徏了一个新?STFFormComponent?/CODE>


清单 12. FormComponent 中修改过?createActionForm() Ҏ

// Look up the application module configuration information we need
ModuleConfig moduleConfig = lookupModuleConfig(context);

// Look up the ActionConfig we are processing
String action = getAction();
String mappingName = RequestUtils.getActionMappingName(action);
ActionConfig actionConfig = moduleConfig.findActionConfig(mappingName);
....
....

Ҏ?STFFormComponent q要作一Ҏ变。Struts-Faces ?action 名本w作单名。这需要改变,因ؓ action 带有后缀 .doQ而表单名没有后缀 .do。所以我们在 STFFormComponent 上增加一个名?action 的新属性,q覆?getAction() ?setAction() Ҏ?

FormRenderer 的改?/FONT>

必须?FormRenderer (?HTML 格式呈现 Struts-Faces 表单的类)?encodeBegin Ҏq行cM?清单 10所C的修改?

同样Q通过l承 FormRenderer 做到q一炏V此外,q必L变写出到 HTML 的表?action。清?13以粗体详l列Zq些改变Q?


清单 13. FormRenderer 的改?/B>

protected String action(FacesContext context, UIComponent component) {

    String treeId = context.getTree().getTreeId();
    StringBuffer sb = new StringBuffer 
      (context.getExternalContext().getRequestContextPath());
    sb.append("/faces");

    // sb.append(treeId); -- This is old code, replaced with 
    // the two lines below.

    STFFormComponent fComponent = (STFFormComponent) component;
    sb.append(fComponent.getAction());
    
    return (context.getExternalContext().encodeURL(sb.toString()));
}

FormTag的改?
正如您已l知道的Q当lg?renderer 改变Ӟ标记也必L变。在q里Q通过l承 Struts-Faces 中的 FormTag 创徏一个新的标讎ͼ STFFormTag 。不必改变Q何功能,只要覆盖 getComponentType() ?getRendererType() Ҏ。清?14 展示了从 STFFormComponent 覆盖的方法:


清单 14. FormTag 的改?/B>

public String getComponentType()
{
    return ("STFFormComponent");
}

public String getRendererType()
{
    return ("STFFormRenderer");
}

修改 faces-config.xml 文g

自定义组件和 renderer 必须?faces-config.xml 文g中声明,q样 JSF 框架才可以初始化q用它们。现在我们已l创Z一个新lg STFFormComponent 和一个新 renderer STFFormRenderer ?

现在我们在 faces-config.xml 文g中增加一个声明,如清?15 所C?component-class 是组件的完全限定cd?component-type 指的是在 STFFormTag ( 清单 12)中用于标识组件的名字。以cM的方式发现和解释 renderer。注?faces-config.xml 文g是在 struts-faces.jar 文g中的。从 struts-faces.jar 文g中取个文件ƈ它攑ֈ Web 应用E序?WEB-INF文g夹中q修改它?


清单 15. ?faces-config.xml 中声明自定义lg?renderer

<faces-config>

  <!-- Custom Components -->
  <component>
    <component-type>STFFormComponent</component-type>
    <component-class>
      foobar.stf.component.STFFormComponent
    </component-class>
  </component>
  ..
  ..
  ..
  <!-- Custom Renderers -->
  <render-kit>

    <renderer>
      <renderer-type>STFFormRenderer</renderer-type>
      <renderer-class>
        foobar.stf.renderer.STFFormRenderer
      </renderer-class>
    </renderer>
    ..
    ..
    ..
  </render-kit>
</faces-config>

修改 struts-faces.tld 文g

您不会在q个CZ Struts-Faces 应用E序中看?struts-faces.tld 文gQ它打包C struts-faces.jar 文g中。打开q分析这个文件。它声明了一个名?org.apache.struts.faces.taglib.LifecycleListener 的类Q这个类实现?ServletContextListener q初始化 FacesRequestProcessor ?

因ؓ希望使用新的 STFRequestProccessor Q所以必dq个文g?struts-faces.jar 文g中删除,它攑ֈ Web 应用E序?WEB-INF 文g夹中Qƈ删除侦听器声明。如果让q个 tld 文g保持原样Q那么在初始化这?Web 应用E序Ӟ除了 STFRequestProcessor Q还会实例化一?FacesRequestProcessor?/CODE>

修改 base href 标记
现在Q您已经完成?Struts、Tiles、JSF 集成的最困难的部分了。您甚至可以览航班搜烦面Qƈ输入搜烦标准查看航班列表。现在试着从航班列表页面返回航班搜索表单。您会得C?HTTP 400 错误。这个错误的原因?HTML base href 标记。它被设|ؓ Master Layout 面?


<base href=
  "http://localhost:8080/stf-example/faces/layout/MasterLayout.jsp" />
           |_________|       |_____________________|
              Context               Servlet Path

E序所有页面浏览都是相对于布局面计算的。如果加入的 base href 标记只达?Web 应用E序上下文则会很方便Q像q样Q?


<base href="http://localhost:8080/stf-example/" />

我们可以通过定制 Struts-Faces BaseTag 做到q一炏V这个类中的改变相当微不道。只d base href 中去?HttpServletRequest.getServletPath() ?

因ؓq些改变是与昄相关的,所以ؓ它创Z一个名?STFBaseRenderer 的新 renderer。这个新标记UCؓ STFBaseTag Q它声明 STFBaseRenderer 作ؓ其关联的 renderer。不需要新的组件?

有了q些信息Q通过l承 BaseTag q覆?getRendererType Ҏ创徏新的 STFBaseTag Q如下所C:


public String getRendererType()
{
    return ("STFBaseRenderer");
}



回页?/FONT>


到目前ؓ止所作的改变

恭喜Q经q这些相对较的修改Q您已经成功地集成了 Struts、Tiles ?JSFQƈ保留了您以前在这些技术上所做的所有投资。本文演CZ如何?JSF 强大的前端能力?Tiles 的内Ҏ式编排优势以?Struts 控制器层的灵zL结合在一个包中,使得创徏一?J2EE Web 应用E序成ؓ一ҎҎ的Q务?/P>

我们讨论了定?Struts cM便与 JavaServer Faces ?Tiles 框架形成紧密集成的工作关p,包括下面q些修改和增加:

  • 新的 ViewHandler Q用于检查提交的响应?
  • 新的 ServletContextListener Q用于创建新?Lifecycle 实现q注册这个定制的 ViewHandler?/CODE>
  • 新的 RequestProcessor Q用于处?Tiles h?
  • 修改q的 web.xml 文gQ声明新?ServletContextListener ?JSF Lifecycle ID?
  • 新的 FormTag?/CODE> FormComponent ?FormRenderer cR?
  • 新的 BaseTag ?BaseRenderer cR?
  • 修改q的 faces-config.xml 文gQ它声明了新的组件和 renderer?
  • 修改q的 struts-faces.tld 文gQ不声明侦听器?

希望它可以概括本文中使用的复合技术,最重要的是Q我们ؓ您提供了?Struts、Tiles ?JavaServer Faces l合到用于构?Web 应用E序的一个强大而灵zȝ机制中的一个oZ服的路线图?BR>代码下蝲



]]>
վ֩ģ壺 ޳ӰԺ߹ۿ| Ѹ߹ۿ| ޹Ʒպav| 鶹˾þþƷ| vvվ| þ޹˾Ʒɫ| ĻþƷƵ| ҹƬ߲| aëƬѧѹۿ| avҹӰ߹ۿ| þþþùƷվ| ޸ľƷ26U| ŮպѲ| պ| ߹ۿѹۿ| ҹƷһ߲ŷ| ĻĻ | ߿Ƭ˳Ƶ | þþƷAV| ѾþþƷþþ| ϼ߿| 99Ƶ߾Ʒѹۿ6| ޾ƷGVͬ| ޵һվ˶| ߾Ʒۿѹۿ| þþƷձľϣ| Ƶ߹ۿƵ| ޾ƷƬþò | ྫƷxxxx| ůůձƵ| avһùŴ| һaƬþ| ޾Ʒ׽þþþþ| 99re6߾ƷƵѲ | 8090߹ۿѹۿ| ɫ͵͵ۺAV | ޳aƬ߲һ | þô| һ| žžŹƷƵ| vaĻþ |