第6章 系统详细设计
6.1 数据库连接
实现业务逻辑层与数据库的连接是通过jdbc技术,它是“java database connectivity”的缩写。jdbc由一组用java语言编写的接口和类组成,是对数据库操作的对象封装,可以实现与数据库的无关性。它以成为一种供数据库开发者使用的标准api。
6.1.1 jdbc的基本功能
a.建立与数据库的连接。
b.发送sql语言。
c.处理数据库操作结果。
6.1.2 jdbc的特点
a.与sql语言的一致性。它允许使用从属于任何dbms的sql语言;提供odbc风格的转义语句;利用databasemetadata接口提供关于dbms的描述性信息,从而使应用程序能适应每个dbms。
b.可在现有数据库上实现。
c.提供与其它java系统一致的界面。这说明开发人员可以采用一致的编程界面来处理数据库编程。
d.简单化。
e.使用静态的通用数据类型。
f.多方法,多功能。
6.1.3 jdbc的驱动类型:
a.jdbc-odbc桥驱动程序。
b.调用本地数据库应用编程接口驱动程序。
c.数据库中间件纯java驱动程序。
d.直接连接数据库的纯java驱动程序。
6.1.4将连接数据库的代码封装在一个javabean中
dbconn.java代码如下:
package com.soul.struts.tool;
import java.sql.connection;
import java.sql.drivermanager;
import java.sql.preparedstatement;
import java.sql.resultset;
import java.sql.sqlexception;
public class dbconn {
private string driver = "sun.jdbc.odbc.jdbcodbcdriver"; //数据库的驱动
private string url = "jdbc:odbc:mydb"; //url地址
private connection conn = null ;
//无参构造器,利用它来加载数据库连接对象
public dbconn() {
try {
class.forname(driver); //加载数据库驱动
conn = drivermanager.getconnection(url); //加载数据库连接对象
}
catch (exception e) {
system.out.println("数据库加载失败");
}
}
public connection getconn() {
return conn;
}
// 关闭数据库结果集
public static void closers(resultset rs) {
try {
if(rs != null) {
system.out.println("关闭数库结果集");
rs.close();
rs = null;
}
} catch (sqlexception e) {
e.printstacktrace();
}
}
//关闭数据库操作对象
public static void closepstmt(preparedstatement pstmt) {
try {
if(pstmt != null) {
system.out.println("关闭数库操作对象");
pstmt.close();
pstmt = null;
}
} catch (sqlexception e) {
e.printstacktrace();
}
}
//关闭数库连接对象
public static void closeconn(connection conn) {
try {
if(conn != null) {
system.out.println("关闭数库连接对象");
conn.close();
conn = null;
}
} catch (sqlexception e) {
e.printstacktrace();
}
}
}
6.2 系统功能模块的设计与实现
6.2.1 用户注册模块
当用户提出注册请求,系统显示用户注册页面,提示用户输入个人信息,用户输入个人信息,系统验证其信息是否符合要求,如果用户输入的个人信息不符合系统要求,则系统显示错误信息并要求用户重新填写个人信息,用户重新填写信息,或者取消注册,注册成功系统将用户信息写入数据库,页面将经一个显示注册成功的页自动进入登录界面。如下图6-1所示:
图6-1 用户注册页面
要实现用户信息验证功能,主要是通过客户端页面上的javascript和服务器端验证,例如验证用户输入的用户名在数据库中是否已存在,如果已存在则在提交的时候会给出提示“用户名已存在”,就要求重新注册。客户端页面上的javascript代码如下:
<script language="javascript">
function checkempty(form){
for(i=0;i<form.length;i++){
if(form.elements[i].value==""){
alert("表单信息不能为空!!!");form.elements[i].focus();
return false;
}
}
if(form.user_password.value!=form.user_password1.value){
alert("两次输入的密码不一致,请重新输入!!!"); form.user_password.focus();return false;
}
if (form.user_name.value.length <1) {
alert("用户名要在1-20个字符之间!");
form.user_name.focus();
return false;
}
var pattern = /^[a-za-z0-9_-]+@[a-za-z0-9_-]+(\.[a-za-z0-9_-]+)+$/;
if(!pattern.exec(form.email.value)){
alert("邮箱格式错误!!");
return false;
}
}
</script>
在服务器端验证时,registeraction 调用 registermanager类中的adduser方法.adduser会先调同类中的hasuser方法来验证用户是否已存在。关键代码如下:
public boolean hasuser(string user_name) throws exception{
connection conn = null;
dbconn db = new dbconn();
preparedstatement pstmt= null;
resultset rs = null;
try{
conn = db.getconn();
pstmt = conn.preparestatement(sql.registcheck_tb_user);
pstmt.setstring(1,user_name);
rs=pstmt.executequery();
rs.next();
int n = rs.getint(1);
if(n==1){
system.out.print("用户名存在,返回true");
return true;
} else {
system.out.print("用户名不存在,返回false");
return false ;
}
}catch(sqlexception e){
e.printstacktrace();
throw e;
}finally{
dbconn.closers(rs);
dbconn.closepstmt(pstmt);
dbconn.closeconn(conn);
}
}
6.2.2 登录模块
在登录模块中分为教师登录和学生登录,只有输入正确的用户名和密码才能进入系统。在登录发生错误时会出现相关的提示信息,如用户名或密码错误。当教师登录成功后进入主页可以进行 电子 教案管理,视频管理,作业管理,在线答疑,留言管理等相关的操作。学生登录成功后进入主页可以查看,下载电子教案和视频,在线向教师提问,上传作业等相关操作。
用户登录模块是系统的入口,用户登录模块应具有以下功能:
获得用户权限。登录模块做为系统的入口,需要对权限进行控制。不同身份登录获的不同的使用权。本系统分为教师用户和学生用户两种权限。教师用户登录后可以进行电子教案管理,视频管理,作业管理,在线答疑,留言管理等相关的操作;学生用户登录成功后可以查看,下载电子教案和视频,在线向教师提问,上传作业等相关操作。网站首页默认为学生用户登录页面。教师用户登录可以点页面中的“教师登录”进入教师登录页面。
验证用户的用户名和密码。系统在登录过程中必须输入其正确的用户名和密码,登录模块会对其进行核对。如果用户的用户名或密码错误则提示信息“用户名或密码错误”并返回用户登录界面。
为实现学生登录功能,要根据用户输入的用户名和密码判断是否是合法用户。于是创建一个loginaction类。调用usermanager类中的validate(string name,string password)方法:
public boolean validate(string name,string password) throws exception {
connection conn = null;
dbconn db = new dbconn();
preparedstatement pstmt = null;
resultset rs = null;
try {
conn = db.getconn();
pstmt = conn.preparestatement(sql.login_tb_user);
pstmt.setstring(1,name);
pstmt.setstring(2,password);
rs = pstmt.executequery();
rs.next();
int n = rs.getint(1);
if(n==1)
{
return true;
} else {
return false;
}
}catch(sqlexception e){
e.printstacktrace();
throw e;
}finally{
db.closers(rs);
db.closepstmt(pstmt);
db.closeconn(conn);
}
}
本系统的教师登录模块采用了固定的用户名和密码。为实现它,我创建了一个adminloginaction类,调用adminmanager类中的方法:
public boolean validate(string name, string password)
{
if (("admin".equals(name))&&("admin".equals(password)))
{
system.out.print("正确!");
return true;
}else
{
system.out.print("错了");
return false;
}
}
如果教师输入的用户名或密码有误则会有提示:"用户名或密码不匹配,请重新登录!"接着页面会跳到教师登录页面。
鉴于对系统安全的考虑,用户使用系统必须先到登录页面进行身份验证,通过登录窗口用户输入用户名和密码,只有输入正确的用户名和密码后用户才能进入系统。
下图页面是学生登录的首页如图6-2:
图6-2用户登录页面
教师登录页面如图6-3所示:
图6-3教师登录页面
6.2.3 电子教案管理模块
a.电子教案管理模块分为学生用户主页的电子教案管理和教师用户主页的电子教案管理。教师成功登录后,在教师用户主页中的电子教案管理模块,教师可以上传新电子教案,也可以删除以前传过的旧电子教案。点击“上传电子教案”就会进入到电子教案上传的页面,教师点击“浏览”选择要上传的电子教案,然后点上传就完成了一个电子教案的上传。创建了一个继承于dispatchaction的uploadaction类,该类用于上传和下载文件。关键代码如下:
uploadform uploadfile = (uploadform)form;
formfile file = uploadfile.getfile();
string uuidname = uuid.randomuuid().tostring();
string kejian_name = uuidname+file.getfilename();
string kejian_time =uploadfile.getkejian_time();
servletcontext servletcontext = this.getservlet().getservletcontext();
string path = servletcontext.getrealpath("");
fileoutputstream out = new fileoutputstream(path+"/uploadc/"+ kejian_name);
out.write(file.getfiledata());
out.flush();
out.close();
uploadmanager ulm = new uploadmanager();
boolean flag = ulm.kejianadd(video_name, video_time);
if(flag)
{
request.setattribute("currenttime", new date());
request.setattribute("upload", "success");
retur, , n mapping.findforward("upload");
}
request.setattribute("upload", "fail");
return mapping.findforward("auploadc");
path表示得到当前项目下webroot 的路径,为了保存视频,在webroot下建立了一个名为uploadv的文件夹,考虑到一处编写到处运行的java语言初衷,把视频保存在tomcat服务器下.代码中的formfile类,是映射上传文件的,对你上传的文件进行操作,可以取得文件的名字,文件的内容等。由于怕上传的电子教案的名的字会相同,于是用个uuid类。用uuid.randomuuid()给文件名加一个随机的32位的不会重复的数字。上传成功的电子教案会存在服务器的uploadc文件夹中。
教师上传电子教案页面如图6-4所示:
图6-4教师上传电子教案图
c. 学生用户成功登录后,可点击“下载电子教案”查看电子教案,选择想要下载的电子教案点击“下载”。
学生下载电子教案页面如图6-5所示:
图6-5学生下载电子教案页面
6.2.4 公告管理模块
站内公告管理小模块主要功能是管理站内公告,教师可通过公告管理模块向学生们发布通知,也可以删除通知。 这是一个小模块,因此创建back_noteaction类调用notemanager类中的add()方法向数据库中添加公告内容:
public boolean add(string note_title,string note_content,string note_time) throws exception{
connection conn = null;
dbconn db = new dbconn();
preparedstatement pstmt= null;
try{
conn = db.getconn();
pstmt = conn.preparestatement(sql.add_tb_note);
pstmt.setstring(1,note_title);
pstmt.setstring(2,note_content);
pstmt.setstring(3,note_time);
int n=pstmt.executeupdate();
if(n==1){
return true;
} else {
return false;
}
}catch(sqlexception e){
e.printstacktrace();
throw e;
}finally{
dbconn.closepstmt(pstmt);
dbconn.closeconn(conn);
}
}
学生的主页是由主页中include进去几个页组成的。所以要在用户的页面中显示公告,创建了一个head_mainaction类,在该类中的show方法中使用 request.getsession().setattribute("list_note", list_note);将list_note放在session中的。于是只要浏览器不关,在任何一个显示页面都能取到用el表达${lsit_note}取得。
添加公告页面如图6-6所示:
图6-6添加公告页面
6.2.5 留言管理模块
在教师的留言管理模块中,教师可以回复留言和删除留言。学生只可以查看留言和留言。教师用户创建了一个back_messageaction类,调用messagemanager中的诸方法来添加或删除留言。学生用户创建了一个head_messageaction类,调用messagemanager中某些方法。在学生显示留言页面要分我利用了jstl加el表达式分页,关键代码如下:
messageactionform maf = (messageactionform)form;
messagemanager mm = new messagemanager();
arraylist list = mm.query();
int pagesize = list.size() / 4 + 1;
arraylist list1 = new arraylist();
int begin = 0;
int end = 3;
int currentpage = 1;
//---从页面得到数据---
if(maf.getcurrentpage()!=1&&maf.getcurrentpage()!=0)
{
begin = maf.getbegin();
end = maf.getend();
currentpage = maf.getcurrentpage();
}
maf.setbegin(begin);
maf.setend(end);
maf.setcurrentpage(currentpage);
list1.add(maf);
request.setattribute("currenttime", new date());
request.setattribute("list", list);
request.setattribute("list1", list1);
request.setattribute("pagesize", integer.valueof(pagesize));
return mapping.findforward("showmessage");
教师查看留言页面如图6-7所示:
图6-7教师查看留言页面
6.2.6 视频管理模块
视频管理模块分为学生用户主页的视频管理和教师用户主页的视频管理。教师成功登录后,在教师用户的主页中的视频管理模块,教师可以上传新的视频,也可以删除以前传过的视频。点击“上传视频”就会进入到 电子 教案上传的页面,教师点击“浏览”选择要上传的视频,然后点上传就完成了一个视频的上传。上传视频的关键代码如下:
uploadform uploadfile = (uploadform)form;
formfile file = uploadfile.getfile();
string uuidname = uuid.randomuuid().tostring();
string video_name = uuidname+file.getfilename();
string video_time = uploadfile.getvideo_time();
system.out.println("时间="+video_time);
servletcontext servletcontext = this.getservlet().getservletcontext();
string path = servletcontext.getrealpath("");
fileoutputstream out = new fileoutputstream(path+"/uploadv/"+video_name);
out.write(file.getfiledata());
out.flush();
out.close();
uploadmanager ulm = new uploadmanager();
boolean flag = ulm.videoadd(video_name, video_time);
if(flag){
request.setattribute("currenttime", new date());
request.setattribute("upload", "success");
return mapping.findforward("upload");
}
request.setattribute("upload", "fail");
return mapping.findforward("auploadv");
path表示得到当前项目下webroot 的路径,为了保存视频,在webroot下建立了一个名为uploadv的文件夹,把视频保存在tomcat服务器下。同时为避免出现相同文件名的视频名字,每个视频上传之前在视频名前加了一段唯一的uuid字符编码,对应数据可存入tb_video表中的video_name字段,将来在显示视频的详细信息时同样根据video_name来寻找视频。
学生下载视频,用video_name查找下载视频。下载视频的代码如下:
uploadform ulf = (uploadform)form;
string video_name = ulf.getvideo_name();
video_name = new string(video_name.getbytes("iso-8859-1"),"gb18030");
servletcontext servletcontext = this.getservlet().getservletcontext();
string path = servletcontext.getrealpath("");
fileinputstream input = new fileinputstream(path+"/uploadv/"+video_name);
response.setcontenttype("application/x-msdownload");
response.setheader("content-disposition", "attachment; filename=" + new string(video_name.getbytes("gb18030"),"iso-8859-1"));
outputstream out = response.getoutputstream();
byte[] b = new byte[1024*1024];
while(input.read(b)>0){
out.write(b);
out.flush();
}
input.close();
out.close();
教师可以根据video_name删除某些视频,调用delvideo()方法将相关信息删除。关键代码如下:
uploadform ulf = (uploadform)form;
string video_name = ulf.getvideo_name();
servletcontext servletcontext = this.getservlet().getservletcontext();
string path = servletcontext.getrealpath("");
file filename = new file(path+"/uploadv/"+video_name);
filename.delete();
uploadmanager um = new uploadmanager();
boolean flag = um.delvideo(video_name);
6.2.7 作业管理模块
本模块在学生用户的主页是学生将自己的作业上传到服务器下的uploadt文件夹中,还可以下载老师批改后上传的作业。在教师用户的主页中老师将学生上传的作业下载下来,之后再将批改好的作业上传到服务器中,供学生下载。上传作业与上传视频类似,只不过多了个string user_name = uploadfile.getuser_name();用来收集上传试卷的用户名。关键代码如下:
uploadform uploadfile = (uploadform)form;
formfile file = uploadfile.getfile();
string test_name = file.getfilename();
string test_time = uploadfile.gettest_time();
string user_name = uploadfile.getuser_name();
system.out.println("时间="+test_time);
servletcontext servletcontext = this.getservlet().getservletcontext();
string path = servletcontext.getrealpath("");
fileoutputstream output = new fileoutputstream(path+"/uploadt/"+file.getfilename());
output.write(file.getfiledata());
output.flush();
output.close();
uploadmanager ulm = new uploadmanager();
boolean flag = ulm.testadd(test_name, test_time,user_name);
学生上传作业页面如图6-8所示:
图6-8学生上传作业页面
6.2.8 在线答疑模块
在这个模块中学生和教师可以在线交流,学生可以向老师在线提出问题,老师将在线回答。
学生或者教师将说的话发送,将先存到数据中,随之再将数据库中的后20条记录取出,在message.jsp中显示。在线答疑页面的主要代码如下:
<frameset rows="*" cols="*,250" framespacing="1" frameborder="yes" border="1" bordercolor="#99ffff" >
<frameset rows="*,117" cols="*" framespacing="0" frameborder="yes" border="0">
<frame src="/pc-theory/090831/message.jsp" name="mainframe" frameborder="1">
<frame src="/pc-theory/090831/control.jsp" name="bottomframe" frameborder="1">
</frameset>
<frameset rows="*,119" cols="*" framespacing="0" frameborder="yes" border="0">
<frame src="/pc-theory/090831/leave.jsp" name="bottomframe1" frameborder="1" scrolling="no" noresize="noresize">
</frameset>
</frameset>
6.2.9 友情链接管理模块
教师还可将自己知道的一些好的网站添加到网站里,把友情链接的网名和网址添加进去,学生会在页面上看见添加进的网站名字,用户可以点网站名进入相应的网站。
为了方便管理和安全,将所有的sql语句都封装在一个sql类中,并且每条语句都定义成public static final类的,这样就不允许有别的语句继承它们。具体的代码如下:
public final class sql {
//用户登录
public static final string login_tb_user = "select count(*) from tb_user where user_name=? and user_password=?";
//用户注册向数库数中增加数据
public static final string registadd_tb_user ="insert into tb_user (user_name,user_password,realname,email)" +"values( ?, ?, ?, ? )";
// public static final string queryid_tb_user ="select user_id from tb_user where user_name=?";
public static final string registcheck_tb_user="select count(*) from tb_user where user_name=?";
public static final string add_tb_articletype="insert into tb_articletype (typename,description) values(?,?)";
public static final string query_tb_articletype="select * from tb_articletype";
public static final string del_tb_articletype="delete from tb_articletype where type_id=?";
public static final string add_tb_article="insert into tb_article (title,type_id,content,phtime,number) values(?,?,?,?,?)";
public static final string del_tb_article="delete from tb_article where article_id=?";
public static final string query_article="select * from tb_article";
public static final string show_article="select tb_article.*,tb_articletype.* from tb_article,tb_articletype where (tb_article.type_id=tb_articletype.type_id and tb_article.type_id=? and article_id=?)";
public static final string xin="select tb_article.*,typename,description from tb_article left join tb_articletype on (tb_article.type_id=tb_articletype.type_id)";
public static final string add_tb_note="insert into tb_note (note_title,note_content,note_time) values(?,?,?)";
public static final string query_tb_note="select * from tb_note";
public static final string del_tb_note="delete from tb_note where note_id=?";
public static final string show_tb_note="select * from tb_note where note_id=?";
public static final string update_tb_note="update tb_note set note_content=? ,note_time=? where note_id=?";
public static final string update_tb_article= "update tb_article set content=? ,phtime=? where article_id=?";
public static final string query_tb_user = "select user_id,user_name,realname,email from tb_user";
public static final string del_tb_user = "delete from tb_user where user_id=?";
public static final string query_tb_message = "select * from tb_message order by mes_id";
public static final string delone_tb_message = "delete from tb_message where mes_id=?";
public static final string delall_tb_message = "delete from tb_message";
public static final string reply_tb_message = "insert into tb_message (mes_content,mes_sender,mes_sendtime,to_whom) values(?,?,?,?,?)";
public static final string add_tb_link = "insert into tb_link (link_name,link_add) values (?,?)";
public static final string del_tb_link = "delete from tb_link where link_id=?";
public static final string query_tb_link = "select link_id,link_name,link_add from tb_link";
// public static final string part_article = "select article_id,title,content,phtime,number from tb_article order by article_id desc";
public static final string part_article = "select article_id,title,content,phtime,number,typename from tb_article left join tb_articletype on (tb_article.type_id=tb_articletype.type_id) order by article_id desc";
public static final string show_link = "select * from tb_link ";
public static final string show_note = "select * from tb_note order by note_id desc";
public static final string add_tb_video = "insert into tb_video (video_name,video_time) values(?,?)";
public static final string add_tb_test = "insert into tb_test (test_name,test_time,user_name) values(?,?,?)";
public static final string query_tb_video = "select video_name,video_time from tb_video order by video_id desc";
public static final string query_tb_test = "select test_name,test_time,user_name from tb_test order by test_id desc";
public static final string del_tb_video = "delete from tb_video where video_name=?";
}
第7章 开发中遇到的难点和对策
a. 数据库的连接问题
问题:数据库的连接:在开发过程中经常出现查找不到数据库,出现这样的错误一般是数据库的连接出现问题。
数据库加载驱动有问题。一开始用的是
class.forname("com.microsoft.jdbc.sqlserver.sqlserverdriver").newinstance();
stirng url = "jdbc:microsoft:sqlserver://localhost:1433;databasename=mywork";
要求有三个库文件:msbase.jar,mssqlserver.jar,msutil.jar,该文件需要放在服务器的/web-inf/lib文件夹下面.
解决方法:经检查发现1433端口没有打开,于是就换成下面的odbc-jdbc桥驱动:
class.forname("sun.jdbc.odbc.jdbcodbcdriver");
string url="jdbc:odbc:mydb";
connection con=drivermanager.getconnection("jdbc:odbc:mywork");
换成这个驱动就可以连上数据库了。
b. 从数据库中查询信息时会出错
问题:把查询的结果集rs放在arraylist的对象list中,可是在jsp页面中调用的时候却没有值。
解决方法:经检查发现,向maf中set相应属性时,顺序必须跟sql查询语句中的查询的顺序一样才可以。
while(rs.next()){
maf = new messageactionform();
maf.setmes_id(rs.getint("mes_id")); //1
maf.setmes_title(rs.getstring("mes_title")); //2
maf.setmes_content(rs.getstring("mes_content")); //3
maf.setmes_sender(rs.getstring("mes_sender")); //4
maf.setmes_sendtime(rs.getstring("mes_sendtime")); //5
list.add(maf);
}
第8章 总结 及未来展望
8.1 总结
《数据库原理网上授课平台》采用b/s模式, 在研究当前网站的基础上,经过详细调研后,确定了系统设计的领域,包括系统设计、数据库设计、程序设计等;通过采用面向对象设计的思想,用java程序语言和jsp+struts等相关技术进行开发设计;本系统主要完成了用户登录模块,用户注册模块,留言模块,视频管理模块,电子教案管理模块,在线答疑模块。该系统完成了用户可以下载电子教案,视频,在线向管理员提问。 利用sql server 2000+jsp+struts框架开发的,便于维护。同时为网站的用户提供友好的操作界面以及操作的灵活性,使用户能轻松地完成相应操作。
在系统的开发过程中也遇到了许多困难和问题,数据库的连接、数据写入数据库时出错、在调度中出现字符不匹配、页面的设计等。处理数据库的连接是通过建立数据源和jsp中的连接语句实现的,数据的处理是通过sql语言完成的,而页面的设计通过html和dreamweaver对其进行设计。
在本次开发过程中涉及到了许多新东西,也遇到了许多问题,经过和老师与同学的交流以及自己的努力解决了这些问题。在本次开发过程中使我很好的掌握了jsp+struts等相关技术和sql server 2000,给我以后的学习带来了极大的帮助。
8.2 展望
由于这次毕业设计时间紧迫,加之自己的水平有限,系统设计得比较简单,有些方面都没有来得及实现,在以后的学习和实践中我会加以丰富。
(1)为了数据安全,在本系统中只有对该系统所用到的数据库进行备份,而没有对应的数据恢复和数据清理机制,为了能够使得系统数据不至于在遇到误操作时无法恢复,应设计数据恢复功能模块,并及时对数据进行定时的清理。并且此次设计也没有数据参照完整性问题。今后要注意这个问题,要把数据库部分做的更加安全。
(2)“在线答疑”学生提交问题,存入数据库,教师显示页面每隔一秒自动刷新,调用chataction类中的方法从数据库中查询结果的在教师显示页面中显示。后因用了frame把几个页面放在一个页面中出了错,所以基本未实现。今后要将其完成。做的更完美一些。
(3)本系统只用了struts框架,为了使系统更好,应该使用struts+spring+hibernate三大框架。
(4)在用户模块中,由于用户需求不同,系统应具有更好的扩展功能来完善,如增加密码找回功能等,更好的满足用户的需求。
参考 文献
[1] 张海藩. 软件工程导论(第四版)[m]. 北京:清华大学出版社,2003.12
[2] johannes gehrke(美). 数据库系统概念[m]. 北京:清华大学出版社,2004.10
[3] paul dubois(美). 网络 数据库指南[m]. 北京:机械 工业 出版社,2000.1
[4]marty hall,larry brown(美). servlet与jsp核心编程(第2版)[m]. 北京:清华大学出版社,2004.6
[5] 汪晓平,俞俊,李功. 精通java网络编程[m]. 北京:清华大学出版社,2005.9
[6] 李载甲. jsp完全探索[m]. 北京: 中国 青年出版社,2001.1
[7] y.daniel liang(美). java编程原理与实践(第4版)[m]. 北京:清华大学出版社,2005.8
[8] 4u2v工作室. dreamweaver网页设计与制作100例[m]. 北京:人民邮电出版社出版,2004.8
[9] 刘晓华,张健,周惠贞. jsp应用开发详解[m]. 北京:电子工业出版社,2002.1
[10] 赵辉,李建国. jsp开发技术原理与实践教程[m].北京:电子工业出版社
[11] 宋梅,张学平. 深入浅出j2ee架构[m].北京:清华大学出版社
[12] 王林玮. jsp网络开发技术与案例应用[m].北京:机械工业出版社, 2000.1
[13] 新东方 教育 科技集团.基于struts的web应用开发.西安:新东方教育科技集团