使用Translator模式构建更好的网站2
发布时间:2010/11/24 17:34:14 来源:www.xue.net 编辑:城市总裁吧
请记住,JSP 文件是由对 Java 代码知之甚少或一无所知的网站设计者编写和维护的。鉴于这个原因,我们希望 JSP 文件包含尽可能少的 Java 代码。但我们在上一段的说明听起来好像需要编写大量的 Java 代码。该 JSP 文件示例只有少量 Java 代码,但它们主要位于表达式 (<%= x %>) 中。它们能够使用这些众多的功能,因为 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 语句的一个示例:
<%@ page extends="com.ibm.igs.ispkcm.translator.JspBase"
import="com.ibm.developerworks.translatorpattern.LoanTranslator,
Java.util.Hashtable"%>
JSP 文件中第一行真正的 Java 代码获取 Translator 对象的一个实例,然后获取一个 Hashtable,其中存储着属于 Translator 对象的那个实例的错误。因为 JSP 文件(在编译后)是一个 servlet,所以它是一个无状态的服务对象。Translator 对象将在特定 JSP 文件或 servlet 的不同往返之间维护必要的状态信息。状态信息应仅限于网站访问者输入的值和要向网站访问者显示的任何处理错误。因为 Translator 对象的每个实例都与一个特定的网站访问者相关联,所以 JSP 文件调用 Translator 对象的 getInstance(HttpServletRequest) 方法。由于为该方法传递的是一个 HttpServletRequest 对象,所以该方法将能够检索与该网站访问者的 HttpSession 相关的 Translator 实例。
<%
LoanTranslator ltLoan = LoanTranslator.getInstance(request);
Hashtable htErrors = ltLoan.getErrors();
%>
在此 JSP 文件示例中,网站访问者将在表单的顶部看到所有处理错误。用来显示这些错误消息的 HTML 是使用 <%= displayErrors(htErrors) %> 表达式输出的。displayErrors() 方法是从 JSP 文件的超类 JspBase 中继承而来的。有了 displayErrors(),用于显示错误消息的所有逻辑都被集中在一起,从而简化了维护工作。
下面这段代码模板适用于表单上的每个输入域:
<%= hightLightErrors(ltLoan.BORROWER_LAST_NAME, htErrors) %>Borrower Last Name:
<INPUT name="<%= ltLoan.BORROWER_LAST_NAME %>"
value="<%= ltLoan.getBorrowerLastName() %>">
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="<%= tLoan.getBorrowerLastName() %> 这行代码是此模式最重要的部分之一,因为它就是使输入域的值缺省为网站访问者最初输入的值的代码。通过将此值缺省设置为网站访问者最初输入的值,访问者就能看到他最初输入的内容,并很容易地修正他的错误。这节省了网站访问者的时间,并能使其获得更好的用户体。
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)
{
// 错误逻辑
}
}