技术开发 频道

用JSTL增强Web应用程序的弹性



【IT168 专稿】

随着脚本语言的流行,它的优点也逐渐显现。大多数脚本语言都具有快速开发和易维护的特性。如果我们想在一天内建立一个动态的网站,一般只需要花数小时学习某种脚本语言就可以完成这些任务。象非常流行的PHP语言(一种类似C语法的脚本语言),就拥有公认的快速开发的能力。

    虽然PHP的精彩特性很多,它也经常被认为是运行最快的脚本语言。但有时也会有些不尽人意的地方,如果这些方面累计起来,可以会造成不小的麻烦。如不加控制地写代码,将会使PHP代码激增,并可能增加维护和调试成本。而且和PHP语句混在一起的HTML标签以及其他的网页元素会大幅度地降低程序的可读性。这些情况在JSP代码中同样存在。因此,最近几年象Struts一样的框架大量涌现。这种框架使用MVC模式将应用程序代码和Web分开,这样可以将Web设计人员和开发人员分开,使他们各尽其职,避免发生冲突。

    象这些框架的做法虽然从表面上看更完美。但它却隐藏着另一个不足,就是增加了学习这些框架的成本。这些成本的增加使一些小型的公司增加的负担。而且对于不大的应用程序使用这些框架可能不切合实际。因此,我们需要找到一些可以快速开发小型应用程序的方法。这些方法之一就是JSP语言中的JSTL。下面我们就来看个究竟。

一、使用JSTL更容易实现Web应用程序

    JSTL是JavaServer Standard Tag Library的缩写,它是JSP的一个超级,JSTL将一些常用且必须的功能封装在四个扩展的标签库中。JSTL的核心思想就是无需写Java代码就可以非常容易地快速建立Web应用程序。这主要是由于一般的Web应用功能被封装了起来。JSP有支持一种表达式语言(EL),这种语言允许非常容易地使用sessions和beans。如下面的表达式:

${sessionScope.driver}

    上面的表达式从session中获得了driver属性。如果在JSP中没有EL,那么将会使用更多的java代码。如使用EL从一个bean中得到一个属性类似于${login.UID},而不使用EL,则代码如下:

<%= ((Login) pageContext.
 getAttribute("login")).getUID () %>
   
   
需要注意的是虽然EL属于JSTL的一部分,但它却可以不依赖JSTL的标签库来运行。JSTL所支持的四个标签库是:内核库(core),这个库主要包含了一些基本的编程指令,如iterations等。用于国际化和格式化的库(internationalization and formatting):这个库允许程序读取和使用一些用于国际化的信息,以及格式化字符串。SQL库:这个库主要通过数据源来连接和操作数据库。XML库:这个库主要来操作XML数据。通过XML库还可以和现在非常流行的AJAX一起使用以达到更好的效果。

    在PHP中也有类似的标签,PHP也正是通过这些技术才使生产率得到大幅度地提高。下面就让我们来看一个简单的PHP页代码。这段代码将大的数据区分成多页显示。代码如下:
 
<?php
include 'config.php';
include 'connection.php';
$query = 'select * from parts';
$result = mysql_query($query) or die(
 'Sorry the query failed');
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
 $temp= "uid :{$row['uid']} <br>Name : {$row['name']}
    <br>" .
      "Description : {$row['description']} <br><br>";
 echo $temp;
 $message=$message.$temp;
 
}
$message=$top.$message.$bottom;
 mail("$to", "$subject", "$message", "$headers");
include 'close.php';
?>


    在上面的代码中,config.php包含了全局变量,connection.php打开一个MySQL数据库连接,close.php并数据加连接关闭。

从名子可以看出,$query表示一条SQL查询语言,我们可以根据需要将其变成其他的查询。如果想更灵活,可以将其保存在一个文本文件中,通过fopen()方法对其进行读取。通过配置文件还可以使数据库管理员无需修改源程序就可对查询进行操作。

    在上面代码的开始处通过调用mysql_query方法执行了查询,并将结果返回给$result,这种方法使用了缓冲,只有当结果全总返回时才生成响应的HTML。当然,我们也可以不使用缓冲的方法。如果这个方法执行失败,我们也可以用PHP将程序引向错误页。PHP是一种支持iteration的语言,我们可以通过Mysql_fetch_array()方法得到结果集的行。$row就代表Mysql表中的每一行。而$message将得到mail的信息。头信息($headers)的内容如下:

$headers =
 "From: $from\nReply-To:
 $replyto\nContent-Type:
 text/html;
 charset=iso-8859-1";


二、  通过自定义JSP Tag增强代码重用性
 
    自定义JSP tag是将Java代码封装在JSP中的最直接的方法,使用这种方法可以大大增强程序的重用性和代码依赖性。如我们经常会遇到在使用SQL返回结果时在一台服务器上没问题,而在另外一台服务器上却出现了编码错误。如果我们查看返回结果的信息头时也许会发现是由于数据库驱动的版本的问题。因此,我们就需要一个友好的界面来调试这些错误。最好的方法是建立一个拥有这样功能的Tag库来满足我们的要求,建立Tag的步骤如下:

1. 写一个tag库定义文件。这个定义文件描述了servlet容器所使用的tag库的语法。Tag的名子使用<tag><name>定义,java类使用<tag><tagclass>定义。其它的定义请看如下代码:
 
<?xml version="1.0" encoding="GBK"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>Article</short-name> <uri>article.tld</uri> <display-name>简单tag实例</display-name> <description>在网页设计器中隐藏代码的tag</description> <tag> <name>debug</name> <tagclass>playground.berg.tag.Debug</tagclass> <info>打印调试信息</info> <bodycontent>empty</bodycontent> </tag> </taglib>

2. 写相应的java类。这些类从javax.servlet.jsp.tagext.BodyTagSupport类继承,并覆盖了doStartTag()方法以便在JSP中产生html代码。在这里需要注意的由于功能的不同,覆盖的也会不同。由于在这里<bodycontent></bodycontent>中的内容已经为empty了,因此,我们只需要覆盖一个方法。类的实现代码如下:

package playground.berg.tag; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.IOException; import java.util.*; public class Debug extends BodyTagSupport { public int doStartTag() throws JspException { JspWriter out = pageContext.getOut(); try { out.println(systemPropertiesAsHTMLTable()); } catch (IOException e) { throw new JspTagException( "Debug tag error: "+e.getClass().getName()); } return SKIP_BODY; } private String systemPropertiesAsHTMLTable(){ String message= "<h3>Checking System Properties.....</h3>"; message+="<table border=1 width=\"80%\" align= \"center\"><tr><td><b>Name</b></td><td>Value </td></tr>\n"; Properties properties =System.getProperties(); Enumeration enumeration = properties.propertyNames(); for (; enumeration.hasMoreElements(); ) { String name = (String)enumeration.nextElement(); String value = (String)properties.get(name); message+="\t<tr><td><b><i>"+name+"</i></b> </td><td><i>"+value+"</i><td></tr>\n"; } message+="</table>"; return message; } }

    上面代码的systemPropertiesAsHTMLTable()方法来枚举所有的系统属性并产生一个HTML表,将这些字符串按name和value的形式存在表中。虽然在程序中使用硬编码是一种不好的习惯,但为了简便起见,在本例中仍然使用了硬编码。但读者在实际项目中可以通过参数将CSS文件名传入,并使用CSS来设置格式。

    这需要提一下的是TLD文件存放的位置,一般我们会将TLD文件放到WEB-INF目录或其子目录中,如果TLD文件放在WEB-INF目录中,那么我们应该在WEB-INF\web.xml文件中加入如下内容:
<taglib> <taglib-uri>article.tld </taglib-uri> <taglib-location> /WEB-INF/article.tld </taglib-location> </taglib>
    我们可以按如下代码来使用这个tag。
<%@ taglib uri= "/WEB-INF/article.tld" prefix= "info" %> <info:debug/>


三、用JSTL进行错误处理

    在进行下面的讨论之前,让我们让来讨论一下错误处理。也许我们曾经很多次在浏览器上看到错误号为500的错误。更令人讨厌的是一些异常跟踪经常会显示出一些毫无意义的信息。或者象PHP一样,只显示一行错误号和方法调用,使人摸不着头脑。但至少它不会显示一大堆令人费解的信息。当然,这些错误发生的原因有很多,如底层构架的异常,网站负载过大。内存异常,数据库连接失败等。
 
    如果这些错误是运行时错误,我们可以使用try catch块对其进捕捉,并打印错误信息。在Tomcat下,我们上面开发的Tag就可以出现异常,当在conf/catalina.policy中定义的安全属性后,获得一些属性就可恶会出错,我们可以捕捉这些错误,并重定向到其它的页。当然,我们还可以在日志中记录所有的错误,甚至发mail或打印更容易理解的信息,这些可以通过设置来完成。实现这些功能的代码如下:
<%@ page errorPage="error.jsp" %> at the top of each displayed page and writing an error.jsp page similar to this: <%@ page isErrorPage="true" %> <HTML> <HEAD><TITLE>Error Page </TITLE></HEAD> <BODY> <H3>Exception Information</H3> <%= exception %> <% Error handling code. %> </BODY> </HTML>

    如果我们认为这样做太麻烦。可以写一个用于错误处理的tag库,用于打印更容易理解的exception信息。这个tag的实现过程和上面的例子类似,这里不再详细描述。我们可以向如下代码一样使用这个tag。

<%@ page errorPage="error.jsp" %> <%@ taglib uri= "/WEB-INF/article.tld" prefix= "info" %> <info:ExpressError/>

    我们从上面两个例子可以看到,使用JSP的tag会比直接在JSP中使用java代码以及使用如struts一样的框架更容易,而且更容易学习,并且同样使程序具有弹性。
0
相关文章