首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

JSP 最佳实践 自定义标记中的错误处理

JSP 最佳实践 自定义标记中的错误处理

回顾我们首先将重复以前的步骤,回顾一下我们在上一期开发的一些代码,但是这次我们将着重发现代码中的错误(或者潜在的错误可能性)。
首先,我们先回忆一下向                  lastModified 标记中添加的新属性                 format 。这个属性允许页面作者传入一个格式字符串,java.text.SimpleDateFomrat类可以使用该字符串来定制最后修改日期戳的格式。虽然这种交互对于大部分JSP页面是必不可少的,但是它也给我们的标记引入了潜在的错误可能性。            
例如,一个页面作者可以轻易地提供一个格式字符串,这个字符串就可能导致一个讨厌的错误消息。如果您想看看得到什么样的消息,可以按照清单1的样子修改您的footer 文件(或者任何其它使用                 lastModified 标记的JSP 页面):            
清单1. 一个无效的格式字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<%@ taglib prefix="site-utils"
            uri="http://www.newInstance.com/taglibs/site-utils"%>
         </td>
         <td width="16" align="left" valign="top"> </td>
   </tr>
   <!-- End main content -->
<!-- Begin footer section -->
   <tr>
     <td width="91" align="left" valign="top" bgcolor="#330066"> </td>
     <td align="left" valign="top"> </td>
     <td class="footer" align="left" valign="top"><div align="center"><br>
         &copy; 2003
         <a href="mailto:webmaster@newInstance.com">Brett McLaughlin</a><br>
         Last Updated: <site-utils:lastModified
         format="PHH:mm a, MM/dd/yyyy"/>
       </div></td>
         <td align="left" valign="top"> </td>
     <td width="141" align="right" valign="top" bgcolor="#330066"> </td>
   </tr>
</table>
<!-- End footer section -->




一个无效参数的例子清单1中格式字符串“PHH:mma, MM/dd/yyyy”中的“P”位置放错了,结果导致一个无效的格式字符串参数。在一个Java 类中,这种类型的错误会导致抛出一个                 IllegalArgumentException 异常。然而,在 JSP 环境中,错误将会传给最终用户,导致类似 所示的错误消息。            
对于页面作者来说,收到和处理这类错误消息是一件非常糟糕的事情。如果错误消息绕过页面作者直接传给最终用户,情况会更糟糕。在最坏的情况下,用户会被站点出现的错误消息吓走并永远不再回来,从而导致站点的知名度、收入和信誉下降――而所有这些对于任何一家公司来说又都是非常重要的。
忽略无效的参数幸运的是,我们可以通过在自定义标记中提供一些基本的错误处理功能来处理这类错误。最简单的错误处理方式是定义默认(或者回撤)行为来忽略无效的参数。在                 lastModified 标记的例子中,我们已经为这种情况创建了错误处理机制的第一部分,方法是为时间戳提供一个默认的格式。然而,最好是将默认值定义为一个常量,然后引用该常量而不要直接将默认字符串赋值给变量。清单2说明了                 DEFAULT_FORMAT 常量是怎样添加到程序中,然后再赋值给                 format            变量的:            
清单2. 为 LastModifiedTag 置一个默认格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.newInstance.site.tags;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.tagext.TagSupport;
public class LastModifiedTag extends TagSupport {
    private final String DEFAULT_FORMAT = "MMM d, yyyy";
    private String format = DEFAULT_FORMAT;
    public void setFormat(String format) {
      this.format = format;
    }
    // doEndTag() method, as seen in previous tips
}




当然,这个默认值可以一直保持不变,也可以通过添加新的格式字符串来修改。如果页面作者用了一个无效的格式字符串,他就会接收到一个错误消息。所以说,除了提供默认行为和一个修改那个行为的机制以外,我们还需要提供一个在使用了无效的格式字符串之后回到默认行为的机制。但是在我们能够修正一个错误之前,需要先捕获它。
Try、catch 和 fix在任何类型的错误处理中,我们都应该在错误的来源处捕获错误,所谓错误的来源是指任何第一次出现问题的地方。在这里,无效的格式字符串将会被传给                            SimpleDataFormat  构造方法,从而导致抛出一个                 IllegalArgumentException 异常。我们把 try/catch 代码块放到构造方法中,如清单3所示:            
清单3. 用于处理无效格式字符串的 try/catch 代码块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.newInstance.site.tags;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.tagext.TagSupport;
public class LastModifiedTag extends TagSupport {
    private final String DEFAULT_FORMAT = "MMM d, yyyy";
    private String format = DEFAULT_FORMAT;
    public void setFormat(String format) {
      this.format = format;
    }
    public int doEndTag() {
      try {
        HttpServletRequest request =
          (HttpServletRequest)pageContext.getRequest();
        String path = pageContext.getServletContext().getRealPath(
          request.getServletPath());
        File file = new File(path);
        DateFormat formatter;
        try {
          formatter = new SimpleDateFormat(format);
        } catch (IllegalArgumentException e) {
          formatter = new SimpleDateFormat(DEFAULT_FORMAT);
        }
        pageContext.getOut().println(
          formatter.format(new Date(file.lastModified())));
      } catch (IOException ignored) { }
      return EVAL_PAGE;
    }
}




注意,                 lastModified 输出现在回到了有                 IllegalArgumentException 异常抛出时的默认字符串。测试这个输出的方法如下,使用新代码重新编译标记,然后重新启动servlet容器,再使用一个无效的日期格式访问页面。这次没有出现讨厌的栈跟踪,您可以看到正常显示的页脚,它以                           DEFAULT_FORMAT  所指定的格式显示最后修改日期和时间。            
结束语希望这一期的提示证明了在自定义标记中包含错误处理机制的重要性。每个新的自定义标记(和属性)都代表一个惟一的JSP平台的扩展,所以对于可能由这个扩展所引起的每一个问题,都应该提供一个惟一解决方案。
要跟着练习在这里学习的内容,可以重写前面写过的自定义标记库。现在再回头看一下,您可能会发现至少有一个或者两个错误情况需要改正。记住您在这里学到的简单的try-catch-fix方法:定位错误的来源,应用某种机制捕获它,然后提供某种行为忽略它。
在下一期的                JSP,我们将完成自定义标记库的学习,转而讨论打包(packaging)。您将了解到怎么将一个或多个自定义标记库打包到一个JAR 文件中,以便于维护、发布以及 Web容器的安装。到那时,我们网上见。
返回列表