第2部分 j2ee基础架构篇 -...

41
43 第2部分 J2EE基础架构篇 该部分将在第 1 部分搭建的 Eclipse 开发环境的基础上,开始开发基于 J2EE 的架构原型。主要包 括三个部分,各部分关系如图所示。 Eclipse 架构1demo(JSP).zip 架构2demo(JSP+JavaBean).zip 架构3:demo(JSP+JavaBean+Servlet).zip Servlet JSP JavaBean 开发 JSP 框架:讲解 JSP JDBC 技术,开发 JSP 负责显示页面和请求响应的架构原型系统 demo(JSP).zip 开发 JSP+JavaBean 框架:讲解 JavaBean 组件技术,在 demo(JSP).zip 基础上增加 JavaBean 功能, 形成 JSP+JavaBean 的架构原型系统 demo(JSP+JavaBean).zip 开发 JSP+JavaBean+Servlet 框架:讲解 Servlet 技术,在 demo(JSP+JavaBean).zip 基础上增加 Servlet 功能,形成 JSP+JavaBean+Servlet 的架构原型系统 demo(JSP+JavaBean+Servlet).zip

Upload: others

Post on 30-Sep-2020

15 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

43

第2部分

J2EE基础架构篇

该部分将在第 1 部分搭建的 Eclipse 开发环境的基础上,开始开发基于 J2EE 的架构原型。主要包

括三个部分,各部分关系如图所示。

Eclipse

架构1:demo(JSP).zip

架构2:demo(JSP+JavaBean).zip

架构3:demo(JSP+JavaBean+Servlet).zip

Servlet

JSP

JavaBean

� 开发 JSP 框架:讲解 JSP 和 JDBC 技术,开发 JSP 负责显示页面和请求响应的架构原型系统

demo(JSP).zip;

� 开发 JSP+JavaBean框架:讲解 JavaBean组件技术,在 demo(JSP).zip基础上增加 JavaBean功能,

形成 JSP+JavaBean的架构原型系统 demo(JSP+JavaBean).zip;

� 开发 JSP+JavaBean+Servlet框架:讲解 Servlet技术,在 demo(JSP+JavaBean).zip基础上增加 Servlet

功能,形成 JSP+JavaBean+Servlet的架构原型系统 demo(JSP+JavaBean+Servlet).zip。

Page 2: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

44

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

第 4 章 开发 JSP 框架

本章的目的是基于 JSP文件开发最简单的架构原型,即直接使用 JSP文件来开发系统的显示页面和

响应请求。在开始开发之前,将先讲解 JSP基本语法、JSP内置对象、JDBC技术。内容结构图如图 4-1

所示。

JSP内置对象

JSP基础语法 MySQL

架构1:demo(JSP).zip

JDBC

图 4-1 内容结构图

本章主要讲解的内容包括:

� JSP 基础语法包括:两种注释类型、三个脚本元素、三个指令元素、八个动作指令;

� JSP 内置对象:Request请求对象、Response响应对象、Session会话对象、Application应用程序对

象、Out输出对象、Cookie客户端对象、Config配置对象、Page页面对象、PageContext页面上下

文对象、Exception例外对象;

� JDBC 技术:详细讲解 Connection、DatabaseMetaData、Statement、ResultSet、PreparedStatement、

CallableStatement的使用;

� 开发 JSP架构原型:利用上面介绍的 JSP和 JDBC技术知识,测试连接MySQL数据库,开发基于

JSP显示页面和响应处理页面的架构原型,并最终形成 JSP的架构原型包 demo(JSP).zip。

4.1 JSP 基本语法

JSP代码中包含 JSP元素和 Template data两类。Template data指的是 JSP引擎不处理的部分,也就是

说除了 JSP语法外,JSP引擎将会把这部分信息直接传递出去而不进行任何处理,简而言之,就是指在标

记<%……%>以外的部分,例如代码中的 HTML 的内容等,这些数据会直接传送到客户端的浏览器;而

CHAPTER

4

Page 3: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

45

Tips

JSP元素则是指将由 JSP引擎直接处理的部分,这一部分必须符合 JSP语法,否则会导致编译错误。

JSP 标记是大小写敏感的,脚本语法和指令语法则使用了传统的语法。所有的 JSP 网页都对应着

XML文件的规格。

4.1.1 一个典型的 JSP 文件

在讲解 JSP语法之前,先来预览一下 JSP文件的构成。首先举一个典型的 JSP文件的例子:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%!int a = 1;%>

<%int b = 2;%>

<html>

<head>

<title>My JSP 'MyJsp.jsp' starting page</title>

</head>

<body><!--计算两个数字的和-->

The sum = <%=a+b%><br>

<jsp:forward page="welcome.jsp"/>

</body>

</html>

该页面用于计算两个数字的和并显示输出。

从上面的 JSP代码中可以看出,它包含了以下几种类型的元素:

� 注释:<!--计算两个数字的和-->;

� 脚本元素:<%!int a = 1;%>属于声明,<%int b = 2;%>属于脚本段,<%=a+b%>属于表达式;

� 指令元素:page用以设置页面的语言、编码,导入 Java类;

� 动作元素:<jsp:forward page="welcome.jsp"/>;

JSP基本语法包括:两种注释类型、三个脚本元素、三个指令元素、八个动作指令。接下来通过实

例进行讲解。

4.1.2 两种注释类型

1. HTML 注释

可以在 JSP 代码中添加一段 HTML 格式的注释,此注释发送到客户端,但并不显示。其语法格式

如下:

<!-- comment [ <%= expression %> ] --> 或

<!-- 注释 [<%= 表达式 %> ] -->

如果在注释标记中包含了表达式等需要 JSP引擎处理的部分,则返回的是处理后的内容。

例如:

<!-- This file displays <%=user%> login screen -->

如果用户名是 xiaozhang,则返回的注释是:

Page 4: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

46

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

Tips

<!-- This file displays xiaozhang login screen -->

2. JSP 注释

写在 JSP程序代码中,但不发送到客户端。其语法格式如下:

<%-- 这是一个 JSP 的单行注释--%>

<% /*这是一个 Scriptlet 中的多行注释*/ %>

<% /**这是一个 Scriptlet 中的多行注释,可以用 javadoc 从生成的 Java 文件中提取出来*/ %>

一般用来帮助进行代码阅读,意思是说这种注释是给编程人员看的,属于内部资料。

例如:

<%-- This comment will not be visible in the page source --%>

用注释标记的字符会在 JSP编译时被忽略掉。这种注释在希望隐藏或注释掉 JSP程序时是很有用的。

JSP编译器不是会对"<%--"和"--%>"之间的语句进行编译的,它不会显示在客户的浏览器中,也不会在

源代码中看到。在"<%-- --%>"之间,可以任意写注释语句,但是不能使用 "--%>",如果非要使用,

应该写为"--%\>"。

4.1.3 三个脚本元素

JSP脚本元素是最基本的语法格式,包含如下的三种语法形式。

1. 声明(Declaration)

用于在 JSP 程序中声明合法的变量和方法,其中变量类型包括 Java 基本类型以及类对象的声明。

其语法格式如下:

<%! declaration; [ declaration; ] ... %> 或

<%! 声明; [声明; ] ... %>

使用时注意不要忘记";"符号。

例如:

<%! int i = 0; %>

<%! int a, b, c; %>

<%! Date date; %>

声明了 int型的变量 i、a、b和 c,此外还有一个类型为 Date的对象型变量 date。至于如何使用变

量请参考后面的内容。

可以一次性声明多个变量和方法,但声明必须以";"结尾。可以直接使用在<% @ page %>中被包含

进来的已经声明的变量和方法,不需要对它们重新进行声明。一个声明仅在一个页面中有效。如果想每

个页面都用到一些声明,最好把它们写成一个单独的文件,然后用<%@ include %>或<jsp:include >元素

包含进来,请参考下文相关语法。

2. 表达式(Expression)

用来定义一个符合 JSP 语法的表达式,在运行后被自动转化为字符串,然后插入到这个表达式在

Page 5: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

47

Tips

JSP文件的位置显示。其语法格式如下:

<%= expression %> 或

<%= 表达式 %>

在 JSP代码中经常使用表达式来输出变量的值,可以用在任何地方。

例如:

<%! int a, b, c; %>

<% a=12;b=a; c=a+b;%>

<b>a=<%= a %></b><br>

<b>b=<%= b %></b><br>

<b>c=<%= c %></b><br>

a、b、c变量的值是由语句"<% a=12;b=a; c=a+b;%> "得到的。

不能用分号(";")来作为表达式的结束符,这和变量声明不同。但是同样的表达式用在 Scriptlet

中就需要以分号来结尾了!Scriptlet这个表达式元素能够包括任何在 Java Language Specification中有效

的表达式;有时候表达式也能做为其他 JSP元素的属性值;一个表达式的形式可能会很复杂,它可能由

一个或多个表达式组成,但它们的运算结果只能返回一个值。

3. 脚本段(Scriptlet)

脚本段(Scriptlet)用来包含一个有效的 Java程序段,所以把 Scriptlet称为程序段标记也许更合适

一些。一个 Scriptlet能够包含多个 JSP语句、方法、变量、表达式。

JSP语法格式如下:

<% code fragment %> 或

<% 代码 %>

例如:

<% condition=1;

switch(condition){

case 0:

out.println("You must select condition 0!"+"<br>");

break;

case 1:

out.println("You must select condition 1!"+"<br>");

break;

case 2:

out.println("You must select condition 2!"+"<br>");

break;

default:

out.println("Your select not in \"0,1,2\",select again!!"+"<br>");

}

%>

读者可通过更改语句"condition=1; "中变量 condition的不同数值来观察运行结果,会发现会有所不

同,在实际设计中也可以使用类似的方法,通过客户的不同选择给出不同的执行结果。

Page 6: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

48

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

4.1.4 三个指令元素

JSP通过指令来执行一些预定义的功能,是 JSP引擎为了方便 JSP开发而预定义的指令。主要包括

如下的三种指令:

1. page 指令

Page指令用于定义 JSP文件中的全局属性。其语法格式如下:

<%@ page

[ language="java" ]

[ extends="package.class" ]

[ import="{package.class | package.*},..." ]

[ session="true | false" ]

[ buffer="none | 8kb | sizekb" ]

[ autoFlush="true | false" ]

[ isThreadSafe="true | false" ]

[ info="text" ]

[ errorPage="relativeURL" ]

[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ]

[ isErrorPage="true | false" ]

%>

共包含 11个属性:

� language:声明脚本语言的种类,目前只能用"java";

� extends:标明 JSP编译时需要加入的 Java Class的全名,但是得慎重的使用,除非你对 Java非常

熟悉,因为它会限制 JSP的编译能力;

� import:需要导入的 Java包的列表,这些包作用于程序段,表达式,以及声明。下面的包在 JSP编

译时已经导入了,所以就不需要再指明了;

java.lang.*

javax.servlet.*

javax.servlet.jsp.*

javax.servlet.http.*

� session:设定客户是否需要 HTTP Session。(学过 ASP的人,应该对它不陌生)如果它为 true,那

么 Session 是有用的。如果它为 false,那么你就不能使用 session 对象,以及定义了 scope=session

的<jsp:useBean>元素。这样的使用会导致错误。默认值是 true;

� buffer:buffer的大小被 out对象用于处理执行后的 JSP对客户浏览器的输出。默认值是 8KB;

� autoFlush:设置如果 buffer溢出,是否需要强制输出,如果其值被定义为 true(默认值),输出正

常,如果它被设置为 false,如果这个 buffer溢出,就会导致一个意外错误的发生。如果你把 buffer

设置为 none,那么你就不能把 autoFlush设置为 false;

� isThreadSafe:设置 JSP文件是否能多线程使用。默认值是 true。也就是说,JSP能够同时处理多

个用户的请求,如果设置为 false,一个 JSP只能一次处理一个请求;

� info:一个文本在执行 JSP将会被逐字加入 JSP中,能够使用 Servlet.getServletInfo方法取回;

� errorPage:设置处理异常事件的 JSP文件;

� isErrorPage:设置此页是否为出错页,如果被设置为 true,默认你就能使用 exception对象;

Page 7: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

49

Tips

� contentType:charset=ISO-8859-1" 设置 MIME 类型。MIME 类型是: text/html,默认字符集为

ISO-8859-1。

<%@ page %>指令作用于整个 JSP页面,同样包括静态的包含文件。但是<%@ page %>指令不能

作用于动态的包含文件,比如<jsp:include>。

可以在一个页面中用上多个<%@ page %>指令,但是其中的属性只能用一次,不过也有例外,那

就是 import属性。因为 import属性和 Java中的 import语句类似(参照 Java Language,import语句引入

的是 Java语言中的类),所以此属性就能多用几次。

无论把<%@ page %>指令放在 JSP文件的哪个地方,它的作用范围都是整个 JSP页面。不过,为

了 JSP程序的可读性,以及好的编程习惯,最好还是把它放在 JSP文件的顶部。

例如:

<%@ page import="java.util.*, java.lang.*" %>

<%@ page buffer="24kb" autoFlush="false" %>

<%@ page errorPage="error.jsp" %>

2. include 指令

使用 include指令可以在 JSP中包含一个静态的文件,同时解析这个文件中的 JSP语句。其语法格

式如下:

<%@ include file="relativeURL" %> 或

<%@ include file="相对位置" %>

共包含 1个属性:

� file:这个包含文件的路径名一般来说是指相对路径,不需要什么端口、协议或域名,例如:"error.jsp",

"/templates/onlinestore.html","/beans/calendar.jsp"等。

例如:

<%@ include file=" test3.7.1.jsp " %>

如果这个路径以"/"开头,那么这个路径主要是参照 JSP 应用的上下文关系路径,如果路径是以文

件名或目录名开头,那么这个路径就是正在使用的 JSP文件的当前路径。

如果这个包含文件被改变,包含此文件的 JSP文件将被重新编译。“<%@include %>”指令会在 JSP

编译时插入一个包含文本或代码的文件,当使用“<%@include %>”指令时,这个包含的过程就是静态

的。静态的包含就是指这个被包含的文件将会被插入到 JSP文件中去,这个包含的文件可以是 JSP文件、

HTML文件、文本文件。如果包含的是 JSP文件,这个包含的 JSP的文件中代码将会被执行。

如果你仅仅只是用 include 来包含一个静态文件。那么这个包含的文件所执行的结果将会插入到

JSP文件中"<%@include %>"所处的位置。一旦包含文件被执行,那么主 JSP文件的过程将会被恢复,

继续执行下一行.。

这个被包含文件可以是 html文件、jsp文件、文本文件,或者只是一段 Java代码,但是要注意在这

个包含文件中不能使用<html>、</html>、<body>、</body>标记,因为这将会影响在原 JSP文件中同样

的标记,有时会导致错误。

Page 8: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

50

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

3. taglib 指令

定义一个标签库以及其自定义标签的前缀。其语法格式如下:

<%@ taglib uri="URIToTagLibrary" prefix="tagPrefix" %>

共包含 2个属性:

� uri:Uniform Resource Identifier (URI)根据标签的前缀对自定义的标签进行唯一的命名,URI可以是

一个相对或绝对的路径;

� prefix:在自定义标签之前的前缀,比如,在<public:loop>中的 public,如果这里不写 public,那么

这就是不合法的。请不要用 jsp, jspx, java, javax, servlet, sun, 和 sunw作为你的前缀,这些已被 Sun

公司声明保留。

<% @ taglib %>指令声明此 JSP文件使用了自定义的标签,同时引用标签库,也指定了它们的标签

的前缀。

例如:

<%@ taglib uri="http://www.jspcentral.com/tags" prefix="public" %>

<public:loop>

<%-- 执行代码 --%>

</public:loop>

4.1.5 八个动作指令

JSP动作指令是预定义的 JSP标签,实现了最常用的基本功能。共有如下的八种动作指令:

1. 页面跳转:<jsp:forward>

<jsp:forward>标签从一个 JSP 文件向另一个文件传递一个包含用户请求的 request 对象。其语法格

式如下:

<jsp:forward page={"relativeURL" | "<%= expression %>"} />

或<jsp:forward page={"relativeURL" | "<%= expression %>"} >

<jsp:param name="parameterName" value="{parameterValue | <%= expression %>}" />

[<jsp:param … />]

</jsp:forward>

("[<jsp:param … />]"指可以有多个"<jsp:param/>"标记。)

共包含 2个属性:

� page属性是一个表达式或是一个字符串用于说明你将要定向的文件或 URL。这个文件可以是 JSP、

程序段,或者其他能够处理 request对象的文件(如 asp,cgi,php);

� <jsp:param/>向一个动态文件发送一个或多个参数,这个文件必须是动态文件。如果想传递多个参

数,可以在一个 JSP文件中使用多个"<jsp:param>";"name"指定参数名,"value"指定参数值。

例如:

<jsp:forward page="test3.10.1.jsp">

<jsp:param name="username" value="<%=user%>"/>

<jsp:param name="password" value="<%=pwd%>"/>

</jsp:forward>

Page 9: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

51

<jsp:forward>能够向目标文件传送参数和值,如果使用了<jsp:param>标签的话,目标文件必须是一

个动态的文件,能够处理参数。如果使用了非缓冲输出,那么使用<jsp:forward>时就要小心。如果在使

用<jsp:forward>之前,JSP文件已经有了数据,那么文件执行将会出错。

2. 包含页面:<jsp:include>

包含一个静态或动态文件。其语法格式如下:

<jsp:include page="{relativeURL | <%= expression%>}" flush="true" />

或<jsp:include page="{relativeURL | <%= expression %>}" flush="true" >

<jsp:param name="parameterName" value="{parameterValue | <%= expression %>}" />

[<jsp:param …/>]

</jsp:include>

("[<jsp:param … />]"指可以有多个"<jsp:param/>"标记。)

共包含 3个属性:

� page:属性为一相对路径,或者是代表相对路径的表达式;

� flush:这里必须使用 flush="true",不能使用 false值。而默认值为 false;

� <jsp:param>用来传递一个或多个参数到指定的动态文件,能在一个页面中使用多个<jsp:param>来传

递多个参数;

例如:

<jsp:include page="scripts/login.jsp" flush="true" />

<jsp:include page="copyright.html" flush="true" />

<jsp:include page="/index.html" flush="true" />

<jsp:include page="scripts/login.jsp" flush="true" >

<jsp:param name="username" value="jsmith" />

</jsp:include>

<jsp:include>元素允许包含动态和静态文件,这两种包含文件的结果是不同的。如果文件仅是静态

文件,那么这种包含仅仅是把包含文件的内容加到 JSP文件中去,则类似于<%@include %>;而如果这

个文件是动态的,那么这个被包含文件也会被 JSP编译器执行(与 ASP相似) 。

如果这个包含文件是动态的,那么还可以用<jsp:param>传递参数名和参数值。与使用<%@include

%>的注意事项相同,被包含的文件中注意不要重复出现某些 HTML标记,以免出错。

3. 创建 Bean:<jsp:useBean>

创建一个 Bean实例并指定它的名字和作用范围。其语法格式如下:

<jsp:useBean

id="beanInstanceName"

scope="page | request | session | application"

{

class="package.class" |

type="package.class" |

class="package.class" type="package.class" |

beanName="{package.class | <%= expression %>}"

type="package.class"

}

{

/> |

Page 10: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

52

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

> other elements </jsp:useBean>

}

共包含 5个属性:

� id:在所定义的范围中确认 Bean的变量,使之能在后面的程序中使用此变量名来分辨不同的 Bean,

这个变量名对大小写敏感,必须符合所使用的脚本语言的规定,这个规定在 Java Language 规范已

经写明。如果 Bean已经在别的"<jsp:useBean>"标记中创建,则当使用这个已经创建过 Bean时,id

的值必须与原来的那个 id值一致;否则则意味着创建了同一个类的两个不同的对象;

� scope:Bean 存在的范围以及 id变量名的有效范围。默认值是 page,以下是详细说明。

� page - 能在包含"<jsp:useBean>"元素的 JSP文件以及此文件中的所有静态包含文件中使用这个

Bean,直到页面执行完毕向客户端发回响应或转到另一个文件为止。

� request - 在任何执行相同请求的 JSP文件中使用这个 Bean,直到页面执行完毕向客户端发回

响应或转到另一个文件为止。能够使用 Request 对象访 问这个 Bean,比如

request.getAttribute(beanInstanceName)。

� session - 从创建 Bean开始,就能在任何使用相同 session的 JSP文件中使用这个 Bean。这个 Bean

存在于整个 Session生存周期内,任何在分享此 Session的 JSP文件都能使用同一 Bean。注意在

创建这个 Bean的 JSP文件中"<% @ page %>"指令中必须指定"session="true""。

� application - 从创建 Bean开始,就能在任何使用相同 application的 JSP文件中使用 Bean。这个

Bean 存在于整个 application 生存周期内,任何在分享此 application 的 JSP 文件都能使用同一

Bean;

� class:使用 new关键字以及 class 构造器从一个 class中示例一个 Bean。这个 class不能是抽象的,

必须有一个公用的,没有参数的构造器。这个 package的名字区别大小写;

� type:如果这个 Bean已经在指定的范围中存在,那么赋予这个 Bean一个数据类型 。如果使用 type

属性的同时没有使用 class或 beanName,Bean将不会被实例化。注意 package和 class的名称区分

大小写;

� beanName:beanName 可以是 package 和 class,也可以是表达式,它的值会传给 Beans.instantiate

方法。type的值可以和 Bean相同,也可以是它的基类,或者是它所实现的接口。package和 class 名

字区分大小写。

例如:

<jsp:useBean id="cart" scope="session" class="session.Carts" />

<jsp:setProperty name="cart" property="*" />

<jsp:useBean id="checking" scope="session" class="bank.Checking" >

<jsp:setProperty name="checking" property="balance" value="0.0" />

</jsp:useBean>

<jsp:useBean>用于定位或示例一个 JavaBeans组件。<jsp:useBean>首先会试图定位一个 Bean实例,

如果这个 Bean不存在,那么<jsp:useBean>就会从一个 class或模版中进行实例化。

4. 设置 Bean 属性:<jsp:setProperty>

设置 Bean的属性值。其语法格式如下:

Page 11: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

53

Tips

<jsp:setProperty

name="beanInstanceName"

{

property= "*" |

property="propertyName" [ param="parameterName" ] |

property="propertyName" value="{string | <%= expression %>}"

}

/>

共包含 4个属性:

� name:表示已经在"<jsp:useBean>"中创建的 Bean 实例的名字;

� property:储存用户在 Jsp输入的所有值,用于匹配 Bean中的属性;

� property="propertyName" [ param="parameterName" ]:用一个参数值来指定 Bean中的一个属性

值,一般情况下是从 request对象中获得的。其中 property指定 Bean的属性名,param指定 request

中的参数名;

� property="propertyName" value="{string | <%= expression %>}":使用指定的值来设定 Bean属性。

这个值可以是字符串,也可以是表达式。如果这个字符串,那么它就会被转换成 Bean 属性的类型

(转换方法见表 4.1)。如果是一个表达式,那么它的类型就必须和将要设定的属性值的类型一致。

如果参数值为空值,那么对应的属性值也不会被设定。此外,不能在同一个<jsp:setProperty>中同

时使用 param和 value参数 。

例如:

1.<jsp:setProperty name="mybean" property="*" />

2.<jsp:setProperty name="mybean" property="username" />

3.<jsp:setProperty name="mybean" property="username" value="Steve" />

5. 取得 Bean 属性:<jsp:getProperty>

使用<jsp:getProperty>可获取 Bean的属性值,用于在页面中显示。其语法格式如下:

<jsp:getProperty name="beanInstanceName" property="propertyName" />

共包含 2个属性:

� name:Bean的名字,由<jsp:useBean>指定;

� property:所指定的 Bean的属性名。

例如:

<jsp:useBean id="calendar" scope="page" class="employee.Calendar" />

<jsp:getProperty name="calendar" property="username" />

在使用<jsp:getProperty>之前,必须有由<jsp:useBean>所创建的 Bean对象。

6. 使用 Applet 插件:<jsp:plugin>

使用<jsp:plugin>插入一个 applet或 Bean,必要的话还要下载一个 Java插件用于执行它。其语法格

式如下:

<jsp:plugin

Page 12: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

54

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

type="bean | applet"

code="classFileName"

codebase="classFileDirectoryName"

[ name="instanceName" ]

[ archive="URIToArchive, ..." ]

[ align="bottom | top | middle | left | right" ]

[ height="displayPixels" ]

[ width="displayPixels" ]

[ hspace="leftRightPixels" ]

[ vspace="topBottomPixels" ]

[ jreversion="JREVersionNumber | 1.1" ]

[ nspluginurl="URLToPlugin" ]

[ iepluginurl="URLToPlugin" ] >

[ <jsp:params>

[ <jsp:param name="parameterName"

value="{parameterValue | <%= expression %>}" /> ]+

</jsp:params> ]

[ <jsp:fallback> text message for user </jsp:fallback> ]

</jsp:plugin>

共包含 13个属性:

� type:将被执行的插件对象的类型,你必须得指定这个是 Bean 还是 applet,因为这个属性没有默认

值;

� code:将会被 Java 插件执行的 Java Class的名字,必须以.class结尾。这个文件必须存在于 codebase

属性指定的目录中;

� codebase:将会被执行的 Java Class文件的目录(或者是路径),如果你没有提供此属性,那么使

用<jsp:plugin>的 jsp文件的目录将会被使用;

� name:这个 Bean或 applet 实例的名字,它将会在 Jsp其他的地方调用;

� archive:一些由逗号分开的路径名,这些路径名用于预装一些将要使用的 class,这会提高 applet的

性能;

� align:图形对象、Applet的位置,有以下值。

� ottom:位于底部

� top:位于顶部

� middle:在中间

� left:在左边

� right:在右边

� height、width:Applet或 Bean将要显示的长宽的值,此值为数字,单位为像素;

� hspace、vspace:Applet或 Bean 显示时在屏幕左右,上下所需留下的空间,单位为像素;

� jreversion:Applet或 Bean运行所需的 Java Runtime Environment (JRE) 的版本。默认值是 1.1;

� nspluginurl:Netscape Navigator 用户能够使用的 JRE 的下载地址,此值为一个标准的 URL,如

http://www.aspcn.com/jsp;

� iepluginurl : IE 用户能够使用的 JRE 的下载 地 址,此值为一个标准的 URL,如

http://www.aspcn.com/jsp;

� <jsp:params>:该标志符需要向 applet或 Bean 传送的参数 name或参数值 value;

Page 13: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

55

� <jsp:fallback>:一段文字,用于 Java 插件不能启动时显示给用户的,如果插件能够启动而 applet

或 Bean不能,那么浏览器会有一个出错信息弹出。

例如:

<jsp:plugin type=applet code="MediaPlay.class" codebase="../classes">

<jsp:params>

<jsp:param name="way" value="Hall" />

</jsp:params>

<jsp:fallback>

<p>Unable to load applet</p>

</jsp:fallback>

</jsp:plugin>

<jsp:plugin>元素用于在浏览器中播放或显示一个对象(典型的就是 applet和 Bean),而这种显示需

要浏览器中的 Java插件。

当 JSP文件被编译之后送往浏览器时,<jsp:plugin>元素将会根据浏览器的版本替换成<object>或者

<embed>元素。注意:<object>用于 HTML 4.0 ,<embed>用于 HTML 3.2。

一般来说,<jsp:plugin>元素会指定对象是 Applet还是 Bean,同样也会指定 class的名称还有位置,

另外还会指定将从哪里下载这个 Java插件。

7. 插件定义参数:<jsp:param>

用以定义<jsp:plugin>插件的输入参数,实际上提供了名称与值的一种一一对应关系,语法为:

<jsp:param name=" name" value=" value" />

8. 插件错误提示:<jsp:fallback>

当<jsp:plugin>插件不能够正常显示时显示提示信息。

4.2 JSP 内置对象

本节主要介绍 JSP 的 9种内置对象和 Cookie对象,9种内置对象包括:

� Request:请求对象;

� Response:响应对象;

� Session:会话对象;

� Application:应用程序对象;

� Out:输出对象;

� Config:配置对象;

� Page:页面对象;

� PageContext:页面上下文对象;

� Exception:例外对象。

有几种对象看起来和 ASP 的内置对象差不多,功能也类似,这是因为这些内置对象的构建基础是

标准化的 HTTP协议。如果使用过 ASP,又对 Java有一定的了解的话,那么对这几种 JSP内置对象的

使用应该能迅速掌握。需要注意的问题是对象名的写法,包括这些对象方法的调用时也要书写正确,因

Page 14: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

56

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

为 Java语言本身是大小写敏感的。

4.2.1 Request:请求对象

该对象封装了用户提交的信息,通过调用该对象相应的方法可以获取封装的信息,即使用该对象可

以获取用户提交的信息。

当 Request对象获取客户提交的汉字字符时,会出现乱码问题,必须进行特殊处理。首先,将获取

的字符串用 ISO-8859-1进行编码,并将编码存发到一个字节数组中,然后再将这个数组转化为字符串

对象即可。

例如: String textContent=request.getParameter("boy"); byte b[]=textContent.getBytes("ISO-8859-1"); textContent=new String(b);

Request常用的方法如下。

� getParameter(String strTextName):获取表单提交的信息。

例如:String strName=request.getParameter("name");

� getProtocol():获取客户使用的协议。

例如:String strProtocol=request.getProtocol();

� getServletPath():获取客户提交信息的页面。

例如:String strServlet=request.getServletPath();

� getMethod():获取客户提交信息的方式。

� getHeader():获取 HTTP头文件中的 accept、accept-encoding和 Host的值。

例如:String strHeade=request.getHeader("accept");

� getRermoteAddr():获取客户的 IP 地址。

� getRemoteHost():获取客户机的名称。

� getServerName():获取服务器名称。

� getServerPort():获取服务器的端口号。

� getParameterNames():获取客户端提交的所有参数的名字。

例如: Enumeration enum = request.getParameterNames(); while(enum.hasMoreElements()){ String s=(String)enum.nextElement(); out.println(s); }

4.2.2 Response:响应对象

对客户的请求做出动态的响应,向客户端发送数据。

� 动态响应 contentType属性

当一个用户访问一个 JSP页面时,如果该页面用 page指令设置页面的 contentType属性时 text/html,

那么 JSP引擎将按照这个属性值做出反应。如果要动态改变这换个属性值来响应客户,就需要使用

Page 15: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

57

Response对象的 setContentType(String s)方法来改变 contentType的属性值。

格式:response.setContentType(String s);

参数 s可取 text/html,application/x-msexcel,application/msword等。

� Response重定向

在某些情况下,当响应客户时,需要将客户重新引导至另一个页面,可以使用 Response 的

sendRedirect(URL)方法实现客户的重定向。例如:

response.sendRedirect("index.jsp");

4.2.3 Session:会话对象

(1)什么是 Session 对象

Session对象是一个 JSP内置对象,它在第一个 JSP 页面被装载时自动创建,完成会话期管理。从

一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。

当一个客户访问一个服务器时,可能会在这个服务器的几个页面之间切换,服务器应当通过某种办法知

道这是一个客户,就需要 Session对象。

(2)Session 对象的 ID

当一个客户首次访问服务器上的一个 JSP 页面时,JSP引擎产生一个 Session 对象,同时分配一个

String类型的 ID号,JSP引擎同时将这换个 ID号发送到客户端,存放在 Cookie中,这样 Session对象,

直到客户关闭浏览器后,服务器端该客户的 Session对象才取消,并且和客户的会话对应关系消失。当

客户重新打开浏览器再连接到该服务器时,服务器为该客户再创建一个新的 Session对象。

(3)Session 对象的常用方法

� public String getId():获取 Session对象编号。

� public void setAttribute(String key,Object obj):将参数 Object指定的对象 obj 添加到 Session对象

中,并为添加的对象指定一个索引关键字。

� public Object getAttribute(String key):获取 Session对象中含有关键字的对象。

� public Boolean isNew():判断是否是一个新的客户。

4.2.4 Application:应用程序对象

(1)什么是 Application 对象

服务器启动后就产生了这个 Application 对象,当客户在所访问的网站的各个页面之间浏览时,这

个 Application对象都是同一个,直到服务器关闭。但是与 Session对象不同的是,所有客户的 Application

对象都是同一个,即所有客户共享这个内置的 Application对象。

(2)Application 对象的常用方法

� setAttribute(String key,Object obj):将参数 Object指定的对象 obj 添加到 Application对象中,并为

添加的对象指定一个索引关键字。

Page 16: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

58

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

� getAttribute(String key):获取 Application对象中含有关键字的对象。

4.2.5 Out:输出对象

Out对象是一个输出流,用来向客户端输出数据。Out对象用于各种数据的输出。其常用方法如下:

� out.print():输出各种类型数据;

� out.newLine():输出一个换行符;

� out.close():关闭流。

4.2.6 Cookie:客户端对象

(1)什么是 Cookie

Cookie是Web服务器保存在用户硬盘上的一段文本。Cookie允许一个Web站点在用户电脑上保存

信息并且随后再取回它。

举例来说,一个Web站点可能会为每一个访问者产生一个唯一的 ID,然后以 Cookie文件的形式保

存在每个用户的机器上。

如果用户使用 IE浏览器访问Web,用户就会看到所有保存在自己硬盘上的 Cookie。它们最常存放

的地方是:C:\Windows\Cookies。Cookie是以“关键字 key=值 value”的格式来保存记录的。

(2)创建一个 Cookie 对象

调用 Cookie对象的构造函数就可以创建 Cookie对象。Cookie对象的构造函数有两个字符串参数:

Cookie名字和 Cookie值。

例如:Cookie c = new Cookie("username","john");

(3)将 Cookie 对象传送到客户端

在 JSP中,如果要将封装好的 Cookie对象传送到客户端,可使用 Response对象的 addCookie()方法。

例如:response.addCookie(c)。

(4)读取保存到客户端的 Cookie

使用 Request对象的 getCookie()方法,执行时将所有客户端传来的 Cookie对象以数组的形式排列,

如果要取出符合需要的 Cookie对象,就需要循环比较数组内每个对象的关键字。

例如:

Cookie[] c = request.getCookies();

if(c != null)

for(int i = 0;i < c.length;i++){

if("username".equals(c.getName()))

out.println(c.getValue());

}

(5)设置 Cookie 对象的有效时间

调用 Cookie对象的 setMaxAge()方法便可以设置 Cookie对象的有效时间。

Page 17: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

59

例如:

Cookie c = new Cookie("username","john");

c.setMaxAge(3600);

(6)Cookie 应用

Cookie 对象的典型应用是用来统计网站的访问人数。由于代理服务器、缓存等的使用,唯一能帮

助网站精确统计来访人数的方法就是为每个访问者建立一个唯一的 ID。使用 Cookie,网站可以完成以

下工作:

� 测定多少人访问过;

� 测定访问者有多少是新用户(即第一次来访),多少是老用户;

� 测定一个用户多久访问一次网站。

当一个用户第一次访问时,网站在数据库中建立一个新的 ID,并把 ID 通过 Cookie 传送给用户。

用户再次来访时,网站把该用户 ID对应的计数器加 1,得到用户的来访次数。

4.2.7 Config:配置对象

一般我们使用 Config 对象来获取一些初始化配置信息,常用的方法有 getInitParameter 和

getInitParameterNames,以获得 Servlet初始化时的参数。

此外,还可以通过 getServletContext()方法取得 ServletContext。一个 ServletContext对象,它能给出

Servlet如何与服务器交互的信息。ServletContext对象是服务器传给这个 Servlet的。在 ServletConfig接

口定义中 ServletContext对象是其中的一部分。

4.2.8 Page:页面对象

Page对象代表了正在运行的由 JSP文件产生的类对象,不建议一般读者使用。

4.2.9 PageContext:页面上下文对象

JSP引入了一个名为 PageContext的类,通过它可以访问页面的许多属性。pageContext变量存储与

当前页面相关联的 PageContext对象的值。

PageContext 类拥有 getRequest,getResponse,getOut,getSession 等方法。如果需要访问多个与页

面相关的对象,传递 pageContext要比传递 request,response,out等的独立引用更容易。

4.2.10 Exception:例外对象

Exception对象代表了 JSP文件运行时所产生的例外对象,此对象不能在一般 JSP文件中直接使用,

而只能在使用了"<%@ page isErrorPage="true "%>"的 JSP文件中使用,这是因为 JSP文件运行时产生的

错误对象被向外抛出,只能被使用了"<%@ page isErrorPage="true "%>"标记从而具有拦截错误对象功能

的 JSP所拦截。最常用的方法就是 getMessage,用以获得错误信息,此外还会用到 getLocalizedMessage

和 printStackTrace。

Page 18: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

60

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

4.3 JDBC 核心技术

JDBC是一种用于执行 SQL语句的 Java API,它由一组用 Java编程语言编写的类和接口组成。JDBC

为工具/数据库开发人员提供了一个标准的 API,使他们能够用纯 Java API 来编写数据库应用程序。

有了 JDBC,向各种关系数据库发送 SQL语句就是一件很容易的事。换言之,有了 JDBC API,就

不必为访问MySQL数据库专门写一个程序,为访问Oracle数据库又专门写一个程序,为访问 SQL Server

数据库又写另一个程序,等等。您只需用 JDBC API 写一个程序就够了,它可向相应数据库发送 SQL

语句。而且,使用 Java编程语言编写的应用程序,就无须去考虑要为不同的平台编写不同的应用程序。

将 Java和 JDBC结合起来将使程序员只需写一遍程序就可让它在任何平台上运行。

简单地说,JDBC可做三件事:

� 与数据库建立连接;

� 发送 SQL语句;

� 处理结果。

下列的代码段给出了以上三步的基本示例:

Connection conn = DriverManager.getConnection ("jdbc:odbc:datasource", "username", "password");

Statement stmt = conn.createStatement();

ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");

while (rs.next())

System.out.println(rs.getString("a") + " " + rs.getString("b") + " " + rs.getString("c"));

该示例使用了 JDBC提供的几个类对象,我们正是通过使用 JDBC提供的类对象来完成与数据库的

交互的。JDBC的这些类中最重要的有:

� java.sql.DriverManager:用来加载不同的 JDBC 驱动程序并且为创建的新的数据库连接提供支持;

� java.sql.Connection:完成对某一指定数据库的连接功能;

� java.sql.Statement:在一个已经创建的连接(java.sql.Connection)中作为执行 SQL 语句的容器;

它包含了两个重要的子类:

� java.sql.PreparedStatement:用于执行预编译的 SQL语句;

� java.sql.CallableStatement:用于执行数据库中已经创建好的存储过程(Stored Procedure)。

� java.sql.ResultSet:代表特定 SQL语句执行后的数据库结果集。

以上这些类是编写 JSP程序经常要调用的,类之间的关系如图 4-2所示。

下面将对这些类的使用做详尽的阐述。

4.3.1 通过 Connection 对象建立数据库连接

Connection 对象代表与数据库的连接。连接过程包括所执行的 SQL 语句和在该连接上所返回的结

果。一个应用程序可与单个数据库有一个或多个连接,或者可与许多数据库有连接。

Page 19: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

61

DriverManager

Connection Connection Connection

PreparedStatementStatement Statement

ResultSet ResultSet

CallableStatement

图 4-2 JDBC API 结构关系图

1. JDBC 连接 URL

JDBC URL 提供了一种标识数据库的方法,可以使相应的驱动程序能识别该数据库并与之建立连

接。JDBC URL的标准语法如下所示。它由三部分组成,各部分间用冒号分隔:

<协议 jdbc>:<子协议>:<子名称>

� <协议>:JDBC URL中的协议总是 jdbc。

� <子协议>:驱动程序名或数据库连接机制(这种机制可由一个或多个驱动程序支持)的名称。子协

议名的典型示例是“odbc“,该名称是为用于指定 ODBC 风格的数据资源名称的 URL 专门保留的。

� <子名称>:包含要连接数据库的名称、用户名、密码等信息。

例如:为了通过 JDBC-ODBC 桥来访问某个数据库,可以用如下所示的 URL:

jdbc:odbc:TEST

其中,子协议为“odbc”,子名称“TEST”是本地 ODBC 数据资源。

下例是MySQL的连接 URL:

jdbc:mysql://localhost/db?user=root&password=123&useUnicode=true&characterEncoding=utf-8

其中的子协议为“mysql”,后面的字符串表示连接MySQL的相关信息。其中“localhost”表示MySQL

的主机地址,“db”表示数据库名,user参数表示用户名,password表示密码,useUnicode表示连接的

编码方式。

下例是 Oracle的连接 URL:

jdbc:oracle:thin:@localhost:1521:orcl

其中,“oracle:thin”表示连接子协议,“localhost”表示 Oracle的主机地址,“1521”表示连接端口,

“orcl”表示连接的 Oracle服务名。

下例是 SQLServer的连接 URL:

jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs

其中,“micorsoft:sqlserver”表示连接子协议,“localhost”表示 SQLServer的主机地址,“1433”表

示连接端口,“pubs”表示连接的数据库名。

Page 20: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

62

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

2. 使用 DriverManager 管理驱动类

DriverManager 类是 JDBC 的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在

数据库和相应驱动程序之间建立连接。一般需要直接使用的唯一方法是 DriverManager.getConnection。

正如名称所示,该方法将建立与数据库的连接。

在取得连接之前,需要注册驱动程序。通过调用方法 Class.forName,这将显式地加载驱动程序类。

以下代码分别加载连接 ODBC、MySQL、Oracle、SQLServer的驱动类:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

Class.forName("com.mysql.jdbc.Driver");

Class.forName("oracle.jdbc.driver.OracleDriver");

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

3. 取得 Connection 连接

我们可以通过驱动管理类 DriverManager的下面的方法取得数据库连接对象:

DriverManager.getConnection(url,username,password);

它包含三个参数,分别为连接的 URL、数据库用户名和密码。如果不需要用户名和密码,可以忽

略后两个参数。

当调用 DriverManager.getConnection 方法发出连接请求时,DriverManager 将检查每个驱动程序,

查看它是否可以建立连接。

有时可能有多个 JDBC驱动程序可以与给定的 URL连接。例如,与给定远程数据库连接时,可以

使用 JDBC-ODBC桥驱动程序、JDBC到通用网络协议驱动程序或数据库厂商提供的驱动程序。在这种

情况下,测试驱动程序的顺序至关重要,因为 DriverManager将使用它所找到的第一个可以成功连接到

给定 URL的驱动程序。

它通过轮流在每个驱动程序上调用方法 Driver.connect,并向它们传递用户开始传递给方法

DriverManager.getConnection的 URL来对驱动程序进行测试,然后连接第一个认出该 URL的驱动程序。

以下的代码是通常情况下用驱动程序(例如 JDBC-ODBC 桥驱动程序)建立连接所需的所有步骤

的示例:

String url = "jdbc:odbc:TEST"; //JDBC URL

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加载驱动程序

Connection conn = DriverManager.getConnection(url, "userID", "passwd"); //取得连接

4. 连接管理

一旦取得一个数据库连接,就在物理上与数据库建立了一个通路,此时可以通过该连接对象来查看

数据库信息、查询数据库数据、修改数据等。并在完成一些列操作后使用下面的函数关闭数据库连接: conn.close();

该对象还可以通过以下的方法进行事务管理:

� 设置不自动提交:conn.setAutoCommit(false);

� 提交数据:conn.commit();

� 回滚数据:conn.rollback();

� 设置自动提交:conn.setAutoCommit(true)。

并可以利用 Connection对象的其他方法来取得各种其他的对象,请看下文。

Page 21: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

63

4.3.2 通过 DatabaseMetaData 对象了解数据库的信息

JSP通过 JDBC对数据库管理系统进行连接以后,得到一个 Connection对象,可以从这个对象获得

有关数据库管理系统的各种信息,包括数据库中的各个表,表中的各个列,数据类型,触发器,存储过

程等各方面的信息。根据这些信息,JDBC可以访问一个事先并不了解的数据库。获取这些信息的方法

都是在 DatabaseMetaData类的对象上实现的,而 DataBaseMetaData对象是在 Connection对象上获得的。

下面的语句可以在一个已经初始化的 Connection对象的基础上创建一个 DatabaseMetaData对象:

DatabaseMetaData datameta=conn.getMetaData();

DatabaseMetaData类中提供了许多方法用于获得数据源的各种信息,通过这些方法可以非常详细地了

解数据库的信息。下面给出一些常用的方法,其他的方法请读者参考 JDK API中的 DatabaseMetaData类。

这些方法中,有一些要用字符串搜索匹配模式作为参数,这些匹配模式与 ODBC中的一样。字符'_'

匹配任何单个字符,'%'匹配零个或者多个字符。一个值为 null的 Java String 可以与任何字符串相匹配。

这些方法中,有些驱动程序可能并不支持,这时会产生一个 SQLException 例外。例外中会给出信

息表明驱动程序不支持该方法。

1. 数据库的基本信息

getURL():返回一个 String 类对象,代表数据库的 URL

getUserName():返回连接当前数据库管理系统的用户名

isReadOnly():返回一个 boolean 值,指示数据库是否只允许读操作

getDatabaseProductName():返回数据库的产品名称

getDatabaseProductVersion():返回数据库的版本号

getDriverName():返回驱动程序的名称

getDriverVersion():返回驱动程序的版本号

2. 获取数据库中各个表的情况

ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]);

getTables方法返回一个 ResultSet 对象,每一条记录是对一个表的描述。只有那些符合参数要求的

表才被返回。

3. 获取表中各列的信息

ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String types[]);

getColumns返回一个 ResultSet类的对象,其中每一行是对一列的描述,只有符合参数要求的列才

被返回。

4. 获取关于索引的信息

ResultSet getIndexInfo(String catalog, String schema, Boolean unique, boolean approximate);

getIndexInfo方法返回一个 ResultSet类的对象,其中每一行是对一个索引的描述,只有符合参数要

求的索引才被返回。

Page 22: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

64

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

4.3.3 使用 Statement 对象

Statement 对象用于将 SQL 语句发送到数据库中。实际上有三种 Statement 对象,它们都作为在给

定连接上执行 SQL 语句的包容器:Statement、PreparedStatement(它从 Statement 继承而来)和

CallableStatement(它从 PreparedStatement继承而来)。它们都专用于发送特定类型的 SQL语句:Statement

对象用于执行不带参数的简单 SQL语句;reparedStatement对象用于执行带或不带 IN参数的预编译 SQL

语句;CallableStatement对象用于执行对数据库已存储过程的调用。

Statement接口提供了执行语句和获取结果的基本方法。PreparedStatement接口添加了处理 IN参数

的方法;而 CallableStatement添加了处理 OUT参数的方法。

1. 创建 Statement 对象

建立了到特定数据库的连接之后,就可用该连接发送 SQL语句。Statement对象用 Connection的方

法 createStatement创建,如下列代码段中所示:

Statement stmt = conn.createStatement();

为了执行 Statement对象,被发送到数据库的 SQL语句将被作为参数提供给 Statement的方法:

ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2");

2. 使用 Statement 对象执行语句

Statement接口提供了三种执行 SQL语句的方法:executeQuery、executeUpdate和 execute。使用哪

一个方法由 SQL语句所产生的内容决定。

� 方法 executeQuery:用于产生单个结果集的语句,例如 SELECT 语句。

� 方法 executeUpdate:用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DL(数据定义语言)

语句,例如 CREATE TABLE和 DROP TABLE。INSERT、UPDATE或 DELETE语句的效果是修改

表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数,指示受影响的行数(即更

新计数)。对于 CREATE TABLE或 DROP TABLE等不操作行的语句,executeUpdate的返回值总为

零。

� 方法 execute:用于执行返回多个结果集、多个更新计数或两者组合的语句。

执行语句的所有方法都将关闭所调用的 Statement对象的当前打开结果集(如果存在)。这意味着在

重新执行 Statement对象之前,需要完成对当前 ResultSet对象的处理。

应注意,继承了 Statement 接口中所有方法的 PreparedStatement 接口都有自己的 executeQuery、

executeUpdate和 execute 方法。Statement 对象本身不包含 SQL语句,因而必须给 Statement.execute 方

法提供 SQL语句作为参数。PreparedStatement对象并不将 SQL语句作为参数提供给这些方法,因为它

们已经包含预编译 SQL语句。CallableStatement对象继承这些方法的 PreparedStatement形式。对于这些

方法的 PreparedStatement或 CallableStatement版本,使用查询参数将抛出 SQLException。

3. 语句完成

当连接处于自动提交模式时,其中所执行的语句在完成时将自动提交或还原。语句在已执行且所有

结果返回时,即认为已完成。对于返回一个结果集的 executeQuery方法,在检索完 ResultSet对象的所

有行时该语句完成。对于方法 executeUpdate,当它执行时语句即完成。但在少数调用方法 execute的情

Page 23: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

65

况中,在检索所有结果集或它生成的更新计数之后语句才完成。

有些 DBMS 将已存储过程中的每条语句视为独立的语句;而另外一些则将整个过程视为一个复合

语句。在启用自动提交时,这种差别就变得非常重要,因为它影响什么时候调用 commit方法。在前一

种情况中,每条语句单独提交;在后一种情况中,所有语句同时提交。

4. 关闭 Statement 对象

Statement对象将由 Java 垃圾收集程序自动关闭。而作为一种好的编程风格,应在不需要 Statement

对象时显式地关闭它们。如下所示:

stmt.close();

这将立即释放 DBMS资源,有助于避免潜在的内存问题。

4.3.4 结果集 ResultSet 对象

在 4.3.3节中,我们介绍了用 Statement类及其子类传递 SQL语句,对数据库管理系统进行访问。

一般来说,对数据库的操作 80%以上都是执行查询语句。这种语句执行的结果是返回一个 ResultSet类

的对象。要想把查询结果最后显示给用户,必须对 ResultSet 对象进行处理,本节将介绍对结果集的处

理方法。

1. ResultSet 类的基本处理方法

一个 ResultSet对象对应着一个由查询语句返回的一个表,这个表中包含所有的查询结果。实际上,

我们就可以将一个 ResultSet对象看成一个表。对 ResultSet对象的处理必须逐行进行,而对每一行中的

各个列,可以按任何顺序进行处理。

� 行与指针:ResultSet对象维持一个指向当前行的指针。最初,这个指针指向第一行之前。Result类

的 next()方法使这个指针向下移动一行。因此,第一次使用 next()方法将指针指向结果集的第一行,

这时可以对第一行的数据进行处理。处理完毕后,使用 next()方法,将指针移向下一行,继续处理

第二行数据。next()方法的返回值是一个 boolean型的值,该值若为 true, 说明结果集中还存在下一

条记录,并且指针已经成功指向该记录,可以对其进行处理;若返回值是 false,则说明没有下一行

记录,结果集已经处理完毕。

� 取得列:在对每一行进行处理时,可以对各个列按任意顺序进行处理。不过,按从左到右的顺序

对各列进行处理可以获得较高的执行效率。ResultSet 类的 getXXX()方法可以从某一列中获得检

索结果。其中 XXX是 JDBC中的 Java数据类型,如 int、String、Date等,这与 PreparedStatement

类和 CallableStatement类设置 SQL语句参数值相类似。Sun 公司提供的 getXXX() API 提供两种

方法来指定列名进行检索:一种是以一个 int 值作为列的索引,另一种是以一个 String 对象作为

列名来索引。

下面是一段简单的显示检索结果的 JSP源代码:

<%

Statement statement=conn.createStatement();

//在 Connection 对象的基础上创建 Statemetn 对象

String sql="SELECT int_colmn, string_colmn,date_colmn," +" byte_colmn FROM table_name";

Page 24: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

66

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

ResultSet result=statement.executeQuery(sql);

//用 Statement 对象执行 SQL 语句,返回结果集

while(result.next()) {

int int_value=result.getInt(1);

String string_value=result.getString("colmn2");

Date date_value=result.getInt(3);

Byte byte_value[]=result.getString("colmn4");

//从数据库中以两种不同的方式取得数据

out.println(int_value+" "+string_value+" "+date_value+" ");

//将检索结果在用户浏览器上输出

}

%>

与 Statement、Connection对象相似,在使用完 ResultSet对象时,应显式地关闭该对象:

rs.close();

2. 获取结果集的信息

在对数据库的表结构已经了解的前提下,可以知道返回的结果集中各个列的一些情况,如:列名数

据类型等。有时并不知道结果集中各个列的情况,这时可以使用 Resultset类的 getMetaData方法来获取

结果集的信息。

ResultsetMetaData rsdata=resultset.getMetaData();

GetMetaData()方法返回一个 ResultSetMetaData 类的对象,使用该类的方法,得到许多关于结果集

的信息,下面给出几个常用的方法:

(1) getColumnCount():返回一个 int 值,指出结果集中的列数;

(2) getTableName(int column):返回一个字符串,指出参数中所代表列的表的名称;

(3) getColumnLabel(int column):返回一个 String 对象,该对象是 column 所指的列的显示标题;

(4) getColumnName(int column):返回的是该列在数据库中的名称。可以把此方法返回的 String 对象作为

Resultset 类的 getXXX()方法的参数。不过,并没有太大的实际意义;

(5) getColumnType(int comlumn):返回指定列的 SQL 数据类型。它的返回值是一个 int 值。在 java.sql.Types

类中有关于各种 SQL 数据类型的定义;

(6) getColumnTypeName(int comlumn):返回指定列的数据类型在数据源中的名称。它的返回值是一个 String 对象;

(7) isReadOnly(int column) :返回一个 boolean 值,指出该列是否是只读的;

(8) isWriteable(int column) :返回一个 boolean 值,指出该列是否可写;

(9) isNullable(int column):返回一个 boolean 值,指出该列是否允许存入一个 NULL 值。

4.3.5 PreparedStatement 接口

在前文中我们讨论了用连接对象 Connection 产生 Statement 对象,然后用 Statement 与数据库管理

系统进行交互。Statement对象在每次执行 SQL语句时都将该语句传递给数据库。在多次执行同一语句

时,这样做效率较低。解决这个问题的办法是使用 PreparedStatement对象。如果数据库支持预编译,可

以在创建 PreparedStatement对象时将 SQL语句传递给数据库做预编译,以后每次执行这个 SQL语句时,

速度就可以提高很多。如果数据库不支持预编译,则在语句执行时,才将其传给数据库。这对于用户来

说是完全透明的。

PreparedStatement 对象的 SQL 语句还可以接收参数。在语句中指出需要接受那些参数,然后进行

Page 25: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

67

预编译。在每一次执行时,可以将不同的参数传递给 SQL 语句,大大提高了程序的效率与灵活性。一

般情况下,使用 PreparedStatement对象都是带输入参数的。下面来看如何使用 PreparedStatement。

1. 创建一个 PreparedStatement 对象

PreparedStatement类是 Statement类的子类。同 Statemetn类一样,PreparedStatement类的对象也是

建立在 Connection对象之上的。我们为在 COFFES表中更新数据数据创建一个 PreparedStatement对象: PreparedStatement updateSales = conn.prepareStatement("UPDATE GOODS SET SALES = ? WHERE

GOODS_NAME LIKE ?");

创建该 PreparedStatement对象时,相应的更新记录的 SQL语句已经被传递到数据库管理系统中进

行预编译。在这里应该提醒读者,PreparedStatement 类是 Statement 类的子类,Statemetn 类的方法

PreparedStatement的对象都可以调用。另外,在建立 PreparedStatement对象之前,应该保证 Connection

对象已经被正确的建立。

2. 为 PreparedStatement 对象提供参数

如果以带输入参数的SQL语句形式创建了一个PreparedStatement对象(绝大多数情况下都是如此)。

在 SQL语句被数据库管理系统正确执行之前,必须为参数(也就是 SQL语句中是"?"的地方)进行初始

化。初始化的方法是调用 PreparedStatement类的一系列 setXXX()方法。如果输入参数的数据类型是 int

型,则调用 setInt()方法;如果输入参数是 String型,则调用 setString()方法。一般说来,Java中提供的

简单和复合数据类型,都可以找到相应的 setXXX()方法。继续前面的例程:

updateSales.setInt(1, 75);

updateSales.setString(2, "Colombian");

setXXX()方法有一般有两个参数,第一个参数都是 int型,该参数指示 JDBC PreparedStatement对

象的第几个参数将要被初始化。第二个参数的值就是 PreparedStatemetn将要被初始化的参数取值,数据

类型自然也就相同。"updateSales.setInt(1,75);"语句使 updateSales对象所对应的 SQL语句中参数 SALES

的值被初始化为 75;"updateSales. setString(2, "goods1");"语句使 updateSales对象所对应的 SQL语句中参

数 GOODS_NAME的值被初始化为 goods1。

当 PreparedStatement的一个对象的参数被初始化以后,该参数的值一直保持不变,直到它被再一次

赋值为止。下面的代码可以很好地说明这个问题:

updateSales.setInt(1, 100);

updateSales.setString(2, "good2");

updateSales.executeUpdate();

// 将商品名为"goods"的记录的销售额设置为 100

updateSales.setString(2, "good3");

updateSales.executeUpdate();

// 将商品名为"goods"的记录的销售额设置为 100

我们可以看到,这段代码的前一部分分别对 GOODS_NAME和 SALES的值进行了设置。然后才调

用 executeUpdate()方法执行 SQL语句。而在这段代码的后一部分,只设置了 GOODS_NAME的值,Sales

的值没有进行更新,Sales的值将维持 100不变。再次调用 updateSales对象执行 SQL语句时,会把商品

名为"goods"的记录的销售额也设置为 100。

在这里顺便提醒读者,PreparedStatement 对象的 executeUpdate()方法不同于 Statement 对象的

executeUpdate()方法,前者是不带参数的,其所需要的 SQL语句型的参数已经在实例化该对象时提供了。

Page 26: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

68

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

3. 使用循环结构设置 PreparedStatement 对象的参数

在 JSP 的实际应用中,PreparedStament 对象要求输入大量的参数值,这就需要使用循环结构来解

决烦琐的参数赋值问题。我们继续前面的例子:

int [] salesForWeek = {100, 85, 95, 125, 90};

String [] goodsname = {"goods1", "goods2", "goods3","good4", "goods5"};

int len = goodsname.length;

for(int i = 0; i < len; i++) {

updateSales.setInt(1, salesForWeek[i]);

updateSales.setString(2, goodsname[i]);

updateSales.executeUpdate();

}

在这段代码中,用 int型数组来存储将要被更新记录的销售额,用 String型数组存储将要被更新记

录的商品名。这两个数组的值一一对应,销售额 100对应着商品名为 goods1的记录;销售额 85对应着

商品名为 goods2 的商品,依次类推。我们以后想再次更新数据库中的数据时,可以将这段代码当作模

版,只需将数组中的数据进行修改,就可以完成要求的功能了。

4. PreparedStatement 对象的 executeUpdate()方法的返回值

executeQuery()方法的返回值是一个包含符合特定要求的数据库的结果集,executeUpdate()方法并非

如此,该方法返回一个整数,这个整数代表 executeUpdate()方法执行后所更新的数据库中记录的行数。

我们看下面的例子:

updateSales.setInt(1, 85);

updateSales.setString(2, "goods2");

int n = updateSales.executeUpdate();

// n = 1

这段代码执行后,GOODS表中商品名是"goods2"的记录,销售额被更新为 85,有一条记录受到了

影响。因此 n的值是 1。

当 PreparedStatement 对象的 executeUpdate()方法所执行的 SQL 语句是诸如建立表格、修改表格、

删除表格的 DDL 类型时,SQL 语句并不是直接对表中的记录进行操作,这时,executeUpdate()方法的

返回值是 0。例如,下面的语句:

String dropTable="Drop Table GOODS";

int n = updateSales.executeUpdate(createTableCoffees);

// n = 0

这里应该注意一点,当 PreparedStatement对象的 executeUpdate()方法的返回值是 0时。有两种可能:

(1)所执行的 SQL语句是对数据库管理系统的记录进行操作,并且没有记录被更新;

(2)所执行的 SQL语句是对数据库管理系统的表、视图等对象进行操作的 DDL语言,没有数据

记录被直接修改。

4.3.6 CallableStatement 对象

通过PreparedStatement对象访问数据库时,SQL语句是在 JSP程序已经由Web Server编译为Servlet,

Servlet由 Java 虚拟机解释执行,PreparedStatement对象被实际创建的时候,才传递给数据库管理系统,

Page 27: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

69

需要数据库管理系统在程序运行的时候编译 SQL,这仍然会消耗一些程序执行时间。能不能在 JSP 程

序执行之前,就将 SQL 语句由数据库管理系统编译好,从而进一步缩短程序执行时间,提高运行效率

呢?答案是肯定的。这要通过我们在这一小节介绍的 CallableStatement对象调用数据库管理系统的存储

过程(Stored Procedure)来实现。

在学习 CallableStatement对象之前,有必要介绍一下存储过程的概念。

1. 存储过程定义和优点

(1)存储过程的概念

存储过程是存储在数据库管理系统服务器上的一组欲编译的 SQL 语句。它是一种封装重复任务操

作的方法,支持用户提供的变量,具有强大的编程功能。

存储过程非常类似于 DOS操作系统中的 BAT文件。在 BAT文件中,可以包含多个经常执行的命

令,执行 BAT文件,实际上就是执行这组命令。同样,可以把用来完成某项任务的许多 SQL语句编写

在一起,组成一个存储过程。然后,执行该存储过程就可以完成该项任务。

存储过程是存储在数据库管理系统的服务器上,并且由服务器来运行的,这使它具有许多优点。从

性能上讲,存储过程是预编译的,节省了数据库管理系统的编译时间,所以存储过程比一般的需要进行

编译的 SQL 语句的执行速度要快很多。另外,由于数据库信息已存储在同一系统中,因此不必等待记

录通过网络传递过来就可以进行处理。所以,存储过程可以立即对数据库进行访问,这使得信息的处理

非常迅速。从客户机/服务器开发方面来看,将客户机和服务器的开发任务分开,可以减少完成项目所

需要的时间。用户可以独立地开发服务器端组件而不涉及客户端,并可以在客户端的应用程序中重复使

用服务器端的组件。

存储过程可以返回值、修改值,也可以将系统欲请求的信息与用户提供的值进行比较。在一般的数

据库管理系统的配置情况下,存储过程可以快速的运行。用户还可以向存储过程传递值,这些值在存储

过程运行期间可以参加运算。

(2)存储过程的优点

使用存储过程的优点如下。

首先,使用存储过程可以与其他应用程序共享应用程序的逻辑,从而确保对数据访问和操作的一致

性。存储过程可以封装企业的功能模块,这种企业的功能模块也称为商业规则或者商业策略,可以只在

一个地方修改和维护。所有的客户机程序都可以使用同一个存储过程进行各种操作,从而确保数据修改

的一致性。

其次,存储过程提供一种安全机制。如果用户被授权执行存储过程的权限,那么,即使该用户没有

访问该存储过程所参考表的或者视图的权限,也可以执行该存储过程,而不会受到影响。因此,可以创

建存储过程来完成所有的增加、删除等操作,并且可以通过编程方式控制上述操作中对信息的访问。

再次,由于存储过程在第一次执行之后,其执行规划就储存在高速缓冲存储器中,所以在以后的操

作中,只要从高速缓存中调用已编译好的二进制代码来执行,从而加速了存储过程的执行,提高了系统

的性能。

最后,使用存储过程可减少网络传输所需要的时间。这是使用存储过程的一条非常重要的原因。如

果有一千条 SQL 语句,一条一条的通过网络在客户机和服务器之间传送,那么这种传输所耗费的时间

非常长,即使是世界上最有耐心的人也无法忍受。但是,如果把这一千条 SQL 语句的命令写成一条较

为复杂的存储过程命令,在客户机和服务器之间进行网络传输所需要的时间就会大大减少。

Page 28: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

70

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

2. 在 JSP 中为数据库管理系统创建存储过程

存储过程一般是在数据库管理系统中创建,在应用程序中进行调用,但在有些情况下,应用程序要

根据运行环境的情况动态创建存储过程。比如说一种存储过程要向一个表中插入数据,但向哪个表中插

入数据是不固定的,要动态的决定。这时就需要在 JSP中创建存储过程,请看下面的代码:

<%

String tablename=table;

String procedurename="insert_value_"+tablename;

String sqlstr="CREATE PROCEDURE "+procedurename+

"(new_keyword IN data.keyword%TYPE, new_title IN data.title%TYPE,"+

"new_author IN data.author%TYPE, new_institution IN data.institution%TYPE,"+

" new_docsource IN data.docsource%TYPE, new_ndatabase IN data.ndatabase%TYPE,"+

" new_url IN data.url%TYPE) AS begin INSERT INTO "+tablename+

"(keyword,title,author,institution,docsource,ndatabase,url)"+ VALUES(new_keyword, new_title,

new_author, new_institution,new_docsource,"+

" new_ndatabase, new_url); end;";

try{

Statement stmt=conn.createStatement();

stmt.executeUpdate(sqlstr);

}catch(SQLException e) {}

%>

请读者注意,不同数据库管理系统创建存储过程的 SQL 语句的语法是有一定差别的,这里的例子

用的是 Oracle创建存储过程的语法。

下面通过程序来讲解创建存储过程的步骤。

(1)创建一个 CallableStatement对象

JSP 调用数据库管理系统的存储过程必须要通过 CallableStatement 类的对象。CallableStatement 类

是 PreparedStatement类的子类,它可以使用 Statement类和 PreparedStatement类中的方法。同它的父类

一样,一个 CallableStatement类的对象也必须建立在一个 Connection类的对象之上。下面代码创建一个

CallableStatement对象用以调用存储过程:

String procedurename=…

//将前一段代码创建的存储过程名赋值给变量 procedurename

String call_procedure_string="{call "+procedurename+"(?,?,?,?,?,?,?)}";

//all_procedure_string 代表调用存储过程的实际命令,{call procedurename(?,?,?...)}是 JDBC 定义的固定格式。

{call }是固定不变的。Procedurename 代表要调用的存储过程的名称

CallableStatement cablestatement = con.prepareCall(call_procedure_string);

//创建一个 CallableStatement 对象,该对象和特定的存储过程相关联

(2)初始化 CallableStatement对象的参数

同父类一样,CallableStatement对象一般都与一个需要输入参数的 SQL语句相关联。在该 SQL语

句被数据库管理系统执行之前,一定要对参数进行初始化。请看下面的示例代码:

<%

String keyword=request.getParameter("kword");

String title=request.getParameter("title");

String author=request.getParameter("author");

String institution=request.getParameter("institution");

Page 29: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

71

String docsource=request.getParameter("docsource");

String ndatabase=request.getParameter("ndatabase");

String url=request.getParameter("url");

//从前一个 html 页面提交的表单中提取需要的信息初始化各个变量

try{

callablestmt.setString(1,keyword);

callablestmt.setString(2,title);

callablestmt.setString(3,author);

callablestmt.setString(4,institution);

callablestmt.setString(5,docsource);

callablestmt.setString(6,ndatabase);

callablestmt.setString(7,url);

}catch(SQLException e) {

}

%>

同它的父类一样,为 CallableStatement 对象对应的 SQL 语句的特定参数进行初始化,也要调用与

参数的数据类型相同的 setXXX()方法,如 setString(), setInt()等。

(3)执行 CallableStatement对象的 executeUpdate()方法

在 CallableStatement 对象对应的 SQL 语句的参数被初始化以后,我们就可以将该语句传递给数据

库管理系统执行,取得执行结果了。

try{

callablestmt.executeUpdate();

}catch(SQLException e) {

}

至此,一个完整的 CallableStatement对象的使用过程就完成了。读者可以自己作一个实验,分别用

Statement 对象的 executeUpdate(String sql)方法和 CallableStatement 的 executeUpdate()方法向一个 table

中插入 2000 条记录,各自记录下执行时间,再进行比较,会得出什么样的结论。

4.4 配置连接 MySQL 并进行测试

前面的三个小节都在讲解 JSP 和 JDBC 的核心技术,现在我们就利用前面介绍的技术知识来开发

JSP的原型功能,其中连接的数据库使用MySQL。

本节使用光盘中 JDBCTest.zip 下的文件来建立 MySQL 数据库的连接环境并进行测试,请先启动

MySQL服务。

4.4.1 添加 MySQL 驱动 mysql-connector-java-5.0.8-bin.jar

在使用 JDBC连接数据库时,需要使用相应的驱动程序。不同的数据库、不同的版本,其驱动程序

也不同,也可能有多个驱动程序可用。这些驱动程序都是一个 jar的包,通常有该数据库的发布厂商或

其他的机构提供。

我们这里所使用的数据库是 MySQL 5.5.0,因此选择了与之相匹配的驱动程序包 mysql-connector-

java-5.0.8-bin.jar。该包可以在MySQL的官方网站上下载,在本书光盘中的位置为\JDBCTest\WebContent\

Page 30: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

72

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

WEB-INF\lib\mysql-connector-java-5.0.8-bin.jar。请复制该文件到前面新建的项目 \demo\WebContent\

WEB-INF\lib 目录下。这样,我们的项目就有了数据库的驱动程序,就可以通过加载该驱动程序使用

JDBC来访问数据库了。

4.4.2 数据库参数文件 inc.jsp

添加完驱动程序,MySQL数据库服务也已经启动,在项目开始之前,我们编写一个测试程序,来

测试数据库是否可以正常连接。

首先建立一个数据库连接参数配置文件 inc.jsp:

①前 5行使用 JSP的 Page指令导入 JDBC的五个基础类,分别用于进行数据库连接、创建申明对

象和查询结果的显示。

②接下来使用 JSP 的脚本指令,即在<%...%>之间定义四个变量 drv、url、usr、pwd,分别赋予连

接数据库的驱动名、URL、用户名、密码。

最后的代码如下所示:

程序 4-1 MySQL 连接配置文件 inc.jsp

<%@ page import="java.sql.Connection"%>

<%@ page import="java.sql.DriverManager"%>

<%@ page import="java.sql.Statement"%>

<%@ page import="java.sql.ResultSet"%>

<%@ page import="java.sql.ResultSetMetaData"%>

<%

String drv = "com.mysql.jdbc.Driver";

String url = "jdbc:mysql://localhost:3306/demo";

String usr = "root";

String pwd = "";

%

该文件在光盘中的位置为\blank\jdbc_blank\inc.jsp。

4.4.3 测试 MySQL 连接 testjdbc.jsp

接下来新建一个 JSP文件 testjdbc.jsp来测试数据库连接。该文件依次包含下面几个部分的代码:

①第 1行使用 JSP的 Page指令设置页面语言和编码;

②第 2行使用 include指令包含MySQL连接配置文件 inc.jsp;

③定义一个 SQL语句变量 sql,用于从用户表 user中查询所有记录;

④调用 Class.forName()方法加载 inc.jsp 中定义的驱动程序,调用 DriverManager.getConnection()的

方法使用 inc.jsp中定义的变量 url、usr、pwd取得数据库连接对象 conn;

⑤使用数据库连接对象 conn创建申明对象 stm,并调用 executeQuery()执行查询,返回结果集对象

rs和结果集描述对象 rsmd,cols表示该结果集的列数;

⑥使用 while 循环 rs 结果集的每一行,并对该行的所有列 cols 进行循环,显示每一列的字段名和

值;

⑦最后依次关闭 rs、stm、conn对象,需要注意的是,关闭的顺序必须与建立的顺序相反;

Page 31: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

73

程序 4-2 测试 MySQL 连接 testjdbc.jsp

<%@page language="java" contentType="text/html;charset=gb2312"%>

<%@ include file="inc.jsp"%>

<%

String sql = "select * from user";

try {

Class.forName(drv).newInstance();

Connection conn = DriverManager.getConnection(url, usr, pwd);

Statement stm = conn.createStatement();

ResultSet rs = stm.executeQuery(sql);

ResultSetMetaData rsmd = rs.getMetaData();

int cols = rsmd.getColumnCount();

while (rs.next()) {

for (int i = 1; i <= cols; i++) {

String field = (String) (rsmd.getColumnName(i));

String value = (String) (rs.getString(i));

out.print(field + "=" + value + ";");

}

}

rs.close();

stm.close();

conn.close();

} catch (Exception e) {

e.printStackTrace();

out.println(e);

}

%>

该文件在光盘中的位置为\blank\jdbc_blank\testjdbc.jsp。

此时启动 Tomcat,访问 http://localhost:8081/demo/testjdbc.jsp,如果能够显示一条预添加的记录(该

记录是在创建数据库时添加的),则表明连接数据库成功,也标志着我们的应用程序的 MySQL 数据库

环境已经可以正常使用了。

4.5 开发 JSP 显示页面和响应处理页面

通过前文的讲解,关于 JSP、JDBC 的知识及与 MySQL 的连接都已经准备就绪,接下来就来开发

JSP的架构原型,也即所有的显示和响应均使用 JSP文件来进行开发。

JSP的原型中,显示的页面是普通的 JSP页面,接收响应的页面用来处理普通 JSP页面的请求,我

们使用“_action”后缀名的形式命名。

根据第 2章的需求设计与流程分析,我们需要开发 6个 JSP文件,它们之间的关系如图 4-3所示。

其中 login.jsp、welcome.jsp、register.jsp为显示页面,login_actin.jsp、logout.jsp、register_action.jsp

为处理响应的页面。下面就来看看如何编写每一个页面。

① ②

Page 32: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

74

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

登录页面

login.jsp

注册页面

register .jsp

登录操作

login_actionjsp

登录

注册

欢迎页面

welcome.jsp

退出操作

logout.jsp

注册操作register_action.jsp

图 4-3 JSP 页面流程

4.5.1 登录页面 login.jsp

首先我们来新建一个登录页面 login.jsp。Eclipse为我们提供了新建 JSP页面的快捷向导,单击菜单

【File�JSP】,选择新建 JSP页面,则显示如图 4-4所示的窗口。

图 4-4 新建 JSP 页面

在该窗口中包含三个选项,默认我们只需要修改第二个选项,即填写你要创建的文件名。这里我们

填写“login.jsp”,单击【完成】按钮完成新建,此时在项目 demo 的 WebContent 目录下就会出现该文

件的图标。双击打开该文件,其代码包含如下几个部分:

①第 1行是 JSP页面的固定语句,使用 Page指令设置页面语言为 java、导入 Java包 java.util.*、设

置页面编码为 UTF-8;

②通过 request对象取得当前文件的上下文路径 path,并通过 request对象取得协议、主机名、端口,

Page 33: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

75

将这四个变量组合起来形成一个 URL的路径;

③设置 HTML 的 head 信息,将取得的 URL 路径设置到<base>标签中,这样当前页面就拥有了访

问路径的属性。并设置 HTML页面的标题元素 title、元信息 meta,以及 CSS引用文件。这里的 CSS引

用使用 HTML的注释<!--…-->给注释掉了,在后面的开发中我们会添加一个 CSS文件,将会去掉这里

的注释;

④设置 HTML的 Body信息,即添加页面的主题内容。

该文件是使用 Eclipse向导创建的默认 JSP文件,这里的代码也是固定的,因此在后文的代码讲解

中,将不再重复粘贴类似的代码。最终的代码如程序 4-3所示。

程序 4-3 登录页面 login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<base href="<%=basePath%>">

<title>My JSP 'login.jsp' starting page</title>

<meta http-equiv="pragma" content="no-cache">

<meta http-equiv="cache-control" content="no-cache">

<meta http-equiv="expires" content="0">

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

<meta http-equiv="description" content="This is my page">

<!--

<link rel="stylesheet" type="text/css" href="styles.css">

-->

</head>

<body>

This is my JSP page. <br>

</body>

</html>

登录页面的作用是让用户进行登录,根据需求设计中该页面的设计可知,需要添加两个表单项,分

别是用户名和密码,并需要提供一个登录按钮和一个引入到注册页面 register.jsp的链接。这部分的代码

如程序 4-4所示。

程序 4-4 登录页面 login.jsp 的表单

<form name="form1" action="login_action.jsp" method="post">

<table width="200" border="1">

<tr>

<td colspan="2">登录窗口</td>

<tr>

Page 34: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

76

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

<td>用户名</td>

<td><input type="text" name="username" size="10"></td>

</tr>

<tr>

<td>密码</td>

<td><input type="password" name="password" size="10"></td>

</tr>

<tr>

<td colspan="2"><input type="submit" name="submit" value="登录"> <a href="register.jsp">注册新用户

</a></td>

</tr>

</table>

</form>

其中的表单元素 action属性为 login_action.jsp,表示响应的页面。该页面的显示效果如图 4-5所示。

图 4-5 登录页面效果图

4.5.2 登录验证操作 login_action.jsp

接下来开发登录提交时的相应处理页面 login_action.jsp。该页面不用于显示,其作用是检验用户的

用户名和密码是否合法。按照顺序需要编写以下的代码:

①由于要进行数据库查询,因此首先使用 include指令包含数据库配置文件 inc.jsp;

②取得 login.jsp页面中用户输入的用户名和密码的参数变量 username和 password;

③检查用户名和密码是否为空,如果有一个为空,则返回页面 login.jsp重新登录;

④定义一个变量 isValid来表示是否验证通过。根据用户名和密码的参数组合查询的 SQL语句,从

用户表 user中查询记录。建立数据库的连接,并执行该 SQL语句的查询。如果能够查询到记录,则表

示用户名和密码正确,则赋予 isValid为 true。并依次关闭 rs、stm、conn对象;

⑤判断 isValid 的值,如果为真,则表示验证通过,此时需要调用 Session 的 setAttritute()方法来保

存用户的用户名,并跳转到欢迎页面 welcome.jsp;如果为假,则返回到登录页面 login.jsp。

最后的代码如程序 4-5所示。

程序 4-5 登录验证操作 login_action.jsp

<%@ include file="inc.jsp"%>

<%

//get parameters

String username = request.getParameter("username");

Page 35: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

77

String password = request.getParameter("password");

//check null

if (username == null || password == null) {

response.sendRedirect("login.jsp");

}

//validate

boolean isValid = false;

String sql = "select * from user where username='"+username+"' and password='"+password+"'";

try {

Class.forName(drv).newInstance();

Connection conn = DriverManager.getConnection(url, usr, pwd);

Statement stm = conn.createStatement();

ResultSet rs = stm.executeQuery(sql);

if(rs.next())isValid = true;

rs.close();

stm.close();

conn.close();

} catch (Exception e) {

e.printStackTrace();

out.println(e);

} finally {

}

if (isValid) {

session.setAttribute("username", username);

response.sendRedirect("welcome.jsp");

} else {

response.sendRedirect("login.jsp");

}

%>

4.5.3 欢迎页面 welcome.jsp

当登录验证成功时,将会跳转到欢迎页面 welcome.jsp。该页面是 JSP 架构原型的导航页面,即通

过该页面可以添加新的功能,并提供到新功能的导航链接。页面包含如下几部分内容:

①页面顶部显示 LOGO 区域,显示两张图片,并在图片下方显示一条横线<hr>;

②这里的导航是通过显示一系列的链接来实现的,页面按照左右两部分显示,左侧显示导航链接;

③右侧显示欢迎信息,并从 Session中取出登录用户的用户名。在该部分还显示了一个表单,当单

击【退出】按钮时,提交到 logout.jsp执行退出操作。

文件代码如程序 4-6所示。

程序 4-6 欢迎页面 welcome.jsp

<table width="100%">

<tr>

<td><img src="images/logo4.png"></td>

<td><img src="images/logo2.png" height="90"></td>

Page 36: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

78

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

</tr>

<tr>

<td colspan="2">

<hr>

</td>

</tr>

<tr>

<td>

<table>

<tr>

<td><a href="welcome.jsp">Main</a></td>

</tr>

<tr>

<td><a href="menu1.jsp">Menu1</a></td>

</tr>

<tr>

<td><a href="menu2.jsp">Menu2</a></td>

</tr>

<tr>

<td><a href="menu3.jsp">Menu3</a></td>

</tr>

<tr>

<td><a href="menu4.jsp">Menu4</a></td>

</tr>

<tr>

<td><a href="menu5.jsp">Menu5</a></td>

</tr>

<tr>

<td><a href="menu6.jsp">Menu6</a></td>

</tr>

<tr>

<td><a href="menu7.jsp">Menu7</a></td>

</tr>

<tr>

<td><a href="menu8.jsp">Menu8</a></td>

</tr>

</table>

</td>

<td>

<form name="form1" action="logout.jsp" method="post">

<table width="200" border="1">

<tr>

<td colspan="2">登录成功</td>

<tr>

<td>欢迎你,</td>

<td><%=(String) session.getAttribute("username")%></td>

</tr>

<tr>

<td colspan="2"><input type="submit" name="submit" value="退出"></td>

</tr>

</table>

Page 37: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

79

</form>

</td>

</tr>

</table>

欢迎页面最后的显示效果如图 4-6所示。

图 4-6 欢迎页面效果图

4.5.4 退出操作 logout.jsp

当单击欢迎页面中的“退出”按钮时,会跳转到 logout.jsp执行退出操作。它要做两件事,一个是

清空 Session中保存的用户信息,一个是返回到登录页面 login.jsp。代码如程序 4-7所示。

程序 4-7 退出操作 logout.jsp

<%

session.removeAttribute("username");

response.sendRedirect("login.jsp");

%>

4.5.5 注册页面 register.jsp

当单击登录页面中“注册新用户”的链接时,会跳转到注册页面 register.jsp。根据需求设计中对注

册页面的设计可知,该页面负责显示注册输入的表单。共包括 4 个表单:用户名、密码、确认密码、

Email地址,并在最后显示一个登录按钮和一个“返回”链接。该表单提交的地址为 register_action.jsp。

最后的代码如程序 4-8所示。

程序 4-8 注册页面 register.jsp

<form name="form1" action="register_action.jsp" method="post">

<table width="200" border="1">

<tr>

<td colspan="2">注册窗口</td>

Page 38: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

80

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

<tr>

<td>用户名</td>

<td><input type="text" name="username" size="10"></td>

</tr>

<tr>

<td>密码</td>

<td><input type="password" name="password1" size="10"></td>

</tr>

<tr>

<td>确认密码</td>

<td><input type="password" name="password2" size="10"></td>

</tr>

<tr>

<td>Email</td>

<td><input type="text" name="email" size="10"></td>

</tr>

<tr>

<td colspan="2"><input type="submit" name="submit" value="登录"> <a href="login.jsp">返回</a></td>

</tr>

</table>

</form>

该页面显示的效果如图 4-7所示。

图 4-7 注册页面效果图

4.5.6 注册用户操作 register_action.jsp

当单击注册页面中的“注册”按钮时,会提交到 register_action.jsp执行注册操作。该页面的逻辑是

先查询数据库中是否有该用户存在,如果不存在则执行添加。按照顺序需要编写以下的代码:

①由于要进行数据库查询,因此首先使用 include指令包含数据库配置文件 inc.jsp;

②取得 register.jsp页面中用户输入的用户名 username、密码 password1、确认密码 password2、Email

参数 email;

③检查用户名、密码、确认密码是否为空,及两个密码是否相等,如果有一个为空或密码不相等,

则返回页面 register.jsp重新注册;

④定义一个变量 isValid 来表示是否注册成功。根据用户名参数查询用户表 user,建立数据库的连

Page 39: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

81

接,并执行该 SQL 语句的查询。如果能够查询到记录,则表示该用户名已经存在了,否则会组合一个

Insert的 SQL语句,插入一个新注册用户,并设置 isValid为 true;并依次关闭 rs、stm、conn对象;

⑤判断 isValid的值,如果为真,则表示注册成功,此时跳转到登录页面 login.jsp;如果为假,则返

回到注册页面 register.jsp。

最后的代码如程序 4-9所示。

程序 4-9 注册用户操作 register_action.jsp

<%@ include file="inc.jsp"%>

<%

//get parameters

String username = request.getParameter("username");

String password1 = request.getParameter("password1");

String password2 = request.getParameter("password2");

String email = request.getParameter("email");

//check null

if (username == null || password1 == null || password2 == null || !password1.equals(password2)) {

response.sendRedirect("register.jsp");

}

//validate

boolean isValid = false;

String sql = "select * from user where username='"+username+"'";

try {

Class.forName(drv).newInstance();

Connection conn = DriverManager.getConnection(url, usr, pwd);

Statement stm = conn.createStatement();

ResultSet rs = stm.executeQuery(sql);

if(!rs.next()) {

sql = "insert into user(username,password,email) values('"+username+"','"+password1+"','"+email+"')";

stm.execute(sql);

isValid = true;

}

rs.close();

stm.close();

conn.close();

} catch (Exception e) {

e.printStackTrace();

out.println(e);

}

if (isValid) {

response.sendRedirect("login.jsp");

} else {

response.sendRedirect("register.jsp");

}

%>

Page 40: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

82

开发者突击:Java Web 主流框架整合开发(J2EE+Struts+ Hibernate+Spring)(第 2 版)

4.6 架构 1:demo(JSP).zip

到此为止,我们已经开发完需求分析中原型的需求功能,即登录、退出与注册。从前面的代码中可

以看出,这些代码完全是基于本章中所讲解的 JSP基础语法、内置对象和 JDBC 核心技术编写的。

我们将现在的项目打包为 demo(JSP).zip,保存在光盘\source 目录中。这个包就是 JSP 的原型程

序包,你可以在该原型基础上开发新的基于 JSP结构的功能。下面我们来对该架构原型程序包进行总

结。

4.6.1 程序结构图

该原型程序包的目录结构如图 4-8所示。

图 4-8 程序结构图

demo为项目的名称,也为项目的根目录。src目前还是空的,WebContent为Web目录,包括图片

目录 images和 8个 JSP文件。WEB-INF目录、lib目录及 web.xml 依然为固定的目录和文件。

4.6.2 系统架构图

现在所形成的程序包我们称为 JSP架构原型。也即完全使用 JSP文件进行开发的系统基础,可以参

照这里的请求和响应方式开发新的 JSP文件,实现新的功能。该系统架构图如图 4-9所示。

JSP

request

response

JDBC

图 4-9 系统架构图

从图 4-9中可以看出,用户的请求会发送给 JSP页面,JSP页面调用 JDBC来访问数据库,然后再

返回响应。

Page 41: 第2部分 J2EE基础架构篇 - images.china-pub.comimages.china-pub.com/ebook195001-200000/197914/ch04.pdf · 44 开发者突击:Java Web 主流框架整合开发(J2EE+Struts+

第 4 章 开发 JSP 框架

83

4.6.3 如何在该架构上开发新的功能

原型的好处是可以拿过来直接开发新的功能。在 JSP的架构原型中,如果要扩展开发新的功能模块,

由于 JSP即是显示页面又可以响应请求,因此对于一个功能,只需要开发两个文件:

� JSP 表单显示文件:用于显示供用户输入的表单;

� JSP 响应处理文件:用户输入提交时的相应页面,通常按照习惯可以在命名上增加一个后缀

“_action”以示区别。

4.7 继续下一主题:开发 JSP+JavaBean 框架

本章重点讲解了 JSP基本语法知识、内置对象、JDBC技术,然后基于这些技术的讲解来连接MySQL

数据库,开发 JSP显示页面和响应处理页面的架构原型。此时读者可以根据本章的学习来试着开发基于

JSP架构原型上的新的功能。

系统的开发不仅仅于此,只有 JSP的系统固然简单方便,但是也有可以改进之处。第 5章就通过为

JSP架构原型添加 JavaBean对象,来优化系统架构,并最终形成 JSP+JavaBean 框架原型。