快捷搜索:

使用 Translator 模式构建更好的网站

作者:Donald S Bell IBM 的 IT 专家

(本文选自IBM developerWorks中文网站)

本文先容 Translator 模式,并阐明若何在 JSP 技巧和 servlet 情况中应用 Translator 模式。读完本文今后,您将能够使用本文供给的代码示例成功实现这一模式。

在应用 JSP 文件和 servlet 构建 Web 利用法度榜样时,利用法度榜样的界面多数会是 HTML。浏览器翻译后的 HTML 便是一个大年夜型字符串。构成利用法度榜样的营业工具只有少数属性为字符串,另外属性则为日期、数字以致其他营业工具。在构建 Web 利用时,若何将营业工具所包孕的信息转换为浏览器可识别的 HTML 是个大年夜问题。险些每个利用法度榜样都邑以 HTML 款式网络信息,而这些信息又会作为字符串发送给办事器。是以现在还存在若何将所提交的信息转换为营业工具可识别的值这一问题。

Translator 模式经由过程供给一个与 JSP 文件、servlet 和营业工具协同事情的 Translator 工具办理了这两个问题。Translator 工具将三个不合工具结合在一路,从而使每个工具都专用于完成一项给定的义务。Translator 工具之以是可充当这个纽带,是由于它封装了要完成的整个转换逻辑。JSP 文件与 Translator 工具通信,专用于显示信息。这使 JSP 文件变得对照“干净”,即 JSP 文件中险些没有 Java 代码。servlet 专门处置惩罚营业工具的持久性和屏幕之间的导航流。有了 servlet 专门处置惩罚这些义务,JSP 文件就险些不必要 Java 代码了,从而使 JSP 文件变得加倍“干净”。

更具体一点

如前所述,Translator 模式由三个基础部分组成,分手是专用的 Translator 工具、servlet 和 JSP 文件。

JSP 文件的独一职责便是充当用户界面类。这是可能的,由于 JSP 文件从 Translator 工具获取预先款式化好的字符串值(稍后评论争论)。JSP 文件应包孕尽可能少的 Java 代码,由于认真开拓 JSP 文件的网页设计者平日对 Java 编程说话知之甚少,或者干脆就一无所知。使内嵌在 JSP 文件中的 Java 代码尽可能达到起码,这样就使 JSP 文件更像纯 HTML 页面。与整篇都纠缠着 Java 代码的 JSP 文件比拟,纯 HTML 页面的改动要轻易得多。

Translator 工具是一种专用的类,它类似于 MVC 模式中的模型 (model) 类。Translator 工具将营业工具与 JSP 文件中的显示域联系起来。网页设计者将调用 Translator 工具的一个 getter 措施在 JSP 文件中显示动态信息。Translator 工具将返回一个预先款式化好的字符串,是以网页设计者必要做的整个事情便是将它发送到一个输出流中。Translator 工具能够供给此信息,由于它在内部变量中存储着必要显示的整个值。这些变量是由 syncGuiToModel() 和 processForm() 措施设置的。这两个措施专门处置惩罚屏幕和 Translator 之间的信息同步。小组中的 Java 开拓职员认真构建这个 Translator 工具。

着末,servlet 专用于处置惩罚导航流和营业工具的持久性。当 servlet 接管到提交表单时,它将得到 Translator 工具的一个实例,并应用 processForm() 措施将对表单的阐发委派给 Translator 工具。在表单的阐发完成今后,servlet 就会让 Translator 工具应用 syncModelToGui() 措施将营业工具的值同步为表单中所提交的值。在成功转换所提交的值并将它们设置到营业工具上之后,servlet 将对营业工具履行持久化,并向网页造访者显示确认页。

给我显微镜

下面我们仔细查看 Translator 模式的三个部分:JSP 文件、servlet 和 Translator 工具。(本文的示例遵照的是 Servlet 2.1 规范和 JSP 1.0 规范。这些示例是在 WebSphere 3.02 和 WebSphere 3.5 情况下构建和测试的。)

JSP 文件

应用 Translator 模式的范例 JSP 输入表单如下所示:

Borrower Last Name:

"

value="">

在 Translator 模式中,所有表单都是 JSP 文件,而非 HTML 文件,以是输入域的值可所以动态的。这一点很紧张,由于我们网站的造访者是实其着实的人,他们会犯输入差错。比让网站看护您它不吸收您的输入更糟糕的独逐一件工作是,让它看护您它不吸收您在某个域中输入的内容,并要求您从新键入其他 20 个域,由于某个法度榜样员正忙于反省股市报价,没有光阴来前进输入表单的用户友好性。在 Translator 模式中,输入表单的每个输入域的值都是动态设置的,是以假如因存在输入差错而必要向网站造访者从新显示输入页,他们就会看到凸起显示的差错,但其他输入项仍旧保留。

请记着,JSP 文件是由对 Java 代码知之甚少或一无所知的网站设计者编写和掩护的。鉴于这个缘故原由,我们盼望 JSP 文件包孕尽可能少的 Java 代码。但我们在上一段的阐明听起来似乎必要编写大年夜量的 Java 代码。该 JSP 文件示例只有少量 Java 代码,但它们主要位于表达式 () 中。它们能够应用这些浩繁的功能,由于 JSP 文件从它的超类 com.ibm.igs.ispkcm.translator.JspBase 中承袭了这些代码,并将大年夜量代码放在 Translator 工具中。

在此 JSP 文件中,要留意的第一点是它有一个 page 指令标记。这是由于它必要承袭一个超类,并必要导入两个类。JSP 文件承袭了超类 com.ibm.igs.ispkcm.translator.JspBase,由于 JspBase 包括一些很好的实用函数,它使得 JSP 文件可包孕更少的代码。该 JSP 文件所用的主要实用函数是 displayErrors() 和 highLightErrors()。该 page 指令导入 LoanTranslator 和 Hashtable,由于 JSP 文件中引用了这两个类,导入这两个类是为了今后在此 JSP 代码中引用这两个类时不必应用它们完全限制的类名。以下代码显示了 import 语句的一个示例:

JSP 文件中第一行真正的 Java 代码获取 Translator 工具的一个实例,然后获取一个 Hashtable,此中存储着属于 Translator 工具的那个实例的差错。由于 JSP 文件(在编译后)是一个 servlet,以是它是一个无状态的办事工具。Translator 工具将在特定 JSP 文件或 servlet 的不合来回之间掩护需要的状态信息。状态信息应仅限于网站造访者输入的值和要向网站造访者显示的任何处置惩罚差错。由于 Translator 工具的每个实例都与一个特定的网站造访者相关联,以是 JSP 文件调用 Translator 工具的 getInstance(HttpServletRequest) 措施。因为为该措施通报的是一个 HttpServletRequest 工具,以是该措施将能够检索与该网站造访者的 HttpSession 相关的 Translator 实例。

在此 JSP 文件示例中,网站造访者将在表单的顶部看到所有处置惩罚差错。用来显示这些差错消息的 HTML 是应用表达式输出的。displayErrors() 措施是从 JSP 文件的超类 JspBase 中承袭而来的。有了 displayErrors(),用于显示差错消息的所有逻辑都被集中在一路,从而简化了掩护事情。

下面这段代码模板适用于表单上的每个输入域:

Borrower Last Name:

"

value="">

highLightErrors() 是从 JSP 文件的超类 JspBase 中承袭而来的。假如某个输入域有差错,该措施将凸起显示该输入域的标签。该措施接管两个参数:String 和Hashtable。该 Hashtable 是此中存储着从 Translator 的实例检索而来的差错的 Translator。String 是正在反省其是否有差错的输入域的名称。假如存在与该域相关的差错,highLightErrors() 就会返回凸起显示此输入域的标签的 HTML。

在此代码模板中,须留意的紧张一点是:INPUT 标记的 name 属性是由一个表达式设置的,该表达式应用 LoanTranslator 工具的 BORROWER_LAST_NAME 常量。由于在 JSP 文件中引用此域名时应用了一个常量,以是 Translator 工具和 servlet 的调试变得加倍轻易。应用常量更为轻易,由于无论何时开拓职员变动此域的名称,他们都邑得到一个编译差错,而非运行时差错。查找编译差错要轻易得多,由于编译器会急速指出差错,而运行时差错到调试和测试时代才能被发明。

有关此代码模板的着末一个(也是最紧张的一个)留意事变是:INPUT 标记的 value 属性是由一个表达式设置的,该表达式应用了 Translator 的一个 getter 措施。value=" 这行代码是此模式最紧张的部分之一,由于它便是使输入域的值缺省为网站造访者最初输入的值的代码。经由过程将此值缺省设置为网站造访者最初输入的值,造访者就能看到他最初输入的内容,并很轻易地修正他的差错。这节省了网站造访者的光阴,并能使其得到更好的用户体验。

servlet

下面是一个范例的简化 servlet:

public void doPost(HttpServletRequest request, HttpServletResponse response)

{

// 缺省设置是应用户返回输入页。

String sRedirect = LOAN_JSP;

// 获取 Translator 的精确凿例

LoanTranslator ltTrans = LoanTranslator.getInstance(request);

// 现在有了 Translator 的一个实例

ltTrans.processForm(request);

// 获取 Loan 的精确版本的逻辑

Loan lnTheLoan = null;

if (ltTrans.isNew () == true)

{

// 创建新 Loan

}

else

{

// 得到现有的 loan

}

// Sync the Loan object values to values in the submitted form.

ltTrans.syncModelToGui(lnTheLoan);

// 确保未呈现任何差错

if (ltTrans.hasErrors() == false)

{

// 提交 Loan 信息,然后将重定向设置为精确的尾随页

sRedirect = LOAN_CONFIRMATION;

}

// 将网站造访者重定向为当前人为。

try{

response.sendRedirect(sRedirect);

}

catch (Exception e)

{

// 差错逻辑

}

}

servlet 的主要用途是节制 JSP 文件之间的导航流以及对营业工具履行持久化。此 servlet 的代码很简单。

servlet 履行的第一个操作便是从 HttpServletRequest 中获取 Translator 工具的一个实例。

随后 servlet 应用 processForm() 措施将对所提交的 HTML 表单的处置惩罚委派给 Translator。

在 Translator 阐揭橥单之后,servlet 将确定是否必要从第二存储中创建或检索营业工具(示例中的 Loan)。

在 servlet 拥有营业工具的一个实例之后,servlet 就会调用 Translator 工具的 syncModelToGui()。syncModelToGui() 随后将网站造访者提交的整个值转换为营业工具可识别的值。

在 Translator 完成值的同步之后,servlet 将反省当试图转换网站造访者输入的值时,Translator 是否记录了任何差错。

假如没有记录任何差错,servlet 就会将网站造访者重定向到确认页(平日是另一个 JSP 文件,它同样能显示来自 Translator 的值)。

假如记录了差错,servlet 就将网站造访者重定向到输入表单,这样他就可以修正差错。

Translator 工具

由于 Translator 工具是 JSP 文件、servlet 和营业工具之间的联系纽带,以是要求它是有状态的,并且要求它在 HTTP 哀求(或线程)之间掩护状态。为了相符这个标准,Translator 工具必要起到类似伪孤子 (pseudo singleton) 那样的感化。Translator 类有五个主要部分,别的还有一个前面不曾说起的 Object Translator 类库。

getInstance()

syncGuiToModel()

多少 getter 措施

processForm()

syncModelToGui()

Object Translators 库

为了调用 Translator 工具的一个实例,调用法度榜样必须调用静态措施 getInstance(HttpServletRequest)。getInstance() 措施将确定是否应返回 Translator 的一个新实例,或者是否应从 HttpSession 中重用某个实例。该措施经由过程查看定制参数 action 来实现这一点。此参数是随 HTTP 哀求(例如,http://localhost/registerLoan.jsp?action=new)一路通报的。下面的样例代码段显示了 getInstance() 的内容:

public static LoanRegistrationTranslator getInstance(HttpServletRequest request)

{

// 声明返回值变量。

LoanRegistrationTranslator lrtRV = null;

// HttpSession 是必需的,是以在此处将它提掏出来。

HttpSession session = request.getSession();

// 从 request 工具中检索 action 参数。

String sAction = parseString(request, ACTION);

// 确定我们要返回哪种 Translator。

if (ACTION_PROCESS.equals(sAction) == true)

{

// 由于 action 参数被设置为 process,这表示我们正在处置惩罚一个现有的

// Translator,以是从 HttpSession 中将这个 translator 提掏出来。

lrtRV = (LoanRegistrationTranslator)

session.getValue(HttpSessionValueKeys.LOAN_REGISTRATION_TRANSLATOR);

}

else if (sAction == null || "".equals(sAction) == true ||

ACTION_NEW.equals(sAction) == true)

{

// 因为未设置或根本未通报 action,以是缺省操作是创建一个新的 translator。

// 另一种可能是 action 为 "new"

lrtRV = new LoanRegistrationTranslator();

session.putValue(HttpSessionValueKeys.LOAN_REGISTRATION_TRANSLATOR, lrtRV);

}

else

{

// 因为 action 不满意前面的任何反省,即 action 值是位于帮助存储器中的

// 一个现有 Loan 的 ID,以是此次创建一个 LoanRegistrationTranslator,

// 其值被预设为已保存的 loan 中的值。

lrtRV = new LoanRegistrationTranslator(sAction);

session.putValue(HttpSessionValueKeys.LOAN_REGISTRATION_TRANSLATOR, lrtRV);

}

// 返回 Translator 工具的一个实例。

return lrtRV;

}

对付要在 JSP 文件中显示的每个营业工具值,Translator 都供给了一个 getter 措施。这些 getter 措施由 JSP 文件调用。必须在 JSP 文件中显示的每个营业工具属性都有一个 getter 措施。getter 措施老是返回一个 String。返回的 String 值已被预先款式化,以便直接在 JSP 文件中显示。预先款式化 String 是为了使 JSP 文件中的 Java 代码尽可能少。对这些值的款式化改为在 syncGuiToModel() 中进行。

Translator 应用 processForm() 清除曩昔显示的差错,并从提交的表单中阐发此信息。当 servlet 接管到一个提交的表单时,它就会将对该表单的处置惩罚委托给 Translator。在本委托时代,Translator 阐发提交表单的值,并将这些值分手存储在 String 变量中。这些存储变量随后经由过程 syncModelToGui()(由 servlet 调用)转换为营业工具的值。

syncGuiToModel() 和 syncModelToGui() 是两个类似的措施,顾名思义,此中一个措施按某个偏向对值履行同步,而另一个措施按相反的偏向履行同步。syncGuiToModel() 从营业工具的属性中提取这些值,并应用 Object Translator 预先款式化每个属性值。Object Translator 将值预先款式化为要在屏幕上显示的值。随后,它将 Translator 的对应 String 变量设置为这个值。syncModelToGui() 履行的操作相同,但偏向相反。下面是从范例的 syncGuiToModel() 中摘出的一小段代码:

DoubleTranslator dtDouble = new DoubleTranslator();

String sTemp = dtDouble.translate(loan.getInterestRate());

setInterestRate(sTemp);

为了使转换代码具有最大年夜的可重用性,并为全部站点供给一种合营的转换,syncGuiToModel() 和 syncModelToGui() 应用的都是 Object Translator 类。Object Translators 与 Translator 工具联系得如斯慎密,乃至于险些可将它们看作是 Translator 工具的规则。Object Translator 类是一个简单的类,它的独一用途便是将一种数据类型转换为款式化字符串,以及将款式化字符串转换为它的数据类型。下面是一个很简单的 Object Translator 类的代码:

public class DoubleTranslator extends ObjectTranslator

{

public String translate(double doubleValue)

{

return Double.toString(doubleValue);

}

public double translate(String stringToBeTranslated) throws Exception

{

double dRV = 0.0;

try{

Double dbDouble = Double.valueOf(stringToBeTranslated);

dRV = dbDouble.doubleValue();

}

catch(Exception e)

{

Exception eTranslation =

new Exception("Please enter a numeric value like 1.0 or 1.25");

throw eTranslation;

}

return dRV;

}

}

当这个样例 Object Translator 将 double 转换为款式化的 String 时,它只需调用 Double.toString()。这个措施可实现更强大年夜的功能,例如,可以添加几行代码,使相宜款式化类似 1000.25 这样的大年夜 double 值时,可预款式化这个值,以便显示为 1,000.25。

对付 DoubleTranslator.translate(String),须留意的紧张一点是,它会发出一个可读性很好的非常,而不是标准的 Java.lang.NumberFormatException 非常。JSP 文件将此非常的消息直接显示给网站造访者,是以,让网站的通俗造访者很轻易地舆解该措施发出的非常是异常紧张的。

小结

应用 Translator 模式框架的优点很多,不仅可以低落网站的资源,而且可以前进用户的知足度。因为不合组件都只履行专门的义务,因而网站的构建资源低落了。这些专门义务分配给临盆小组,如 HTML 小组或 Java 法度榜样员小组。由于 Translator 模式的 ObjectTranslators 在全部网站重用,所有整个款式化和阐发都因此相同的要领进行的。由于每项义务都以相同的要领完成,以是网站造访者就能够以同等的要领查看全部网站的信息。这进一步前进了用户的知足度。

参考资本

下面的 developerWorks 教程可赞助您进一步懂得 servlet 和 JSP 文件:

Building Java HTTP servlets

Building servlets with session tracking

Introduction to JavaServer Pages technology

作者简介

Donald Bell 是 IBM 举世办事中间的 IT 专家,他为客户供给有关基于 Web 的技巧利用指示。可以经由过程 bellds@us.ibm.com 与他联系。

您可能还会对下面的文章感兴趣: