写点什么

用 JSF/DWR/DOJO 创建动态 Web 应用

2007 年 11 月 05 日

摘要

本文给出如何将 JSF、DWR、DOJO 集成在一起来创建丰富 Web 应用(该应用使用 Portlet 和 Facelet)的方法。假定读者对这些框架和它们所提供的特性已有基本的了解。

例子应用

本文中所讨论的例子应用是一个产品管理应用。该应用为期用户提供了如下特性:

  1. 用户可以基于名字搜索一个产品类型
  2. 当用户选择了一个产品,将显示一个带有分隔面板(split pane)的新窗口。该分隔面板左侧以树的形式(就像你在 Windows Explorer 所看到的那样)显示所有属于该产品类型的产品子类型。可能每个产品子类型还有它自己的子类型。分隔面板右侧显示还有如下标签的标签面板(tabbed pane):
  • Products(产品) —— 这个标签页显示属于所选子类型的产品列表
  • Add Product Subtype(增加产品子类型) —— 这个标签页显示一个表单,用来接受给所选产品子类型增加新产品子类输入值
  • 在分隔面板的底部,有一个 back 按钮以便回到搜索产品类型页。
  1. 当某个子类型关联的产品列表显示在分隔面板右侧时,每一页应该只显示 10 个产品。这意味着应该能够对屏幕上的结果进行分页和排序。
  2. 显示在分隔面板左侧的树应该可以展开 / 折叠(expandable/collapsable)而且不应导致页面刷新,这样会增强用户体验。
  3. 鼠标右键点击树上任何一个节点(代表一个产品子类型)应该给用户显示弹出菜单,带有给所选子类增加新产品子类子节点、删除所选产品子类型、用数据库的最新数据刷新所选产品子类的孩子产品子类列表等选项。
  4. 当一个新的产品子类被增加到所选产品子类上后,无需刷新页面,新产品子类应该立刻显示在树上。

图 1 显示了当用户选择一个产品类型 / 子类型时,屏幕上的期望效果。

图 1. 产品子类详细信息窗口

DOJO

创建跨浏览器兼容的树结构、标签面板、分隔面板、弹出菜单等等是耗时的工作,同时这些工作最好是由有经验的 Javascript/DHTML 程序员来完成。有许多工具包支持这些 UI 部件并且是跨浏览器兼容的,但是支持丰富事件处理模型的工具包却不多。以下罗列了一些例子应用需要响应以满足用户需求的用户动作:

用户动作 应用程序响应 选择树节点 显示属于该节点的产品子类列表 右键点击树节点 显示带有增加孩子产品子类、删除所选产品子类等功能的弹出菜单 选择标签面板上的‘增加产品子类型’标签 显示输入新产品子类型信息的表单 当用户点击 [+] 号展开树并察看子节点时 从数据库中装载孩子节点信息并显示在树上 DOJO 工具包是一个 Javascript/DHTML 工具包,它提供了一套丰富 UI 部件(包括但不止限于树、标签面板、弹出菜单),该套 UI 部件带有一个非常适合用于本例子应用的丰富事件处理模型。

DWR

DWR ( Direct Web Remoting ) 是一个简化构建用 Java 编写的 AJAX 应用的 AJAX 框架。DWR 提供了许多特性,包括(但不只限于此):

  • 由 Java 类(开发者创建用来处理 AJAX 请求)创建 Javascript
  • 允许 JSF 管理 bean 作为处理 AJAX 请求的 Java 类
  • 用转换器(converter)对 Javascript 关联数组(associative array)和 Java bean 进行双向转换
  • 用转换器对 Javascript 数组和 Java 集合进行双向转换

转换器在 DWR 中扮演一个十分重要的角色,并提供了一个更整洁的编程模型。例如,如果用户输入新产品子类信息,并需要应用程序保存它,那么在 Web 层有两种方法获得其信息:

  • 用 HttpServletRequest 的 getParameter 方法获得所有关于新产品子类的信息。
  • 创建一个 DTO(数据传输对象) ProductSubtype,其所有产品子类属性都有 getter 和 setter。在 dwr.xml 文件中配置一个转换器将 ProductSubtype 指定为一个bean转换器。在 Javascript 中,简单地创建一个关联数组(associative array)并把它传递给 Java 类(由它来处理 AJAX 请求)中以 ProductSubtype 作为参数的方法。在本例中 DWR 将做由 Javascript 关联数组到 ProductSubtype 的转换,因为 ProductSubtype 在 DWR 中被声明用于bean 转换器。

后一种选择提供了一个更整洁的编程模型,你不必处理获取请求参数及创建一个在 Java 程序中被使用的 DTO。

当 AJAX 请求被处理时,大多数时候需要在 Javascript 回调方法中接收状态编码、消息或一些的数据,以决定给用户显示什么、不显示什么。Bean 转换器在这种情景下非常方便。

DOJO 的丰富事件模型结合 DWR 处理 Java 应用 AJAX 请求的整洁方法,提供了创建高交互性 Web 应用(类似于例子应用)的一种途径,应用中由 DOJO 组件产生的事件被传递给 DWR 去处理。

问题描述

  1. 在一个 Portal 环境中,开发者不负责为用户界面产生 HTML,界面通过解析符合 Facelet 的 XHTML 文件来产生。即使 JSF 管理 bean 的属性包含 HTML 字符串作为其值,它并不是由 Portal 解析的,而是照原样在用户界面上显示给用户。如何产生可以被 Web 浏览器执行以创建 UI 部件的 DOJO 特定 HTML 呢?
  2. DOJO 提供了丰富事件模型,而且可以在 Javascript 中截获这些事件。DWR 框架可以用来在服务器端接收这些事件,但是服务器端会话状态需要维护在什么地方?
  3. 当树上的节点超过几百个时,在 IE 或 Mozilla 中 Javascript 创建 DOJO 树节点需要花些时间。因此是否这意味着如果节点超过几百个,应用不能在浏览器使用 DOJO 的树部件?
  4. 在 Web 应用中使用 AJAX 后,当窗口上发生用户事件时如何产生 HTML 或 HTML 片断?应该在 Java 代码中编码产生还是从一个外部文件获取?应用程序能否在 AJAX 请求的响应中显示复杂用户界面?
  5. 当使用 AJAX 时,代码可能因使用 HttpServletRequest 的 getParameter(“fieldName”) 方法而变得混乱,难以维护。

解决方案

自定义 JSF 组件

自定义 JSF 组件用来为 DOJO 的树和分隔容器组件产生所需的 HTML。JSF 组件所产生的 HTML 总是由浏览器解析,而不是由 Portal 作为文本输出。下面是 XHTML 的部分内容,展示了如何自定义 JSF 组件用来产生 DOJO 的树和标签面板窗口部件。

<div xmlns="http://www.w3.org/1999/xhtml"<br></br> ...<br></br> ...<br></br> xmlns:dojo="http://dojotoolkit.org/"<br></br> xmlns:mytree="http://mytree.com/tree"<br></br> xmlns:mytab="http://mypane.com/tabPane"><br></br> <ui:composition><br></br> <ui:define name="body"><br></br> <f:view><br></br> <h:form styleClass="form" id="formId"><br></br> <div dojoType="SplitContainer" orientation="horizontal" sizerWidth="5" activeSizing="false" style="overflow:<br></br> auto; whitespace: nowrap; height: 550px; background: transparent; padding: 5px;" ><br></br> <div dojoType="ContentPane" sizeShare="20"<br></br> style="overflow: auto; whitespace: nowrap;"><br></br> <mytree:treeComponent backingBeanName="treeBackingBean"></mytree:treeComponent><br></br> </div><br></br> <div dojoType="ContentPane" sizeShare="80" style="overflow: auto; white-space nowrap;"><br></br> <mytab:tabPaneComponent/><br></br> </div><br></br> </div><br></br> ...<br></br> ...如果树上的节点数很大(超过 200),自定义 JSF 组件不应为多于 200 的节点产生代码。如果节点数超过了 200,在装载页面时 IE 将花费大量时间去创建这些窗口部件。本文例子应用的自定义 JSF 组件只创建 100 个树节点(在根一级上)并在最后显示‘Show more…’选项。当用户选择了‘Show More…’选项,则由 DWR 负责将剩余的节点信息从数据库中取来。该信息接着被传递给 Javascript 回调方法以便用程序创建 TreeNode 窗口部件。

MyFaces 也提供了能产生 DOJO 树的组件,但是 MyFaces 组件一次性创建所有节点,这不是好方法,因为当树上的节点数达到上千时 Web 应用中的组件将变得无法使用。

DWR 和 JSF

DWR 要求你创建 Java 类并将其配置到 dwr.xml 配置文件中。DWR 创建一个 Javascritp 文件(文件扩展名为.js),该文件的名字是在 dwr.xml 中配置的

如下 dwr.xml 配置信息展示了 Java 类是如何被配置的:

<create creator="jsf" javascript="AjaxBean" scope="request"><br></br> <param name="managedBeanName" value="ajaxBean" /><br></br> <param name="class"<br></br> value="com.somebean.AjaxBean" /><br></br> </create>
creator="jsf"这一句说明 Java 类被配置为 JSF 管理 bean。该 Java 类包含所有将由 Javascritp 调用的 AJAX 方法。

<param name="managedBeanName" value="ajaxBean" />这一句说明在 faces-config.xml 配置文件中管理 bean 的名字为 ajaxBean。

<param name="class"<br></br> value="com. somebean.AjaxBean" />这一句说明所引用的实际 Java 类。

javascript="AjaxBean"这一句说明在 Javascript 代码中以此名称使用 Java 类。

为了在 Javascript 中使用 AjaxBean,需要用

2007 年 11 月 05 日 15:482648
用户头像

发布了 150 篇内容, 共 35.6 次阅读, 收获喜欢 2 次。

关注

评论

发布
暂无评论
发现更多内容

程序范式的意义

soolaugust

架构 程序设计

ARTS week 4

锈蠢刀

云上安全工作乱如麻,等保2.0来一下

华为云开发者社区

安全 华为云 等保 云平台 多云服务

一个数据库管理员的自我救赎之路

华为云开发者社区

数据库 华为云 数据库迁移 企业上云 DRS

SpringCloud服务注册中心双节点集群(Eureka集群)

xcbeyond

Java 架构 微服务 Eureka 集群

Java-技术专题-synchronized关键字

李浩宇/Alex

nginx报错worker_connections are not enough

Java联盟

nginx

草脸识别,AI泡沫还是皇冠明珠?

郭华

人工智能 AI 商业 解决方案

影响音视频延迟的关键因素(一):流媒体系统

ZEGO即构

TCP udp RTC HLS RTMP

我的敏捷历程 —— 兼评《敏捷整洁之道 - 回归本源》

FollowFlow

敏捷开发 Agile 极限编程 XP

跨域问题(CORS / Access-Control-Allow-Origin)

xcbeyond

Java CORS 跨域

系统不可用总结

不在调上

Spring 为啥默认把bean设计成单例的?这篇讲的明明白白的

程序员生活志

"工科生"的浪漫 百度大脑语言与知识技术峰会在七夕向你发出参会邀请

百度大脑

钓鱼网站:详解hosts文件

xcbeyond

Java 域名解析 hosts

高效程序员的45个习惯:敏捷开发修炼之道(3)

石云升

读书笔记 敏捷开发 无限游戏

丐帮,少林,明教,武当!看看你数据分析的技能属于哪一派?

程序员生活志

spring Cloud Eureka Rest接口重写

xcbeyond

Java SpringCloud Eureka

如何利用k8s拉取私有仓库镜像

Damon

Docker k8s

写代码爬取了某 Hub 资源,只为撸这个鉴黄平台!

程序员生活志

教程 Hub 资源

nginx 报错 accept4 () failed (24:Too many open files)

Java联盟

nginx

MySQL索引问题探究手记

flyer0126

MySQL 索引

大厂面试必读,JAVA进阶神书《深入理解Java虚拟机》第三版更新内容全曝光!

华章IT

JVM 虚拟机 周志明 Java虚拟机 jvm调优

一个虚拟世界里栽树的公司及其启示

郭华

技术 商业模式 电影

海量并发也没那么可怕,运维准点下班全靠它!

华为云开发者社区

容器 网络 并发 华为云 裸金属容器

错误的存储方案正吞噬你的成本

jinjin

学习的深度 & 深度的学习

北风

学习

为啥PHP in_array(0,['a', 'b', 'c']) 返回为true?

flyer0126

php 弱类型语言

搭载十代酷睿i7处理器,这台ROG冰刃4新锐拥有媲美台式游戏电脑的性能

飞天鱼2017

区块链承兑商支付系统开发,usdt支付系统搭建

WX13823153201

CRM往事丨三件事,所有SaaS的缩影

人称T客

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

用JSF/DWR/DOJO创建动态Web应用-InfoQ