版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7章动态显示信息
7.1目标及演示
7.2使用MySQL7.3编写UserBean7.4编写userlist.jsp7.5创建控制器
小结
习题7实训7:图书信息查询
7.1目 标 及 演 示
7.1.1功能描述
首先需要在数据库中建立存储用户信息的表,然后使用JSP
7.1.2运行效果
当点击查看用户信息的时候,会得到如图7.1图7.1所有用户信息
7.1.3相关文件
显示用户信息的功能包括3个文件:
● UserBean.java,需要在这个文件中添加一个查询方法,查询所有的用户信息。
● userlist.jsp,显示所有用户信息。
● FindAllUserServlet.java,控制器Servlet,调用UserBean中的查询所有用户的方法,传递给userlist.jsp。
7.1.4思路分析
根据前面介绍的MVC模式,对于本功能应该做如下设计:
(1)考虑V部分,也就是输入/输出,应该从用户的角度出发。用户要查看所有用户的信息,分两步:
●输入。用户要查看所有用户的信息,应该在某个界面上有一个超链接,通过点击这个超链接发送请求。所以只需要在需要查看所有用户信息的界面上增加一个超链接即可。
●输出。系统完成查询之后,界面要显示查询的结果。而这些信息是动态的,所以需要从控制层传递过来,这里需要知道要传递的信息的名字。我们使用userlist表示,这个名字相当于控制层与表示层之间的接口。因为查询的结果可能有很多,所以通常需要使用表格来呈现信息,使用标准标签库的<c:forEach>标签完成信息的输出。
(2)考虑M部分,也就是功能如何实现。该功能是查询所有用户信息,是与用户相关的操作,可以考虑使用前面介绍的UserBean,然后增加一个新的方法即可。方法的设计
如下:
●方法名。方法名要体现方法的功能,所以这里使用findAllUser。
●方法的参数。因为要查询所有的用户,不需要查询条件,所以参数列表为空。
●方法的返回值。查询的结果是多个用户,每个用户是一个对象,所以应该返回对象的集合,通常使用ArrayList。
●方法的异常列表。这里不需要考虑异常,所以异常列表为空。
●方法实现,访问数据库获取所有用户信息,然后把这些信息封装成对象,再把对象封装成集合对象。
(3)考虑C部分,也就是如何建立视图和模型之间的关联,这里使用Servlet来实现,设计过程如下:
●获取用户的输入信息,这个请求没有条件,所以不需要获取。
●调用模型,创建UserBean的对象,然后调用findAllUser方法,并保存返回的结果。
●把得到的结果存储在request对象中,使用名字userlist,这是前面界面设计时给出的名字。
●跳转到响应界面userlist.jsp。
图7.2文件之间的关系
7.2使用MySQL
7.2.1MySQL数据库的下载
本书使用的安装程序是:mysql-5.0.20-win32.exe7.2.2MySQL数据库的安装
安装前的准备工作和注意事项:
(1)首先检查计算机上是否已经安装了MySQL。方法是:打开【开始】【程序】,查看是否有MySQL的目录;或者到【服务】中查看是否有名为MySQL的服务。
(2)所有的安装目录必须是英文目录(不能是中文)。
下面是具体的安装过程:
(1)运行mysql-5.0.20-win32.exe,进入欢迎界面,如图7.3所示。
图7.3欢迎界面
(2)选择安装类型,这里选择默认的安装类型,即“Typical”,如图7.4所示。
图7.4选择安装类型
(3)下一个界面显示默认的安装目录,如图7.5所示。如果不想使用默认的安装目录,则可以点击【Back】按钮,回到前一界面,选择“Custom”,这样可以自己指定安装目录。
(4)点击【Install】开始安装,如图7.6所示。
图7.5安装信息确认
图7.6安装过程
图7.7注册
图7.8配置服务器
(7)点击【Finish】进入下一个界面:使用配置向导来配置MySQL实例,如图7.9所示。
图7.9开始配置
(8)点击【Next】进入下一个界面:选择配置类型,请选择标准配置“StandardConfiguration”,如图7.10所示。
图7.10选择配置类型
(9)点击【Next】进入下一个界面:设置Windows选项,默认情况下选择将MySQL安装为Windows服务,并在开机时自动启动该服务。注意选中“IncludeBinDirectoryinWindowsPATH”,这样会使得MySQL的bin目录被包含在Windows的环境变量PATH中,便于安装以后在命令行下执行MySQL命令,如图7.11所示。
图7.11服务设置
(10)点击【Next】进入下一个界面:设置安全选项,如图7.12所示。这里要求设置管理员root的口令,输入两遍相同的密码,一定要把它记住。选中“Enablerootaccessfromremotemachines”,则允许远程计算机使用root(管理员)登录到MySQL。选中“CreateAnAnonymousAccount”,会自动创建匿名用户,这样就可以不使用任何用户名登录到MySQL服务器。
图7.12设置口令
(11)点击【Next】进入下一个界面,直接点击【Execute】按钮开始配置,如图7.13所示。
图7.13开始配置
图7.13开始配置
(12)配置完成的界面如图7.14所示。
图7.14完成配置
(13)配置完成以后,首先到【控制面板】【管理工具】【服务】中查看是否有名为MySQL的服务,以及该服务是否已经启动,如图7.15所示。如果服务已经安装并且启动,说明安装成功。
图7.15查看安装的MySQL服务
7.2.3MySQL数据库的常用操作
1.登录和退出MySQL
要登录到MySQL数据库服务器,首先要进入命令行界面并输入如下的命令:
mysql-hhostname-uusername–p
图7.16是一个连接数据库的例子。
图7.16连接数据库
如果连接成功,应该出现mysql>提示符,这时就可以输入mysql命令和SQL语句了。
如果要退出mysql,只需要输入“quit”命令就可以了。
2.显示现有的数据库和表信息
连接到数据库服务器以后,通常需要对数据库中的表进行操作。首先需要查看数据库服务器上有哪些可用的数据库和表。
查看数据库的命令为:
showdatabases;
要想查看某个数据库中有哪些表,首先需要选择数据库。
选择数据库的命令为:
usedbname;选择了数据库以后,就可以对该数据库进行操作。
查看当前数据库中的表的命令为:
showtables;
如果想查看的数据库不是当前使用的数据库,可以使用下面的命令:
showtablesfromdbname;
该命令仅仅显示当前数据库中的表的名称。如果想查看某个表的结构,可以使用下面的命令:
desctablename;
要查看表中的列信息,使用下面的命令:
showcolumnsfromdbname.tablename;图7.17显示所有数据库和表
3.创建用户和授权
在安装完MySQL以后,默认的用户只有root用户。为了安全起见,root用户通常只用做管理目的。对于每个需要使用该数据库的用户(或应用),都应该为他们创建一个帐号和
密码。
通常情况下,使用MySQL数据库的用户并不需要root用户所拥有的所有权限。一个用户只需要拥有能够执行需要执行的任务的最低级别的权限就可以了。
创建用户的一种简单的方法是直接使用授权命令(grant)来授予权限。
授权命令的语法形式为:
grantprivileges[columns]ondbname.tablename
touser_name[identifiedby'password']
[with[grantoption|limit_options]];说明:
●
privileges应该是由逗号分开的一组权限。
●
columns是可选的,可以用它对每一列指定权限。
●
dbname.tablename用于指定使用权限的数据库和表。*或者*.*表示将权限用于所有数据库(全局权限)。要想指定权限用于某个数据库中的所有表(表级),可以写为dbname.*。
● user_name是登录MySQL使用的用户名,也可以加上@hostname以指定是来自哪个域的用户。
● password是用户登录时使用的密码。
● 如果指定withgrantoption选项,则表示允许指定的用户向别人授予自己所拥有的权限。
执行grant命令时,如果要授权的用户不存在,则系统会自动创建该用户。因此,授权命令也可以用来创建用户。
例如,如果要创建一个用户,允许访问当前的所有数据库和所有表,则可以使用下面的命令:
grantallon*.*tozhangidentifiedby'zhang123';
在该语句中创建的用户名为zhang,密码为zhang123,可以对所有数据库和表执行任何操作。
如果要创建一个用户,允许访问test数据库,则可以使用下面的命令:
grantallontest.*towangidentifiedby'wang123';创建好用户以后,可以使用下面的命令来查看数据库中现有的用户:
selectuserfrommysql.user;
可以在退出mysql以后,再次使用新创建的用户登录到mysql。
命令的运行结果如图7.18所示。
如果想要收回某个用户的权限,可以使用revoke命令。语法如下:
revokeprivileges[(columns)]ondbname.table
fromuser_name;
例如,如果希望删除用户wang,可以使用下面的命令:
revokeallprivilegesfromwang;
4.创建数据库和删除数据库
MySQL可以支持多个数据库。通常,每个应用程序都需要一个数据库。
创建数据库的命令是:
createdatabasedbname;
例如,本书中用到的数据库为bookstore,则可以使用下面的语句创建数据库:
createdatabasebookstore;
删除数据库的命令是:
dropdatabasedbname;图7.18连接到MySQL
5.创建表和删除表
创建好数据库以后,通常需要创建表。创建表可以使用SQL语句createtable。语法格式为:
createtabletablename(columns);
说明:
● tablename是要创建的表的名称。
● columns是表中包含的列。每个列都需要指定列名,后面加上该列的数据类型,还可以加上约束条件。如果有多个列,需要使用逗号分隔。
●也可以设置表级的约束条件。
例如,创建后面的实例时将要使用的用户表如下:
createtableusertable(
useridvarchar(8)primarykey,
usernamevarchar(10),
userpassvarchar(8),
typechar(1),
birthdaydate,
degreevarchar(10),
localvarchar(4),
emailvarchar(20),
addressvarchar(50),
commentvarchar(100)
)
要删除表,可以使用下面的语句:
droptabletablename;
6.向表中插入数据
创建好表以后,要想对表进行操作,必须先保存一些数据,方法是使用SQL语句insert。通常,insert语句的语法格式如下:
insert[into]tablename[(col1,col2,…)]values(value1,value2,…);
例如,要向表中插入一条记录,可以输入下面的命令:
insertintousertablevalues(
'user004','张三','zhangsan','0','1985-02-04','本科','东北','zhangsan@',
'大连软件园','我喜欢计算机类图书');
如果只针对少部分列插入数据,可以使用下面的语法格式:
insert[into]tablenamesetcol1=expression1,…
也可以一次将多行数据插入表中。每行数据用括号括起来,每组括号之间用逗号分隔。
7.从表中获取数据
从表中获取数据使用的是select语句。它的语法格式如下:
select[options]items
[intofile_name]
fromtables
[wherecondition]
[groupbygroup_type][HAVINGconditon]
[orderbyorder_type]
[limitlimit_criteria]
例如,要查看所有用户信息,可以使用下面的语句:
select*fromusertable;
8.删除表中数据
要想删除表中的数据,可以使用delete语句。语法格式为:
deletefromtablename
[wherecondition]
[orderbyorder_cols]
[limitnumber]
例如,要删除用户ID为“user002”的用户信息,可以使用下面的代码:
deletefromusertablewhereuserid='user002'
9.更新表中的数据
要想修改表中的数据,可以使用update语句。语法格式为:
updatetablename
setcol1=expression1,…
[wherecondition]
[orderbyorder_criteria]
[limitnumber]
例如,要将用户ID为“user002”的用户的用户名修改为“Jack”,可以使用下面的语句:
updateusertablesetusername='Jack'whereuserid='user002' 7.3编写UserBean
7.3.1JDBC的基本用法
JDBC是Java应用与数据库管理系统进行交互的标准API,包括多个接口:Driver、DriverManager、Connection、Statement、PrepareStatement和ResultSet等。Driver表示驱动程序,DriverManager用于管理驱动程序,Connection表示与数据库之间的一个连接,要执行SQL语句需要使用Statement和PrepareStatement,如果要查询数据库会得到结果集ResultSet。这些接口是JDBC的基本接口,编写数据库应用的时候,主要就是对这些接口的使用。编写Java数据库应用的基本过程如下:
●建立数据源(库);
●导入用到的包;
●加载驱动程序;
●创建与数据库的连接;
●创建语句对象;
●编写SQL语句;
●执行SQL语句;
●处理结果集;
●关闭相关对象;
●处理异常。
(1)建立数据源(库)。要使用的数据库就是在“使用MySQL”一节创建的数据库,所以这个步骤就省略了。
(2)导入java.sql包。在连接数据库的过程中需要用到以下接口和类:
Driver:驱动程序(不同的数据库使用不同的驱动程序),用于连接应用程序(包括Application,JSP,Servlet,JavaBean)和数据库。
DviverManager:驱动程序管理器,用于对程序中用到的驱动程序进行管理,包括加载驱动程序、创建对象、调用方法等。
Connection:连接,不管对数据库进行什么样的操作,都需要先创建一个连接,然后通过这个连接来完成操作。
Statement:语句对象,用于执行SQL语句。连接数据库对数据库进行访问,主要就是执行一些SQL语句,语句对象就是用于执行SQL语句的。
ResultSet:结果集对象,用于表示查询后得到的结果。如果要查询数据库中的一些信息,例如所有用户信息,查询完之后查询结果就保存在结果集对象中。
这些接口和类在java.sql包中,要访问这些接口和类,需要导入这个包。在Java中引入这个包的语句为:
importjava.sql.*;
(3)加载驱动程序。驱动程序的作用就是把用户对数据库的访问请求转换成数据库可以理解的方式,然后把数据库的执行结果返回给用户。例如要向数据库中添加一个新的用户,需要编写相应的SQL语句,然后执行SQL语句。怎么执行SQL语句呢?驱动程序把这个请求提交给数据库,然后由数据库执行。因为每个数据库的执行过程不同,所以每个数据库都应该有自己的驱动程序。根据要访问的数据库,首先要加载相应的驱动程序。
如果驱动程序的名字是MyDriver,则加载驱动程序的语句是:
Class.forName("MyDriver");本书中使用的是MySQL数据库,连接MySQL数据库的驱动程序是com.mysql.
jdbc.Driver。
加载该驱动程序的语句是:
Class.forName("com.mysql.jdbc.Driver");
(4)创建与数据库的连接。不管对数据库进行什么样的操作,都需要先创建连接,然后操作。
要连接数据库,首先需要知道数据库的相关信息。通常连接数据库需要的信息包括以下几个方面:
①
数据库的位置:包括数据库所在的主机和所使用的端口。每个应用程序都会有自己的端口,例如Oracle使用的端口默认情况下是1521,MicroSoftSQLServer使用的端口默认情况下是1433,我们要使用的MySQL的端口默认情况下是3306。
②
数据库的信息:包括数据库的名字。因为在同一个数据库管理系统中可能会有多个数据库,所以需要指出要访问哪个数据库。这里,我们要访问的数据库是bookstore。
③
用户信息:包括用户名和口令。因为数据库中的信息通常都非常重要,所以一般需要提供身份验证。
有了数据库的相关信息,接下来就可以创建与数据库的连接了。连接数据库的格式如下:
Connectioncon=DriverManager.getConnection(constr,user,pass);
其中,constr是连接字符串,user是用户名,pass是口令。
若使用MySQL数据库,连接字符串的格式为jdbc:mysql://localhost:3306/bookstore,其中bookstore是数据库的名字,假设用户名和口令都是root,则连接该数据库的代码如下:
Connectioncon=
DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore","root","root");
(5)创建语句对象。创建语句对象是用来执行SQL语句的。不管对数据库进行什么样的操作,都是执行SQL语句,不同的是,不同的功能需要执行不同的SQL语句。
语句对象是Statement的对象,语句对象的创建是通过连接对象创建的,所以在创建语句对象之前应该确保连接对象已经创建。
创建语句对象的代码如下:
Statementstmt=con.createStatement();不管连接什么数据库,不管执行什么样的操作,这句代码都不用修改。
(6)编写SQL语句。根据要完成的功能,编写相应的SQL语句。最常用的SQL语句有如下几个:
①
添加:insert语句。
②
删除:delete语句。
③
查询:selete语句。
④
修改:update语句。
在程序中SQL语句表现为字符串,例如要查询所有的用户信息,代码如下:
Stringsql="select*fromusertable";
(7)执行SQL语句。使用语句对象来执行SQL语句,语句对象提供了多个用于执行SQL语句的方法,常用的有两个:
executeQuery(Stringsql):主要用于执行有结果集返回的SQL语句,典型的就是select查询语句。要从数据库得到一些数据,会有一些数据返回,这时候就应该使用该方法。
executeUpdate(Stringsql):主要用于执行没有结果集返回的SQL语句。比如要向数据库中添加信息、修改数据库中的信息或者删除数据库中的信息,它们都没有结果集返回,就应该使用该方法。该方法的返回值是整数,表示影响数据库中记录的个数。
假设要执行上面的查询语句,可以使用下面的代码:
ResultSetrs=stmt.execute(sql);
因为有结果集返回,所以创建ResultSet的对象来接收这个结果集。stmt是前面创建的语句对象,sql是前面编写的SQL语句。
(8)处理结果集。如果进行删除、插入或者更新操作,执行完就可以了。如果要查询数据,需要处理查询结果。查询的结果在结果集中保存,结果集的数据就像数据库中的表格一样,由若干行、若干列组成,每一行表示一个记录。而Java是面向对象的语言,操作的是一个个的对象,所以需要把结果集的数据进行处理,转化成对象。
结果集就像一个表格,由若干行和若干列组成,查询的结果中有多少条记录,结果集中就有多少行,查询的结果中有多少字段,结果集中就有多少列。
处理结果集的过程,就是对结果集的遍历过程。遍历每一行,然后取出当前行的每一列,再根据这一行的各列的信息构造对象。
对行的遍历,使用结果集的next()方法。
要获取某一列,使用get方法。有很多get方法用于获取不同类型的值,例如通过getInt可获取整数字段的值,通过getString可获取字符串字段的值,这些方法的区别在于方法的返回值不同。为了便于大家记忆,只需要记住getString方法就可以了。如果需要其他类型的值,则进行转换就可以了。
getString方法需要一个参数,参数表示要获取哪一列的值。参数可以使用序号,例如获取第1列,可以使用getString(1)。参数也可以使用列的名字,例如获取用户名,可以使用getString("username")。
例如要以字符串的形式获取第1列可以使用下面的代码:
Stringuserid=rs.getString(1);
(9)关闭相关对象。在上面的介绍中,我们创建了多个对象,其中连接对象、语句对象、结果集对象需要关闭,如果不关闭,这些连接会占用资源。对于网络应用来说,用户量非常大,如果每个用户都浪费资源的话,系统资源的浪费就会很大。所以需要关闭这些对象。
关闭连接的代码是:
con.close();
关闭语句的代码是:
stmt.close();
关闭结果集的代码是:
rs.close();
(10)处理异常。在对数据库进行操作的过程中可能会发生各种各样的异常,例如数据库服务器没有启动、网络没有连接、SQL语句写错等。如果不对这些异常进行处理,程序在运行过程中就会出错,对用户来说是不友好的,所以应该对异常进行处理。
使用下面的框架对异常进行处理:
try{
//要执行的可能出错的代码
}catch(Exceptione){
//出错后的处理代码
}finally{
//不管是否出错都要执行的代码
}7.3.2编写表示用户信息的JavaBean
在数据库中,实体是以记录的形式存在的,而在程序中,实体是以对象的形式存在的。对应数据库中的表,应该提供一个类。用于保存用户信息的表是usertable
packagebookstore.bean;
importjava.util.*;
importjava.sql.*;
publicclassUserBean{
privateStringuserid;
privateStringusername;
privateStringuserpass;
privateStringtype="0";
privatejava.util.Datebirthday;
privateStringdegree;
privateStringlocal;
privateStringemail;
privateStringaddress;
privateStringcomment;
publicStringgetUserid(){
returnuserid;
}
publicvoidsetUserid(Stringuserid){
this.userid=userid;
}
publicStringgetUsername(){
returnusername;
}
publicvoidsetUsername(Stringusername){
this.username=username;
}
publicStringgetUserpass(){
returnuserpass;
}
publicvoidsetUserpass(Stringuserpass){
this.userpass=userpass;
}
publicStringgetType(){
returntype;
}
publicvoidsetType(Stringtype){
this.type=type;
}
publicjava.util.DategetBirthday(){
returnbirthday;
}
publicvoidsetBirthday(java.util.Datebirthday){
this.birthday=birthday;
}
publicStringgetDegree(){
returndegree;
}
publicvoidsetDegree(Stringdegree){
this.degree=degree;
}
publicStringgetLocal(){
returnlocal;
}
publicvoidsetLocal(Stringlocal){
this.local=local;
}
publicStringgetEmail(){
returnemail;
}
publicvoidsetEmail(Stringemail){
this.email=email;
}
publicStringgetAddress(){
returnaddress;
}
publicvoidsetAddress(Stringaddress){
this.address=address;
}
publicStringgetCommentt(){
returncomment;
}
publicvoidsetComment(Stringcontent){
ment=comment;
}
}7.3.3编写查询所有用户的方法
接下来编写查询所有用户信息的方法,方法的返回值是所有用户对象的集合,不需要查询条件,方法的定义如下:
publicArrayListfindAllUser()
根据前面介绍的访问数据库的基本过程,需要在类的前面添加导入java.sql包的代码。另外,要使用ArrayList,需要在类的定义前面添加导入java.util.ArrayList的代码。类代码之前添加的代码如下:
importjava.sql.*;
importjava.util.*;
方法的定义如下:
publicArrayListfindAllUser()
{
ArrayListuserlist=newArrayList();
//连接对象
Connectioncon=null;
//语句对象
Statementstmt=null;
//结果集对象
ResultSetrs=null;
//查询语句
Stringsql="select*fromusertable";
//连接数据库的URLStringurl="jdbc:mysql://:3306/bookstore";
//用户名
Stringdbuser="root";
//口令
Stringdbpass="root";
try
{
//加载驱动程序,参数是驱动程序的名字
Class.forName("com.mysql.jdbc.Driver");
//建立连接,第一个参数是url,
//第二个是用户名,第三个是口令
con=DriverManager.getConnection(url,dbuser,dbpass);
//创建语句对象
stmt=con.createStatement();
//执行select语句,返回结果集对象
rs=stmt.executeQuery(sql);
//对结果集进行遍历
while(rs.next())
{
//获取结果集中的信息
StringtmpUserid=rs.getString(1);
StringtmpUsername=rs.getString(2);
//进行编码转换
tmpUsername=newString(tmpUsername.getBytes("8859_1"));
StringtmpUserpass=rs.getString(3);
StringtmpType=rs.getString(4);
java.util.DatetmpBirthday=rs.getDate(5);
StringtmpDegree=rs.getString(6);
tmpDegree=newString(tmpDegree.getBytes("8859_1"));
StringtmpLocal=rs.getString(7);
tmpLocal=newString(tmpLocal.getBytes("8859_1"));
StringtmpEmail=rs.getString(8);
StringtmpAddress=rs.getString(9);
tmpAddress=newString(tmpAddress.getBytes("8859_1"));
StringtmpComment=rs.getString(10);
//创建用户对象
UserBeanuser=newUserBean();
//根据获取的用户信息初始化用户对象
user.setUserid(tmpUserid);
user.setUsername(tmpUsername);
user.setUserpass(tmpUserpass);
user.setType(tmpType);
user.setBirthday(tmpBirthday);
user.setDegree(tmpDegree);
user.setLocal(tmpLocal);
user.setEmail(tmpEmail);
user.setAddress(tmpAddress);
user.setComment(tmpComment);
//把对象添加到集合中
userlist.add(user);
}
}catch(Exceptione)
{
}
finally
{
//关闭对象的顺序:rsstmtcon
//与创建对象的顺序相反
try{rs.close();}catch(Exceptione){}
try{stmt.close();}catch(Exceptione){}
try{con.close();}catch(Exceptione){}
}
//返回查询到的所有对象
returnuserlist;
}7.3.4采用数据库连接池
1.配置JNDI数据源
DBCP可以使用很多技术实现,本书介绍的是比较流行的Jakarta-Commons的DBCP。
使用连接池的时候存在一个问题。Web应用必须显式地关闭结果集对象、语句对象、连接对象,如果关闭失败,将导致这些对象不能重用。可能还会导致在连接使用完的时候,Web应用无法连接到数据库。
Jakarta-Commons的DBCP提供了一种机制,能够跟踪和恢复那些不能被管理的连接。此时需要在配置数据源的时候增加下面的代码:
removeAbandoned=“true”
当可用的连接数比较少时,连接池会查找并重复使用这些不能被管理的连接。可以使用removeAbandonedTimeout属性设置一个连接空闲多少秒之后就认为是已经被放弃的连接,默认值是300s。如果想改为60s,可以使用下面的代码:
removeAbandonedTimeout=“60”
可以设置logAbandoned属性来记录没有正确释放连接的代码:
logAbandoned="true"
2.配置server.xml
server.xml文件在Tomcat安装目录的conf子目录下。在</host>之前应增加下面的代码:
<Contextpath="/bookstore"docBase="bookstore"
debug="5"reloadable="true"crossContext="true">
<Resourcename="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root“
password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://:3306/bookstore?autoReconnect=true"/>
</Context>各属性的含义如下:
(1)
maxActive:池中连接的最大数目。要确保让MySQL的最大连接数大于这个值。如果其值为0,则没有最大数量限制。
(2)
maxIdle:池中最大空闲数据库连接数。如果其值为-1,则没有限制。
(3) maxWait:等待一个连接变成可用的最长时间,单位是ms。这个例子中该值为10s,如果超时将抛出异常。如果设置为-1,将无限等待。
(4)
username和
password:连接MySQL数据库的用户名和口令。
(5)
driverClassName:MySQL数据库的JDBC驱动程序的名字,这里的名字是com.mysql.jdbc.Driver。
(6)
url:JDBC连接MySQL数据库的url。参数autoReconnect=true确保连接池能够重新连接。如果8个小时没有操作,MySQL管理器会关闭连接。
3.配置web.xml
需要为当前应用配置web.xml。其主要作用是声明数据源。代码如下:
<resource-ref>
<description>DBConnection</description>
<res-ref-name>jdbc/TestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
4.使用连接池访问数据库
使用连接池访问数据库与使用JDBC直接访问数据库的过程基本相同,只是得到连接的方式不同。
下面的代码展示了在使用连接池的时候,如何获取到数据库的连接:
ContextinitContext=newInitialContext();
ContextenvContext=(Context)initContext.lookup("java:/comp/env");
DataSourceds=(DataSource)envContext.lookup("jdbc/TestDB");
Connectionconn=ds.getConnection();
修改后的findAllUser方法的代码如下:
publicArrayListfindAllUser()
{
ArrayListuserlist=newArrayList();
//连接对象
Connectioncon=null;
//语句对象
Statementstmt=null;
//结果集对象
ResultSetrs=null;
//查询语句
Stringsql="select*fromusertable";
try
{
//创建上下文环境
ContextinitContext=newInitialContext();
//查找数据源
ContextenvContext=(Context)initContext.lookup("java:/comp/env");
DataSourceds=(DataSource)envContext.lookup("jdbc/TestDB");
//从连接池中获取连接
con=ds.getConnection();
//创建语句对象
stmt=con.createStatement();
//执行select语句,返回结果集对象
rs=stmt.executeQuery(sql);
//对结果集进行遍历
while(rs.next())
{
//获取结果集中的信息
StringtmpUserid=rs.getString(1);
StringtmpUsername=rs.getString(2);
//进行编码转换
tmpUsername=newString(tmpUsername.getBytes("8859_1"));
StringtmpUserpass=rs.getString(3);
StringtmpType=rs.getString(4);
java.util.DatetmpBirthday=rs.getDate(5);
StringtmpDegree=rs.getString(6);
tmpDegree=newString(tmpDegree.getBytes("8859_1"));StringtmpLocal=rs.getString(7);
tmpLocal=newString(tmpLocal.getBytes("8859_1"));
StringtmpEmail=rs.getString(8);
StringtmpAddress=rs.getString(9);
//进行编码转换
tmpAddress=newString(tmpAddress.getBytes("8859_1"));
StringtmpComment=rs.getString(10);
//创建用户对象
UserBeanuser=newUserBean();
//根据获取的用户信息初始化用户对象
user.setUserid(tmpUserid);
user.setUsername(tmpUsername);
user.setUserpass(tmpUserpass);
user.setType(tmpType);
user.setBirthday(tmpBirthday);
user.setDegree(tmpDegree);
user.setLocal(tmpLocal);
user.setEmail(tmpEmail);
user.setAddress(tmpAddress);
user.setComment(tmpComment);
//把对象添加到集合中
userlist.add(user);
}
}catch(Exceptione)
{
System.out.println(e.toString());
}
finally
{
//关闭对象的顺序:rsstmtcon
//与创建对象的顺序相反
try{rs.close();}catch(Exceptione){}
try{stmt.close();}catch(Exceptione){}
try{con.close();}catch(Exceptione){}
}
//返回查询到的所有对象
returnuserlist;
}
需要在这个文件中导入多个包,语句如下:
importjava.sql.*;
importjavax.sql.*;
importjavax.naming.*;
7.4编写userlist.jsp
7.4.1实现代码
实现代码如下:
<%@pagecontentType="text/html;charset=gb2312"%>
<%@taglibprefix="c"uri="/jsp/jstl/core"prefix="c"%>
<h2align=center>所有用户信息<h2>
<tablealign=center>
<tr>
<th>用户编号</th>
<th>用户名</th>
<th>用户类型</th>
<th>生日</th>
<th>学历</th>
<th>地区</th>
<th>Email</th>
<th>地址</th>
</tr>
<c:forEachitems="${userlist}"var="user">
<tr>
<td>${user.userid}</td>
<td>${user.username}</td>
<td>
<c:iftest="${user.type==0}">普通用户</c:if>
<c:iftest="${user.type==1}">管理员</c:if>
</td>
<td>${user.birthday}</td>
<td>${user.degree}</td>
<td>${user.local}</td>
<td>${user.email}</td>
<td>${user.address}</td>
</tr>
</c:forEach>
</table>
<c:forEach>标签中的items属性表示要遍历的集合,可以使用表达式语言。var属性定义一个变量,该变量表示集合中的一个元素,在循环中对该变量进行处理,相当于循环变量。它的功能与下面代码中的i类似:
int[]a=newint[10];
for(inti=0;i<10;i++)
{
a[i]=i*i;
}7.4.2<c:forEach>标签
<c:forEach>标签的语法结构如下:
<c:forEach
var="变量名"
[items="集合"]
[begin="起始位置"]
[end="结束位置"]
[step="步长"]
[varStatus="状态信息"]
>
循环体
</c:forEach>这个标签包括开始标志、结束标志和循环体。
var属性表示要循环的集合中的一个元素,例如要遍历1~10,var的值是i,第1次遍历的时候i表示1,第2次遍历的时候i表示2,依次类推。
items表示要循环遍历的集合,通常是集合对象。
begin表示从集合的第几个元素开始循环,集合的第一个元素的序号是0。
end表示循环到集合中的第几个元素。
step表示循环的步长,如果是1,就遍历所有元素,如果是2,就间隔一个遍历一个。
varStatus表示的变量保存了循环的状态信息,如index、count、first和last等,分别表示当前元素的索引、集合中元素的个数、是否是第一个元素和是否是最后一个元素。
该标签可以对集合进行遍历,也可以使用规律的数字控制循环。
例如,要用循环把1、3、5、7、9分别输出到5行上,可以使用下面的代码:
<c:forEach
var="i"
begin="1"
end="9"
step="2"
>
${i}<br>
</c:forEach>其中,var指出的i表示循环变量,从1开始,到9结束,循环的步长是2。使用表达式语言输出当前元素,i表示当前元素。
如果循环遍历的是集合对象,则需要使用items属性指出循环的集合对象。集合对象可以是数组、java.util.Collection、java.util.Map、java.util.Iterator、java.util.Enumeration对象,也可以是使用逗号分隔的特殊字符串。
在前面设计功能的时候,把所有用户信息存储在request中,名字是userlist,用户信息本身是ArrayList对象,是一个集合,可以使用<c:forEach>标签进行遍历:
<c:forEachitems="${userlist}"var="user">
循环体
</c:forEach>
在这个循环中,items指出的是循环的集合userlist,var表示循环时候集合中的一个元素,此处表示某个具体的用户。循环体可以对这个元素进行操作,例如输出这个元素的各种属性。
7.4.3使用标准标签库中的SQL标签
1.设置数据源
在使用JDBC连接数据库的时候,需要先得到数据库的JDBC驱动程序以及数据库的相关信息。在使用SQL标记库的时候同样需要这些信息,这些信息通过标记库中的<sql:setDataSoruce>标记完成。该标记可以完成数据源的设定,设定之后其他的标记就可以使用这个数据源了。
<sql:setDataSource>标记的语法格式有两种:
格式一:
<sql:setDataSourceurl="数据源描述信息"
driver="驱动程序名字"
user="用户名"
password="口令"
var="创建的数据源的名字"
scope="{page|request|session|application}"
/>
格式二:
<sql:setDataSourcedataSource="数据源的名字"
var="创建的数据源的名字"
scope="{page|request|session|application}"
/>如果在服务器上配置了数据源(连接池),在server.xml中进行配置时可以使用格式二。如果没有配置数据源,可以使用格式一。
其中,dataSource属性指出已经配置的数据源的名字,url属性指出数据库的位置信息,driver属性指出JDBC驱动程序的名字,user指出连接数据库使用的用户名,password指出该用户名对应的口令,scope属性指出设定的数据源的作用范围。这些信息的含义与我们在使用JDBC连接数据库时所使用的信息的含义是相同的。这些信息保存在var所指定的变量中。
要连接前面创建的数据库,可以使用下面的代码:
<sql:setDataSourceurl="jdbc:mysql://localhost:3306/bookstore"
driver="com.mysql.jdbc.Driver"
user="root"
password="root"
var="ds"
/>
2.执行查询
要执行查询语句可以使用<sql:query>标签,该标签的语法格式如下:
<sql:querysql="要执行的SQL语句"
var="查询的结果集"
[scope="page|request|session|application"]
[dataSource="所使用的数据源"]
[maxRows="最大记录数"]
[startRow="开始记录"]
/>
其中,sql属性指出要执行的SQL语句,dataSource属性指出要使用的数据源,这个数据源是前面通过<sql:setDataSource>标记创建的,var指定的变量用于保存查询的结果,scope属性指出查询的结果保存在什么地方,maxRows属性和startRow属性限定查询结果,即查询多少条记录,从哪条记录开始。
要查询所有用户信息,可以使用下面的代码:
<sql:querysql="selectuserid,username,type,birthday,degree,localfromusertable"
var="userlist"
dataSource="${ds}"
/>
使用连接池技术,代码如下:
<sql:queryvar="userlist"dataSource="jdbc/TestDB">
select*fromusertable
</sql:query>
3.显示查询结果
经<sql:query>标签查询之后,查询的结果存储在var指定的变量中,这个结果对象是javax.servlet.jsp.jstl.sql.Result的对象。Result类提供了多个访问结果集中数据的方法:
(1)
getRows:得到一个SortedMap对象数组,每个元素是一个SortedMap对象,表示一个记录,键是列名,值是该列对应的值,访问的时候按照列名访问。
(2) getRowsByIndex:得到一个对象数组,每个数组元素又是一个对象数组,表示一个记录,数组中的每个元素是记录的对应列的值,访问的时候按照索引访问。
(3) getColumnNames:得到列名数组。
(4) getRowCount:得到记录数。
(5) isLimitedByMaxRows:判断结果集是否受最大行数的限制。
要访问上面得到的结果集,可以使用下面的代码:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 IEC 60068-2:2025 SER EN-FR Environmental testing - Part 2: Tests - ALL PARTS
- 物理-辽宁省大连市2024-2025学年高三上学期期末双基测试卷及答案
- 2024陶瓷行业知识产权保护合作协议3篇
- 2025宾馆特色餐饮开发与推广合作协议3篇
- 2024食品工厂代加工绿色包装合作合同范本2篇
- 2024版协议离婚制度论文深度解读与案例分析3篇
- 2024年航空公司飞机采购协议
- 2025年度安全文化建设与推广承包合同范本3篇
- 中国各省地图形状
- 2024智能交通信号控制系统研发合同
- 常用静脉药物溶媒的选择
- 当代西方文学理论知到智慧树章节测试课后答案2024年秋武汉科技大学
- 2024年中国心力衰竭诊断和治疗指南2024版
- HCCDP 云迁移认证理论题库
- 台大公开课--《红楼梦》笔记剖析
- 工伤保险待遇及案例分析PPT课件
- 底总结报告2017年初开场计划策划模版图文可随意编辑修改课件
- 询问调查笔录内容来自dedecms - 税务局(稽查局)
- 石油化工中心化验室设计规范
- 自己总结的清华斯维尔节能问题解答(共21页)
- 烹饪专业课程及课表设置
评论
0/150
提交评论