基于Java的图书馆管理系统设计与实现【附源码】

摘 要
随着社会的发展,人类对知识的需求也在不断地增长。在这种形式下,书籍就逐渐成为获得知识的主要途径。因此图书馆就自然而然地在人们的生活中占据了一定的位置。如何科学地管理图书不但关系到读者借阅图书的方便程度,也关系到图书馆的发展。因此,开发一套完善的图书馆管理系统就必不可少了。
本文详细讲解如何使用Java语言开发图书馆管理系统。同时为了使程序结构更加简洁,在编写是使用了简单的MVC架构。本系统还使用了MySQL数据库来存储有关数据。主要实现以下功能功能:
⑴ 登录管理:提供用户登录、注销及修改密码等功能。
⑵ 用户信息管理:提供用户信息查看以及修改密码等功能。
⑶ 图书借阅管理:图书管理员可以对图书进行借阅和归还操作。
⑷ 图书信息管理:图书管理员可以对图书进行增加及更新操作。
⑸ 新书订购:可以为图书馆里增添新书下购书订单。

关键词:图书管理系统;图书订购;MVC模式

Abstract
With the development of society,the human demand for knowledge continues to grow.In this situation,the book gradually became the main way to knowledge.So the library naturally occupies a certain position in people’s lives. How to scientifically manage the books not only related to the convenience of the readers to borrow books, but also to the development of the library.Therefore,development a comprehensive library management system will become essential.This writing explains how to use the Java language for developing library management system in detail.
This paper explained in detail how to use Java language to develop the library management system. Meanwhile, in order to make the program structure more simple, prepared using a simple MVC architecture. The system also uses a MySQL database to store the data. The main achievement of the following functions:
⑴ Log management: provides the user login, logout and modify passwords and other functions.
⑵ The user information management: provides user information view and modify passwords and other functions.
⑶ The librarian, library management system to borrow and return books operating.
⑷ Library information management: the librarian can add to the book and the update operation.
⑸ The new order, can add: library book purchase order.
Key words: Library management system;Book ordering;MVC model

目 录
第1章 序言 1
1.1课题开发背景及意义 1
1.2课题研究内容 2
第2章 开发工具及相关技术 4
2.1开发工具 4
2.2开发运行环境 8
2.3相关技术支持 12
2.4 MVC模式 15
第3章 系统总体设计 17
3.1功能与模块分析 17
3.2系统实现流程图 18
3.3系统用例图 19
第4章 数据库设计 21
4.1数据库分析 21
4.2数据库概念设计 21
4.3数据库逻辑结构设计 24
4.4数据库E-R图 28
第5章 系统详细设计 30
5.1公共模块设计 31
5.2基础数据维护模块设计 35
5.3新书订购管理模块设计 38
5.4借阅管理模块设计 40
5.5系统维护模块设计 44
第6章 系统测试与优化 46
6.1系统安全优化 46
6.2身份验证 48
6.3异常处理 49
6.4系统测试 50
第7章 总结与展望 53
参考文献 54
致谢辞 55
附录1 英文参考文献 56
附录2 中文参考文献 60

1序言
1.1课题开发背景及意义
当今社会随着图书馆规模的不断壮大,图书馆馆藏的图书品种、数量也逐渐增多。在图书馆不断发展的同时,其常年采取的传统的人工方式管理暴露了一些问题:
⑴ 检索速度慢、效率低
因为图书馆的藏书种类多、数量大,将藏书准确地分门别类,快速检索,手工进行非常困难往往是终于查到了图书的信息,馆中没有此书或已被别人借走。图书馆的规模越大,这个问题越突出。
⑵ 借书、还书工作量大
借书、还书频率越大,说明图书馆的作用越大,然而随之而来的大量的借书、还书登记、实存图书的更新以及借出图书超期、遗失等的处理,其工作量之大,往往是人工操作所难以胜任的。而且经常会出现这样那样的差错。
⑶ 图书统计工作难、藏书更新不能及时完成。
图书馆的图书应根据科学技术的发展和教学工作的需要及时添加和更新,然而由于藏书数量及图书种类越来越多,加上自然损耗,人为破坏,使图书的统计工作难以及时完成,藏书的更新也就很难有针对性地进行,藏书的知识结构得不到良好地控制。
当今高校发展速度很快,图书馆的规模和藏书数量也不断的扩大,为了解决海量图书的管理问题,改变传统的管理方式也是迫在眉睫了。
随着计算机的广泛应用,其逐步成为现代化的标志。图书馆或者一些企业内部,甚至是书店,在正常运行过程中总是面对大量的读者信息,书籍信息以及两者相互作用产生的借书信息、还书信息。因此需要对读者资源、书籍资源、借书信息、还书信息进行管理,及时了解各个环节中信息的变更,要对因此而产生的单据进行及时的处理,为了提高图书馆或者企业内部对图书存销的自动化的管理,能够更快速的满足读者的要求,提高各种工作的效率,现对其设计相应的系统,以达到上述的目的。
图书管理系统的主要功能是实现图书馆图书借阅和归还的管理的自动化。围绕这一主要功能,本系统涉及到以下核心功能:借阅管理,归还管理。除了这些核心功能外,还包括一些基本和辅助功能,它们是:用户管理、图书馆参数管理、图书管理、统计查询。
1.2课题研究内容
本课题主要应用Java语言编程,以MVC简易分层架构,再结合与MySQL数据库连接等相关知识进行图书馆管理系统的设计和实现。本课题内容包括以下内容:
⑴ 登录管理:为用户提供登录、注销及修改密码等功能。登录时有相应的身份验证功能,以便能让不同权限的用户能使用到相应的功能;修改密码时要求每个用户只能修改自己的密码。
⑵ 用户信息管理:每个用户可以对自己的信息进行查看以及修改等操作,与此同时用户还可以查看自己当前借阅信息和历史借阅信息。
⑶ 新书订购:可以为图书馆里增添新书下购书订单,并能对订购单进行验收。每一个订单中可以包含多本图书,可以对订单中的图书信息进行修改。在验收订单时,输入相应的订单号后就能找到要验收的订单,确认验收即可。
⑷ 图书信息管理:图书管理员可以对图书进行增加及更新操作。图书的添加时,要检测正要添加的图书是否与馆藏的图书重复,并做相应的处理。对图书信息更新时,按照图书的编号找的馆藏图书后,对图书信息进行更新即可。
⑸ 图书借阅管理:图书管理员可以对图书进行借阅和归还操作。图书的借阅与归还是图书馆最重要的工作,在图书借阅时要判断该书是否已经被该用户借阅了,并进行相应的操作。归还时,只要找到该用户的借阅信息,归还图书即可。
⑹ 图书查询:用户可以通过图书编号以及书名进行查询。图书的查询功能是为了满足用户想要了解馆藏图书信息的需求而添加的。图书查询是条件查询,按照图书编号、图书名称、出版社、作者等信息进行条件查询,当要输入的信息为空是就将图书全部查询出来。

2开发工具与相关技术
2.1开发工具
IDE(Integrated Development Environment,集成开发环境)。其缩写形式IDE同时也代指“电子集成驱动器”。IDE集成开发环境(简称IDE)软件是用于程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面工具。该程序可以独立运行,也可以和其它程序并用。
2.1.1 Eclipse 简介
Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。
虽然大多数用户很乐于将 Eclipse 当作 Java 集成开发环境(IDE)来使用,但 Eclipse 的目标却不仅限于此。Eclipse 还包括插件开发环境(Plug-in Development Environment,PDE),这个组件主要针对希望扩展 Eclipse 的软件开发人员,因为它允许他们构建与 Eclipse 环境无缝集成的工具。由于 Eclipse 中的每样东西都是插件,对于给 Eclipse 提供插件,以及给用户提供一致和统一的集成开发环境而言,所有工具开发人员都具有同等的发挥场所。
这种平等和一致性并不仅限于 Java 开发工具。尽管 Eclipse 是使用 Java 语言开发的,但它的用途并不限于 Java 语言;例如,支持诸如 C/C++ 和 COBOL 等编程语言的插件已经可用,或预计将会推出。Eclipse 框架还可用来作为与软件开发无关的其他应用程序类型的基础,比如内容管理系统。 基于 Eclipse 的应用程序的一个突出例子是 IBM Rational Software Architect,它构成了 IBM Java 开发工具系列的基础。
Eclipse Babel项目提供了多种语言包,用户可以根据自己的需求来对Eclipse进行汉化,汉化以后的界面如图2.1所示。

图2.1 汉化后的Eclipse
2.1.2 NetBeans简介
NetBeans 由Sun公司(2009年被甲骨文收购)在2000年创立,它是开放源运动以及开发人员和客户社区的家园,旨在构建世界级的Java IDE。NetBeans当前可以在Solaris、Windows、Linux和Macintosh OS X平台上进行开发,并在SPL(Sun公用许可)范围内使用。
NetBeans IDE是一个屡获殊荣的集成开发环境,可以方便的在Windows,Mac,Linux和Solaris中 运行。NetBeans包括开源的开发环境和应用平台,NetBeans IDE可以使开发人员利用Java平台能够快速创建Web、企业、桌面以及移动的应用程序,NetBeans IDE目前支持PHP、Ruby、JavaScript、Ajax、Groovy、Grails和C /C + +等开发语言。
NetBean开发环境提供了丰富的产品文档和培训资源以及大量的第三方插件。它是一种“所见即所得”的开发工具,界面如图2.2。

图2.2 NetBeans界面图
Swing 是一个为Java设计的GUI工具包。 Swing 是 JAVA基础类 的一部分。 Swing 包括了图形用户界面 (GUI) 器件 如:文本框,按钮,分隔窗格和表。
Swing是一个用于开发Java应用程序用户界面的开发工具包。它以抽象窗口工具包(AWT)为基础使跨平台应用程序可以使用任何可插拔的外观风格。Swing开发人员只用很少的代码就可以利用Swing丰富、灵活的功能和模块化组件来创建优雅的用户界面。但是SWING 提供许多比AWT更好的屏幕显示元素。它们用纯Java写成,所以同Java本身一样可以跨平台运行,这 一点不像AWT。 它们是JFC的一部分。 它们支持可更换的面板和主题(各种操作系统默认的特有主题),然而不是真的使用原生平台提供的设备,而是仅仅在表面上模仿它们。这意味着你可以在任意平台 上使用JAVA支持的任意面板。 轻量级元件的缺点则是执行速度较慢,优点就是可以在所有平台上采用统一的行为。
使用NetBeans开发Swing,只要将控件从控件栏拖出来,放到你想要放的地方,然后选中它,在属性栏中编辑它的相应事件,就能轻松完成。NetBeans提供的丰富的控件能够让我省去了编写界面的时间,极大的节省了编码者的时间。NetBeans控件栏如图2.3.

图2.3 NetBeans控件栏
2.2开发运行环境
本系统是在64位Window7下开发的,配置的编程环境应该与window操作系统相匹配。使用Java开发桌面应用程序相对简单,只要正确安装JDK、Netbeans、MySQL数据库即可。
下面是图书管理系统的具体开发环境:
⑴ 系统开发平台:NetBeans IDE 7.1.2
⑵ 数据库:mysql-5.5.23
⑶ 数据库管理工具:Navicat Premium
⑷ 运行平台:Window XP及以上
⑸ Java开发包:jdk-7u4-windows
⑹ 分辨率:800×600以上
⑺ GUI开发包:Swing
Java应用程序开发需要的环境如上面所说。下面介绍一下开发Java应用程序所用到的相关技术的介绍。
2.2.1 JDK简介
JDK(Java Development Kit)是Sun Microsystems专门针对Java程序员开发的免费软件开发工具包。自从Java推出以来,JDK已经成为使用最广泛的Java SDK。JDK 是整个Java的核心,包括了Java运行环境,Java工具和Java基础的类库。此外,还可以使用Open JDK进行开发。JDK是学好Java的第一步,所以对程序开发人员,必须使用JDK进行开发调试。对于普通用户仅需要安装JRE来运行Java程序即可。
在Oracle官方网站上下载JDK安装文件,点击安装包安装即可。JDK安装完成后文件夹结构如图2.4。

图2.4 JDK安装文件夹
bin文件夹包含各种命令,例如javac命令可以将Java源文件编译成class文件;java命令可以运行class文件;jar命令可以将相关的类文件爱你进行打包;javadoc命令用于从源代码中提取说明文档。src压缩文件包含了Java SE API的源代码。正是因为有这么多的命令,许多程序的运行需要JDK,所以理所当然要配置Java的环境变量。右击“我的电脑”,点击“属性”>“高级”>“环境变量”>“系统变量”中,设置3项属性,JAVA_HOME,PATH,CLASSPATH,若已存在则点击“编辑”,不存在则点击“新建”。
JAVA_HOME指明JDK安装路径,D:\Software\Java\jdk1.7.0_04/jdk,此路径下包括lib,bin,jre等文件夹;Path使得系统可以在任何路径下识别java命令,设为:%JAVA_HOME%/bin;%JAVA_HOME%/jre/bin ; CLASSPATH为
java加载类(class or lib)路径,设为%JAVA_HOME%/lib/dt.jar; %JAVA
_HOME%/lib/tools.jar。上面的%JAVA_HOME%就是引用前面指定的JAVA_HOME。设置截图如图2.5。

     图2.5 JDK环境变量配置

2.2.2 MySQL数据库简介
MySQL是一个小型关系型数据库管理系统,开发者为瑞典MySQL AB公司。在2008年1月16号被Sun公司收购。而2009年,SUN又被Oracle收购。MySQL是一种关联数据库管理系统,关联数据库将数据 保存在不同的表中,而不是将所有数据放在一个大仓库内。这样就增加了速度并提高了灵活性。MySQL的SQL“结构化查询语言”。SQL是用于访问数据库的最常用标准化语言。MySQL软件采用了GPL(GNU通用公共许可证)。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了MySQL作为网站数据库。

图2.6 MySQL命令窗
由于MySQL数据库安装完成后,要使用是用命令提示符窗口,相对不变。我们要安装一个前台的图形化界面程序,以便进行数据库操作。
Navicat 是一套快速、可靠并价格相宜的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设。它可以用来对本机或远程的 MySQL、SQL Server、SQLite、Oracle 及 PostgreSQL 数据库进行管理及开发。 Navicat 的功能足以符合专业开发人员的所有需求,但是对数据库服务器的新手来说又相当容易学习。有了极完备的图形用户介面 (GUI),Navicat 让你可以简便地以安全且简单的方法创建、组织、访问和共享信息。 Navicat 适用于三种平台 - Microsoft Windows、Mac OS X 及 Linux。它可以让用户连接到任何本机或远程服务器、提供一些实用的数据库工具如数据模型、数据传输、数据同步、结构同步、导入、导出、备份、还原、报 表创建工具及计划以协助管理数据。

图2.7 Navicat工作界面
2.3相关技术支持
2.3.1 JDBC操作数据库
在本程序中,将数据信息保存到MySQL数据库中。因此需要使用JDBC技术来操作数据库。
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC为工具/数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯 Java API 编写数据库应用程序。
本系统中将操作数据库的代码统一编写到DataAccess包中的Database类中。获取连接、操作数据库、释放连接的关键代码如下:
public class Database {
protected static String dbClassName =
“com.mysql.jdbc.Driver”;//数据库连接驱动类
protected static String dbUrl = “jdbc:mysql://localhost:3306/library”;//数据库连接URL
protected static String dbUser = “meng”; //数据库用户名
protected static String dbPwd = “aptx4869”; //数据库密码
private static Connection conn = null; //数据库连接对象
public static Connection getConnection() { //默认构造函数
try {
if (conn == null) { //如果连接对象为空
Class.forName(dbClassName); //加载驱动类
conn = DriverManager.getConnection(dbUrl, dbUser, dbPwd); //获得连接对象
}
} catch (Exception ee) {
//ee.printStackTrace();
JOptionPane.showMessageDialog(null, “未成功加载驱动!”, “错误”, JOptionPane.ERROR_MESSAGE); }
return conn;
}
public void close() { //关闭方法
try {
conn.close(); //关闭连接对象
} catch (SQLException e) {
//e.printStackTrace();
JOptionPane.showMessageDialog(null, “未成功关闭连接!”, “错误”, JOptionPane.ERROR_MESSAGE);
} finally {
conn = null; //设置连接对象为null值
}
}

2.3.2 MySQL存储过程
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
本系统将进行数据操作的部分写成了数据库的存储过程,并在Java中的DataAccess包中的Database类中调用存储过程。调用存储过程例子的代码如下:
public int LoginCheck(String name) {
int flag = 0;
try {
Connection conn0 = Database.getConnection();
// 设置调用的存储过程名及参数情况
CallableStatement proc = conn0.prepareCall(“{call logincheck(?,?)}”);
proc.setString(1, name); // 设置输入参数值1的值
proc.registerOutParameter(2, java.sql.Types.INTEGER);
// 设置输出参数及返回类型
proc.execute();
if (!proc.getMoreResults()) {
flag = proc.getInt(2); }
proc.close();
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, “数据库操作不成功!”, “警告”, JOptionPane.WARNING_MESSAGE);
}
return flag;
}
2.4 MVC模式
MVC是三个单词的缩写,分别为: 模型(Model),视图(View) 和控制Controller)。Swing创造性的采用了MVC(Model View Controller) 模式。MVC 把控件(Component)划分成三个部分:模型( Model):管理这个模块中所用到的数据和值,如某个数据的最大值、最小值、当前值等数据;视图( View):管理如何将模型显示给用户;控制器(Controller) 决定如何处理用户和该模块交互时产生的事件,如用户单击一个按钮等。
本课题程序也采用了简单的分层,分为表现层、业务逻辑层、数据访问层。
表现层就是与用户交互的各种界面,这个层把用户的数据传递给业务逻辑层,同时能接受从业务逻辑层传来的数据;数据访问层负责执行各种数据操作,这个层把业务逻辑层传来的数据经过相应的处理,并形成对数据库操作的方法,执行这个方法就能完成对数据库的操作,这个层还能将从数据库返回的数据传递给业务逻辑层;业务逻辑层处于表现层和数据访问层之间,为两者传递数据。
下面图2.8描述的就是MVC模式。

图2.8 MVC模式图

3系统总体设计
图书管理系统是一个高度集成的图书信息处理系统,通过将图书管理的各种功能进行整合,从而达到高度检索信息、提高工作效率、降低管理成本等目的。一个典型的图书管理系统应该能够管理所有的图书种类、图书信息以及读者信息 ,还需要提供各种图书信息的检索查询功能。该系统还需要能够对图书借阅、归还进行操作,并对读者的罚款进行自动计算。通过该系统的自动化管理,能够大大减少图书馆管理人员,还能减少管理人员的工作任务,从而降低管理开销和成本。
3.1功能与模块分析
图书管理系统是管理图书的一个重要工具,一个功能完善的图书管理系统需要提供5个功能模块,分别是图书管理模块、读者信息管理、新书订购模块、图书借阅模块,以及系统维护模块。其中各功能模块的具体说明如下:
图书管理模块:该模块主要负责管理图书馆的图书各种信息和查询图书,如图书种类的名称、可借天数、罚款数目、图书编号、图书名称、作者、出版社等信息。包括图书查询、图书添加、图书类别添加、图书信息修改等模块。
读者信息管理模块:该模块主要负责管理图书馆的读者信息,如读者编号、读者信息、证件号、最大借书量等信息。
新书订购管理模块:该模块主要负责管理图书馆的新书订购邪的信息,包括新书订购和验收新书两个子模块。
图书借阅管理模块:该模块主要负责管理图书馆的书籍借阅于归还,包括图书借阅和图书归还两个子模块。
系统维护模块:该模块主要负责管理图书馆的工作人员信息,包括用户密码修改和用户管理两个子模块。
由各个模块可以都得到系统的模块结构图,模块结构图如图3.1。

图3.1 模块结构图
3.2 系统实现流程图
经实际思考分析、基于图书馆发展需求,现在将图书管理系统按照功能划分为基础数据维护模块、新书订购管理模块、借阅管理模块、系统维护模块模块等功能模块。其中,基础数据维护模块用来维护读者信息,图书类别和图书信息,新书订购模块用于新书订购和验收新书,借阅管理模块用图书借阅、图书归还,系统维护模块用于更改口令和用户管理。
整个图书管理系统不但可以按照整体需求实现各种功能,同时也可以帮助图书馆管理人员安全、稳定、高效地实现管理体制。基础数据维护模块包括了系统维护的全部内容,方便管理。新书订购管理模块可与快速查看新书信息。借阅管理模块具有快捷查询、易于维护等特点。系统维护模块可以方便地添加管理员,并能对已经存在的人员信息进行修改。
要使用系统首先需要对用户的身份进行识别,只有合法的用户才能进入系统;否则将不能进入系统。进入系统后,首先打开的是系统的主窗体,在系统的首页的菜单或者功能区可以选择各种导航连接来进行个中操作。
图书管理系统结构图如图3.2。

图3.2 图书管理系统结构图
3.3 系统用例图
图书管理系统是一个内部人员使用的系统,也就是说不是所有人都能够使用他,只有在图书馆登记注册的用户才能使用。而在图书馆注册的用户也分两类:一类是普通用户,拥有图书的借阅、归还和更改密码的权限;另一类是管理员,除了普通用户的所有功能外,还能够对书籍列表、书籍信息、读者信息等进行管理。下面以管理员为用例,绘制其所对应的用例图如图3.3所示。

图3.3管理员用例图
相对与管理员普通用户所拥有的权限相对较少,只能借阅、归还图书和修改自己的密码。普通用户的用例图如图3.4。

图3.4 普通用户用例图

4数据库设计
4.1数据库分析
在开发图书管理系统是,考虑到图书量大,数据维护大的特点,决定采用MySQL作为数据库,用Navicat 作为数据库管理软件。在MySQL新建一个数据库,将其命名为library。数据库中一共包含10张表,用来存储不同信息,数据库表的详细信息如图4.1所示。

图4.1 数据库library中的所有数据表
4.2数据库概念设计
本系统一共设计规划6个实体类,分别是图书类别信息实体、图书信息实体、读者信息实体、用户信息实体、图书借阅信息实体以及图书订购信息实体。
图书的类别有很多,例如有文学、人文、天文、数学、计算机等。因此可以建立一个图书类别信息表,专门用来保存图书的类别信息。同时因为每种类别的书籍阅读时间有所不同。所以需要在类别表中保存该类别可借天数信息。图书类别信息实体E-R图如图4.2.

          图4.2 图书类别信息实体E-R图

对于图书馆来说最重要的就是要管理其下的书籍,所以需要建立一个图书信息表,用来保存图书的所有信息。图书信息实体E-R图如图4.3。

图4.3图书信息实体E-R图
要想在图书馆借书首先需要进行登记并交押金,领取读书。所以需要建立一个读者信息表来保存图书馆的所有读者的登记信息。读者信息实体E-R图如图4.4。

图4.4 读者信息实体E-R图
图书馆里一般有一个以上的系统操作员,需要建立一个操作员信息表,用来保存操作员的身份信息。操作员信息实体E-R图如图4.5。

图4.5操作员信息实体E-R图
图书馆最大的功能就是能够借书,这时需要建立一个图书借阅信息表,用来保存读者的借书信息,例如读者编号、书籍编号等。图书借阅信息实体E-R图如图4.6.

图4.6 图书借阅信息实体E-R图
图书馆除了借书,还需要到出版社或者其他代理商订购新书,这时需要建立一个图书订购信息表,用来保存所有的订购信息,如订购书籍编号、数量、书籍折扣等信息。图书订购信息实体E-R图如图4.7。

图4.7 图书订购信息表
4.3数据库逻辑结构设计
数据库中各表中tb_borrowhis、tb_ordertemp分别用来保存图书借阅历史、临时图书订购单,他们的结构分别与tb_borrow、tb_order表的结构相同,就不再列举他们的信息。
根据设计好的各实体E-R图创建数据库的逻辑结构,数据库各表的结构如下。
⑴ 图书类别信息表tb_booktype用来存储所有的图书类别信息,包括图书类别编号、图书类别名称、可借天数以及迟还一天的罚款数额4个字段。该表的逻辑结构图如图4.8。

图4.8图书类别信息表
⑵ 图书信息表tb_bookinfo用来存储所有的图书信息,包括图书编号、类别编号、图书名称、作者、译者、出版社、出版日期、书籍数量以及书籍价格9个字段。该表的逻辑结构图如图4.9。

图4.9图书信息表
⑶ 读者信息表tb_reader用来存储所有的读者信息,包括读者姓名、性别、年龄、证件号码、会员证有效日期、最大借书量、电话号码、押金、证件类型、职业、读者编号以及办证日期12个字段。该表的逻辑结构如图4.10。

图4.10读者信息表
⑷ 操作员信息表tb_operator用来保存操作员信息,包括操作员编号、用户名、性别、年龄、证件号码、工作时间、电话号码、是否为管理员、密码9个字段。该表的逻辑结构如图4.11。

图4.11操作员信息表
⑸ 操作员类别信息表tb_operatortype用来保存操作员类别信息,包括类别编号。类别名称、操作员权限3个字段。该表的逻辑结构如图4.12。

图4.12操作员类别信息表
⑹ 图书借阅信息表tb_borrow用来存储所有图书借阅信息,包括借阅编号、书籍编号、读者编号、操作员编号、是否归还、借阅日期、应还日期以及罚款8个字段。该表的逻辑结构如图4.13。

图4.13图书借阅信息表
⑺ 图书订购单表tb_order用来保存图书馆的所有订购信息,包括订单编号、订购日期、操作员、是否验收以及书籍折扣5个字段。该表的逻辑结构如图4.14。
⑻ 图书订单详情表tb_bookinfotemp用来保存订单里图书的详情,包括图书编号、类别编号、图书名称、作者、译者、出版社、出版日期、书籍数量、书籍价格、订单编号、流水号(作为主键)11个字段。该表的逻辑结构如图4.15。

图4.14 图书订购单表

图4.15 图书订单详情表
4.4 数据库E-R图
数据库中表tb_borrow中的readerid字段是表tb_reader中的主键,operatorid字段是表tb_operator中的主键,bookISBN是tb_bookinfo表中的主键;表tb_operator中的admin是表tb_operatortype的主键;表tb_bookinfo中的typeid是表tb_booktype中的主键;表tb_bookinfotemp中的ISBN是表tb_bookinfo中的主键,tb_bookinfotemp中的orderid是表tb_order中的主键。
根据各表的之间的关系,绘制各表之间的关系E-R图,如图4.16。

图4.16 各表之间的关系E-R图

5 系统详细设计
在编写代码前,把代码的结构设计好是一个很好的习惯,这样可以方便的开发系统,同时还可以规范系统的整体架构。本系统的文件夹组织结构图如图5.1。

图5.1文件夹组织结构图
NetBeans工程构建过后,将产生的类放置到了build文件夹的classes下面,将生成的jar包放置到了dist下面。nbproject 文件夹包含大多数 NetBeans 项目 meta 数据,包括由主 NetBeans 生成脚本调用的资源。该文件夹还包含一个 private 文件夹,其中包含特定于您的系统的数据。不应将该文件夹签入到版本控制系统中,因为它的内容会因用户而异。build.xml 文件是项目的主 NetBeans 生成脚本。您可以根据项目的需要来定制脚本。缺省情况下,该文件的名称为 build.xml。如果项目文件夹中已经存在这样的文件,则该脚本的名称为 nb-build.xml。src文件夹是NetBeans工程源代码存放文件夹。从上图可以看出,该文件夹包含了工程中已经分好层次的各个层,其中Business文件夹存储的是业务逻辑层,DataAccess文件夹存储的是数据访问层,Frames文件夹存储的是表现层,Common文件夹存储的是公共类,Entity文件夹存储的是实体类,Images文件夹存储的是工程所用到的图片。
5.1公共模块设计
公共模块是一些用户必须要用到的程序,这些程序被统一叫做公共模块。
5.1.1登录模块
登录模块是用户登录时,通过对比用户输入的用户名和密码和数据表里相应的内容,来判断用户拥有哪些权限,让用户可以进行那些操作。由于登录界面是系统的第一个提供给用户的界面,我们力求简洁,设计界面如5.2图:

图5.2 用户登录页面
在登录模块中,用户名的输入框具有验证功能,当你没输入一个字符便会判断用户名存不存在,如果为空的话也会做出判断,主要代码如下:
if(userid.equals(“”))
{
jlblName.setText(“用户名不能为空!”);
jlblName.setForeground(Color.red);
jtxtName.requestFocus();
}
else
try{
if(users.Logincheck(userid)!=1)
{
jlblName.setText(“用户名未找到!”);
jlblName.setForeground(Color.red);
}
else
{
jlblName.setText(“用户名正确!”);
jlblName.setForeground(Color.green);
userid=jtxtName.getText().trim();
}
}
输入正确的用户名和密码方可进入系统,进入系统才能进行各种操作。
5.1.2 数据表信息绑定
JTable是Swing编程中很常用的控件,它是一般是用来显示从数据库里查出的数据集。正是因为JTable控件的这种特点,使得JTable在本系统中使用的次数颇多,有必要把JTable的数据绑定放在公共模块中方便使用。JTable数据绑定的主要代码如下:
public DefaultTableModel displayResultSet(String[] col, RowSet rs)
throws SQLException {
mm= new DefaultTableModel(col,0);
rs.beforeFirst();// 指针移到第一条记录前面
boolean hasRecords = rs.next();
if (!hasRecords) { // 记录集为空,提示一条消息
JOptionPane.showMessageDialog(null, “无相关记录”, “检查你的输入!”, JOptionPane.ERROR_MESSAGE);}
else { do
{ String [] str_row=new String[col.length];
for(int i= 0;i<col.length;i++)
{ str_row[i]=rs.getString(i+1); }
mm.addRow(str_row);//添加在表模板中,
}while(rs.next());
}
return mm; }
5.1.3 日期格式转换
日期的格式在与数据库连接的程序中经常需要转换,日期格式由字符串转换成日期格式,或者将日期格式转换成所需要的字符串。
字符串转换成日期格式的主要代码如下:
public Date Switch(String todate)
throws ParseException, SQLException
{
java.sql.Date time=null;
if(!todate.equals(“”))
{
SimpleDateFormat df = new SimpleDateFormat(“yyyy-MM-dd”);
java.util.Date time1 = df.parse(todate);//util类型
time=new java.sql.Date(time1.getTime());
}
else
{ }
return time;
}
日期格式转换成字符串的主要代码如下:
public Date Switchlong(String todate)
throws ParseException, SQLException
{
java.sql.Date time=null;
if(!todate.equals(“”))
{
SimpleDateFormat df = new SimpleDateFormat(“yyyy-MM-dd”);
java.util.Date time1 = df.parse(todate);//util类型
time=new java.sql.Date(time1.getTime());
}
else
{ // }
return time; }
5.2基础数据维护模块设计
基础数据维护模块包括图书类别管理、图书信息管理、读者信息管理和注销4个功能。
5.2.1 图书类别管理
为了方便图书的管理,可以将图书进行分类,因此提供了类别信息的管理。图书类别添加与修改其实数据操作类似,图书类别添加窗体如图5.3。页面可以输入新类别的名称,该类图书主持借阅天数及超器罚款信息。单击按钮即可完成类别信息的添加与修改了。

图5.3图书类别添加窗体
这里主要用到了Jtable的数据绑定和点击事件将数据填写到文本框中,关键代码如下:
Jtable数据绑定代码:
mmbooktype= tableDisplay.displayResultSet(booktype,users.getTypeall());
jtabbooktype.setModel(mmbooktype);
Jtable点击事件将数据填写到文本框大妈:
int row=jtabbooktype.getSelectedRow();
jtxttypeId.setText(jtabbooktype.getValueAt(row, 0).toString().trim());
jtxtBookTypeAdd.setText(jtabbooktype.getValueAt(row, 1).toString().trim());
jtxtBookTypeDayAdd.setText(jtabbooktype.getValueAt(row, 2).toString().trim());
jtxtBookTypeFaAdd.setText(jtabbooktype.getValueAt(row, 3).toString().trim());

图5.4图书信息添加内部窗体
5.2.2图书信息管理
图书信息管理包括了对图书信息的添加和修改。图书信息添加内部窗体如图5.4所示。在输入了合法数据之后,单击“添加”按钮可以完成图书信息的添加操作。
图书信息修改内部窗体如图5.5所示。在表格中选择需要修改的数据之后,下方会显示该书的相关信息。修改完毕后,单击“修改”按钮保存修改即可完成操作。

图5.5图书信息修改内部窗体
此页面的程序,是将数据传递到数据访问层,数据访问层交给数据库,有数据库中的存储过程执行数据操作,存储过程会在系统优化中提到,这里不再赘述。
5.2.3读者信息管理
在管理图书馆的读者信息时,需要提供读者的增加、修改和删除功能。为此提供了内部窗体完成增加功能,内部窗体完成修改和删除,同时还可以添加读者相关信息。读者相关信息操作窗体如图5.6.
在输入合法的信息之后,单击“添加”按钮,即可完成对读者相关信息的添加操作。
用户可以单击窗体部中的表格,选择需要修改或删除的读者信息。单击“修改”或者“删除”按钮,完成相应的修改或删除操作。
图5.6读者信息操作窗体
注销功能是为了让用户能退出系统,并且能够快速的再次登录而设计的。单击“注销”按钮即可返回到登录页面了。
5.3新书订购管理模块设计
5.3.1新书订购
新书订购功能用于管理新书的订购,在输入图书编号、图书名称等图书相关信息之后,点击“确认”按钮即可将该图书放入订单之中,订单的相关信息将会显示在窗体右侧的表格了。若还想添加另一本图书按照以上操作填写图书相关信息,点击“确认”按钮即可将该图书放入订单之中。此时如发现订单中的图书信息有误,点击右边图书信息表中你要修改的图书,图书相关信息将自动填写在左边的相应的栏目中,用户按照要求修改,点击“确认”按钮即可将修改后图书放入订单之中。在订单确认无误后,点击“提交订单”按钮,就正式生成了订单。订购新书窗体如图5.7。
新书订购功能也用到了Jtable的数据绑定操作和鼠标点击事件的响应,基本代码与上面的基本一致,这里不再赘述。

图5.7订购新书窗体
5.3.2验收新书
验收新书功能用于管理新书订单属否背验收。进入验收新书订单选项后,会出现查询订单的窗体,查询相关的未验收的新书订单,点击“查询”按钮,相应的订单信息会显示在下方的表格中。新书订单查询窗体如图5.8。

图5.8新书订单查询窗体

图5.9新书订单验收窗体
选择你要验收的新书订单,点击表中的相应的条目,验收新书的窗体会弹出。验收新书的窗体中有该订单中图书的详细的信息,确认订单无误之后,点击“验收”按钮即可完成验收新书。验收新书窗体如图5.9。
5.4借阅管理模块设计
5.4.1图书借阅
图书借阅管理用于完成图书借阅功能,读者输入想要借阅的图书编号,点击“查询”按钮相应的图书信息就会显示在下方的表格中,点击表格中的相应的条目就可借阅图书了,这样就完成了借阅操作。借阅窗体如图5.10。

图5.10借阅窗体
借阅管理要判断这本书你是否已经借阅了,如果已经借阅就不可再借阅了,判断的组要代码如下:
String isSure =
users.checkJieyue(borrow2).toString().trim();
if (isSure.equals(“否”)) {
JOptionPane.showMessageDialog(null, “此书你已经借阅或为归还,不能再借!”, “警告”, JOptionPane.WARNING_MESSAGE);
} else if (isSure.equals(“是”)) {
option = JOptionPane.showConfirmDialog(null, “你确定要借阅此书吗?”, “提示”, JOptionPane.YES_NO_OPTION);}
要想查看当前借阅图书的详细信息,点击“当前借阅信息”就可查看你当前已经借阅的图书了。借阅图书信息如图5.11。

图5.11借阅图书信息
5.4.2图书归还
图书归还管理用于完成归还操作。在输入读者编号后,会显示该读者借阅的书籍信息。点击表中的你要归还的图书条目,就可归还该图书。在归还的会判断借阅图书是否已经超期以及罚款金额,如果有会显示罚款数目,并提示你缴纳罚款。图书归还窗体如图5.12。
图书归还模块中要把查询出来的借阅信息放到表格中,如果你当前有借阅信息,Jtable中就会有借阅信息。点击Jtable中的你要归还的书籍条目,Jtable鼠标响应事件就会响应归还该图书,主要代码与前面的模块类似,这里不再赘述。

图5.12图书归还窗体
5.4.2图书查询
图书查询功能让用户查看馆藏图书情况,如果在按要求填写图书信息,并点击“查询”按钮,即可完成指定条件查询;如果不输入条件的话就查询全部图书。图书查询窗体如图5.13。

图5.13图书查询窗体
5.5系统维护模块设计
5.5.1更改密码
更改用户密码能用与修改当前登录用户的密码,每个操作员仅能修改自己的密码。更改密码窗体如图5.14。

图5.14更改密码窗体
每个用户只能修改自己的密码,进入密码修改模块之后用户名的文本框要设置成不可编辑才能让用户只能修改自己的密码。
设置文本框不可编辑,jtxtUserName. setEditable(false);
5.5.2用户管理
用户管理功能用于完成用户信息的添加、修改和删除等功能。用户信息操作窗体如图5.15。
用户管理功能包括了添加、修改和删除等功能,必须是用户权限高的管理员才能进行该操作。该页面用到的代码与前面的类似,这里不再赘述。

图5.15用户信息操作窗体

6系统测试与优化
6.1系统安全优化
数据访问层的数据操作部分,如果完全写成SQL语句不仅会造成程序规模庞大,还会造成程序不安全。为此本系统的数据操作部分写成了存储过程。
相对于直接使用SQL语句,在应用程序中直接调用存储过程有以下好处:
(1)减少网络通信量。调用一个行数不多的存储过程与直接调用SQL语句的网络通信量可能不会有很大的差别,可是如果存储过程包含上百行SQL语句,那么其性能绝对比一条一条的调用SQL语句要高得多。
(2)执行速度更快。有两个原因:首先,在存储过程创建的时候,数据库已经对其进行了一次解析和优化。其次,存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接调用。
(3)更强的适应性:由于存储过程对数据库的访问是通过存储过程来进行的,因此数据库开发人员可以在不改动存储过程接口的情况下对数据库进行任何改动,而这些改动不会对应用程序造成影响。
(4) 布式工作:应用程序和数据库的编码工作可以分别独立进行,而不会相互压制。
下面就以登录为例子列举主要代码;
程序中调用存储过程的代码:
public User Login(String id)//
{
User user = new User();
try {
Connection conn1 = Database.getConnection();
// 设置调用的存储过程名及参数情况
CallableStatement proc = conn1.prepareCall(“{call login(?,?,?,?)}”);
// 设置输入参数值1的值
proc.setString(1, id);
// 设置输出参数及返回类型
proc.registerOutParameter(2, java.sql.Types.VARCHAR);
proc.registerOutParameter(3, java.sql.Types.VARCHAR);
proc.registerOutParameter(4, java.sql.Types.INTEGER);
proc.execute();
user.setName(proc.getString(2));
user.setPassword(proc.getString(3));
user.setAdmin(proc.getByte(4));
proc.close();
} catch (SQLException e) {
}
return user;
}
MySQL数据库端的存储过程为:
CREATE DEFINER = root@localhost PROCEDURE NewProc(_nameid varchar(50),
OUT _name varchar(50),OUT _password varchar(50),
OUT _admin bit)
BEGIN
select tb_operator.name,tb_operator.password,tb_operator.admin into _name,_password,_admin from tb_operator where id=_nameid;
end;
6.2身份验证
身份验证是任务通过登录是查询数据库,来确认正在登录用户的权限,以便让用户在成功登录之后能够使用相应的功能。验证用户的身份,将经过未授权的用户会一直停留在登录窗口,直到输入正确的用户密码为止。
身份验证的主要代码如下:
if(password.equals(user.getPassword()))
{
flag=user.getAdmin();
Library jLibrary=new Library();
jLibrary.setVisible(true);
Login.this.setVisible(false);
}
else
{
JOptionPane.showMessageDialog(null, “登录失败!请输入正确的用户名和密码!”,“错误”,JOptionPane.ERROR_MESSAGE);
jtxtName.setText(“”);
jpwdPassword.setText(“”);
}
程序中的flag=user.getAdmin();语句就是用来获取用户的权限的代码。在这里在创建一个方法来让其他窗口来获取用户权限:
public int getFlag()
{ return flag;
}
6.3异常处理
根据具体的情况,可能需要以不同的方式处理应用程序中出现错误。
在与数据库连接是可能出现异常。处理该异常的代码端如下:
try { …
} catch (Exception ee) {
JOptionPane.showMessageDialog(null, “未成功加载驱动!”, “错误”, JOptionPane.ERROR_MESSAGE);
}
相应的异常处理页面如图6.1。

图6.1 数据连接异常处理页面
在程序调用数据库中的存储过程的时候,由于程序编写有误,或者数据库中的存储过程编写与程序不一致,导致异常的产生。此时应该对异常进行处理。处理该异常的代码端如下:
try{…}
} catch (SQLException e) {
//e.printStackTrace();
JOptionPane.showMessageDialog(null, “数据库操作不成功!”, “警告”, JOptionPane.WARNING_MESSAGE);
}
相应的异常处理页面如图6.2。

图6.2 数据操作不成功异常处理页面
6.4系统测试
随着软件开发规模的增大、复杂程度的增加,以寻找软件中的错误为目的的测试工作就显得更加困难。系统测试作为软件开发的重要环节,就越来越受到人们的重视。测试按照典型的软件工程理论分为单元测试、集成测试、系统测试等,在整个测试中,采用了白盒测试和黑盒测试相结合的方法。
6.4.1模块测试
⑴登录模块测试
数据库中有一个正确的用户名和密码,是admin和admin。当输入一切正常的时候便会进入系统;只是输入用户名或密码,便会提示;用户名与密码不匹配便不会进入系统。
用例1:正确的用户名和密码 预测:进入系统
用例2:空的用户名 预测:提示输入用户名
用例3;正确用户名但是空密码 预测:提示输入密码
用例4:正确用户名但是密码错误 预测:登录失败,请输入正确的用户名和密码
当用户输入的用户名或密码错误是系统会弹出到出错窗体并提示“您输入的用户名或密码错误”,用户点击确定,系统会重新返回登陆页面,其中错误信息提示页面如图6.3所示:

               图6.3登录出错提示窗
⑵更改密码模块

用户登录系统后可对自己的登录密码进行更改,更改过程要求用户输入两次新密码,两次输入的新密码不一致将无法执行密码更新操作,系统会给出相应的提示,其显示页面如图6.4。

图6.4 更改密码错误提示页面
6.4.2 集成测试
把经过单元测试的模块放在一起形成一个子系统并对它进行测试用于检验模块相互间的协调和通信,这里主要对图书管理员功能系统进行了测试,经过检验其功能均得以顺利实现,下图为管理员操作的新书订购模块成功运行界面如图6.5:

图6.5新书订购子系统功能测试截图
把经过测试的子系统装配成一个完整的系统进行测试,经过黑盒测试于白盒测试相结合的方式,对整个系统的各个功能模块进行了测试,并调试改正其中的设计和编码错误,经过这个环节的操作整个系统的功能基本实现成功运行。
6.4.3 验收测试
在进行了以上的测试工作后,将整个软件系统作为单一的实体进行测试,测试内容与系统测试基本类似,但它是在用户积极参与下进行的,此测试过程主要使用实际数据,进行测试,验证测试的目的是验证系统确实能够满足用户的需求,经过这个环节的实际数据测试,系统的各个功能实现都达到了系统需求设计的要求。

7总结与展望
用Java语言的优势,实现图书管理的电子化,使系统的管理维护更加方便、灵活,工作效率得到提高,出错几率大大减低。
图书馆工作人员能够实现方便的对图书进行查询,方便的进行读者借阅情况查询,方便的进行借书还书处理等,便捷的对图书信息进行添加、修改、删除,分类管理等操作,对读者信息进行相关添加,修改,分类管理等操作。系统管理员可以对图书馆信息进行修改更新操作,对系统用户进行添加、修改、删除、权限设置等操作,对图书馆的办证参数进行修改维护等操作功能。
本系统只对传统书籍进行了最基本的管理,随着计算机技术的飞速发展,应将各个图书馆的图书进行联网交流,使读者可以远程查询图书馆的藏书等信息,还应开发对电子书的管理,形成网上图书资源共享平台,使读者可以在线阅读电子书资料,并设置用户权限,使管理员可以上传图书资料信息,高级用户可以下载网上电子书资源,从而实现信息资源最大化被共享。

参考文献
[1] David Lip Piatt.Traditional ,Distance and Virtual: an exploration of concepts. International Workshop on Distance Learning and Virtual Campus.2000,40(3):104-113
[2] Luo Jian.Optimal Concurrent Control of Database System. Journal of Systems Science and Systems Engineering.2000,9(1):119-124
[3] LU Jingping, HE Yulin. A web product data management system based on Simple Object Access Protocol. Journal of Chongqing University-Eng. Ed.2003,2(1):57-61
[4] 文东,赵俊岚.数据库系统开发基础与项目实训-基于SQLServer2005.北京:中国人民大学出版社,2009.49-227
[5] 曲培新.Java项目开发案例精粹.北京:电子工业出版社,2010.1-40
[6] 明日科技.Java项目案例分析.北京:清华大学出版社,2012.297-320
[7] 钱乐秋,赵文耕.软件工程.北京:清华大学出版社,2007.1-61
[8] 刘京华等编著. Java Web整合开发王者归来. 北京:清华大学出版社,2010:480-532

致谢辞
大学四年的时间,感谢山东科技大学各位老师对我的悉心教导,感谢他们帮助我顺利度过了大学四年最重要的时光,是他们让我懂得了好多做人的道理。治学先做人,在以后的工作和学习中我会时刻铭记老师的教诲,不辜负老师的希望,做对社会有用的人。
感谢本次毕业设计的指导教师鲁法明老师,同时感谢在毕业设计过程中给予我大力支持的各位老师和同学。

附录 1 英文原文
Graphical User Interfaces
A fundamental design guideline is “Make simple things easy, and difficult things possible.”
The original design goal of the graphical user interface (GUI) library in Java l.o was to allow the programmer to build a GUI that looks good on all platforms. That goal was not achieved. Instead, the Java l.o Abstract Windowing Toolkit (AWT) produced a GUI that looked equally mediocre on all systems. In addition, it was restrictive; you could use only four fonts and you couldn’t access any of the more sophisticated GUI elements that exist in your operating system. The Java 1.0 AWT programming model was also awkward and non-object-oriented. A student in one of my seminars (who had been at Sun during the creation of Java) explained why: The original AWT had been conceived, designed, and implemented in a month. Certainly a marvel of productivity, and also an object lesson in why design is important.
The situation improved with the Java 1.1 AWT event model, which takes a much clearer, object-oriented approach, along with the addition of JavaBeans, a component programming model that is oriented toward the easy creation of visual programming environments. Java 2 (JDK 1.2) finished the transformation away from the old Java 1.0 AWT by essentially replacing everything with the Java Foundation Classes (JFC), the GUI portion of which is called “Swing.” These are a rich set of easy-to-use, easy-to-understand JavaBeans that can be dragged and dropped (as well as hand programmed) to create a reasonable GUI. The “revision 3” rule of the software industry (a product isn’t good until revision 3) seems to hold true with programming languages as well.
This chapter introduces the modern Java Swing library and makes the reasonable assumption that Swing is Sun’s final destination GUI library for Java.2 If for some reason you need to use the original “old” AWT (because you’re supporting old code or you have browser limitations), you can find that introduction in the 1st edition of this book, downloadable at www.MindView.net. Note that some AWT components remain in Java, and in some situations you must use them.
Please be aware that this is not a comprehensive glossary of either all the Swing components or all the methods for the described classes. What you see here is intended to be a simple introduction. The Swing library is vast, and the goal of this chapter is only to get you started with the essentials and comfortable with the concepts. If you need to do more than what you see here, then Swing can probably give you what you want if you’re willing to do the research.
I assume here that you have downloaded and installed the JDK documentation from http://java.sun.com and will browse the javax.swing classes in that documentation to see the full details and methods of the Swing library. You can also search the Web, but the best place to start is Sun’s own Swing Tutorial athttp://java.sun.com/docs/books/tutorial/uiswing
There are numerous (rather thick) books dedicated solely to Swing, and you’ll want to go to those if you need more depth, or if you want to modify the default Swing behavior.
As you learn about Swing, you’ll discover:

  1. Swing is a much improved programming model compared to many other languages and development environments (not to suggest that it’s perfect, but a step forward on the path). JavaBeans (introduced toward the end of this chapter) is the framework for that library.
  2. “GUI builders” (visual programming environments) are a de rigueur aspect of a complete Java development environment. JavaBeans and Swing allow the GUI builder to write code for you as you place components onto forms using graphical tools. This rapidly speeds development during GUI building, and also allows for greater experimentation and thus the ability to try out more designs and presumably come up with better ones.
  3. Because Swing is reasonably straightforward, even if you do use a GUI builder rather than coding by hand, the resulting code should still be comprehensible. This solves a big problem with GUI builders from the past, which could easily generate unreadable code.
    Swing contains all the components that you expect to see in a modern UI: everything from buttons that contain pictures to trees and tables. It’s a big library, but it’s designed to have appropriate complexity for the task at hand; if something is simple, you don’t have to write much code, but as you try to do more complex things, your code becomes proportionally more complex.
    Much of what you’ll like about Swing might be called “orthogonality of use.” That is, once you pick up the general ideas about the library, you can usually apply them everywhere. Primarily because of the standard naming conventions, while I was writing these examples I could usually guess successfully at the method names. This is certainly a hallmark of good library design. In addition, you can generally plug components into other components and things will work correctly.
    Keyboard navigation is automatic; you can run a Swing application without using the mouse, and this doesn’t require any extra programming. Scrolling support is effortless; you simply wrap your component in a JScrollPane as you add it to your form. Features such as tool tips typically require a single line of code to use.
    For portability, Swing is written entirely in Java.
    Swing also supports a rather radical feature called “pluggable look and feel,” which means that the appearance of the UI can be dynamically changed to suit the expectations of users working under different platforms and operating systems. It’s even possible (albeit difficult) to invent your own look and feel. You can find some of these on the Web.3
    Despite all of its positive aspects, Swing is not for everyone nor has it solved all the user interface problems that its designers intended. At the end of the chapter, we’ll look at two alternative solutions to Swing: the IBM-sponsored SWT, developed for the Eclipse editor but freely available as an open-source, standalone GUI library, and Macromedia’s Flex tool for developing Flash client-side front ends for Web applications.
    If you’ve programmed with graphical user interface (GUI) libraries in the past 10 years or so, you have likely come across the model-view-controller (MVC) design. MVC was first introduced by Trygve Reenskaug, a Smalltalk developer at the Xerox Palo Alto Research Center in 1979, and helps to decouple data access and business logic from the manner in which it is displayed to the user. More precisely, MVC can be broken down into three elements:
    • Model - The model represents data and the rules that govern access to and updates of this data. In enterprise software, a model often serves as a software approximation of a real-world process.
    • View - The view renders the contents of a model. It specifies exactly how the model data should be presented. If the model data changes, the view must update its presentation as needed. This can be achieved by using a push model, in which the view registers itself with the model for change notifications, or a pull model, in which the view is responsible for calling the model when it needs to retrieve the most current data.
    • Controller - The controller translates the user’s interactions with the view into actions that the model will perform. In a stand-alone GUI client, user interactions could be button clicks or menu selections, whereas in an enterprise web application, they appear as GET and POST HTTP requests. The view registers as a listener on the model. Any changes to the underlying data of the model immediately result in a broadcast change notification, which the view receives. This is an example of the push model described earlier. Note that the model is not aware of the view or the controller – it simply broadcasts change notifications to all interested listeners.
  4. The controller is bound to the view. This typically means that any user actions that are performed on the view will invoke a registered listener method in the controller class.
  5. The controller is given a reference to the underlying model.
    Once a user interacts with the view, the following actions occur:
  6. The view recognizes that a GUI action – for example, pushing a button or dragging a scroll bar – has occurred, using a listener method that is registered to be called when such an action occurs.
  7. The view calls the appropriate method on the controller.
  8. The controller accesses the model, possibly updating it in a way appropriate to the user’s action.
  9. If the model has been altered, it notifies interested listeners, such as the view, of the change. In some architectures, the controller may also be responsible for updating the view. This is common in Java technology-based enterprise applications
    As this article mentioned earlier, the model does not carry a reference to the view but instead uses an event-notification model to notify interested parties of a change. One of the consequences of this powerful design is that the many views can have the same underlying model. When a change in the data model occurs, each view is notified by a property change event and can update itself accordingly.
    Modifying the MVC Design
    A more recent implementation of the MVC design places the controller between the model and the view.
    The primary difference between this design and the more traditional version of MVC is that the notifications of state changes in model objects are communicated to the view through the controller. Hence, the controller mediates the flow of data between model and view objects in both directions. View objects, as always, use the controller to translate user actions into property updates on the model. In addition, changes in model state are communicated to view objects through an application’s controller objects.
    Thus, when all three components are instantiated, the view and the model will both register with the controller. Once a user interacts with the view, the events are nearly identical:
  10. The view recognizes that a GUI action – for example, pushing a button or dragging a scroll bar – has occurred, using a listener method that is registered to be called when such an action occurs.
  11. The view calls the appropriate method on the controller.
  12. The controller accesses the model, possibly updating it in a way appropriate to the user’s action.
  13. If the model has been altered, it notifies interested listeners of the change. However, in this case, the change is sent to the controller.
    Why adopt this design? Using this modified MVC helps to more completely decouple the model from the view. In this case, the controller can dictate the model properties that it expects to find in one or more models registered with the controller. In addition, it can also provide the methods that effect the model’s property changes for one or more views that are registered with it.
    Using the Modified MVC
    This section of the article shows you how to put this design into practice, starting with the model. Suppose that you want to paint some text using a simple display model with five properties. The Controller
    Between the model and view lies the controller. First, take a look at the code for the abstract controller superclass. The AbstractController class contains two ArrayList objects, which are used to keep track of the models and views that are registered. Note that whenever a model is registered, the controller also registers itself as a property change listener on the model. This way, whenever a model changes its state, the propertyChange() method is called and the controller will pass this event on to the appropriate views.
    The final method, setModelProperty(), employs some magic to get its work done. In order to keep the models completely decoupled from the controller, the code samples in this article have employed the Java Reflection API. In this case, when this method is called with the desired property name, you hunt through the registered models to determine which one contains the appropriate method. Once you find it, you invoke the method using the new value. If the method is not called, the getMethod() will throw a NoSuchMethodException, which the exception handler ignores, allowing the for- loop to continue.
    The View
    This example will have two views displaying the data from the model: a property-editor view and a graphical page view. Both of these are implementations of a JPanel, inserted into either a JDialog or JFrame. The dialog box allows the user to update the values of the model, and the frame panel simply reflects the changes as the final textual display. The author of this article built this example using the NetBeans Swing GUI Builder, formerly referred to as Project Matisse, to design the GUI forms.
    If you’re using the NetBeans IDE, this practice is highly recommended.
    Again, this code sample omits portions of the code that are similar to the sections shown.
    Issues With Application Design
    Once the application is up and running, you immediately run into a problem. Consider the following chain of events:
  14. One of the Swing components in the view receives a change, presumably from the user action.
  15. The appropriate controller method is called.
  16. The model is updated. It notifies the controller of its property change.
  17. The view receives a change event from the controller and attempts to reset the value of the appropriate Swing components.
  18. The appropriate controller method is called, and the model is updated again.
    At this point, any of three different scenarios can occur, depending on what Swing component you use and how robust your model is.
    • The Swing component that prompted the initial change refuses to update itself the second time, noting that its property state cannot be updated again while it is in the process of notifying listeners of the initial state change. This primarily occurs when you use Swing text components.
    • The model notes that the value of the second update matches that of the first, its current value, and refuses to send a change notification. This is always a safe programming practice, and it automatically occurs if you use the PropertyChangeSupport class provided in the java.beans package. However, it does not keep the model from receiving a redundant update.
    • No safeguards are in place on either the model or the Swing component, and the program enters an infinite loop.
    This issue occurs because the Swing components are autonomous. For example, what happens if the user presses the up arrow of the JSpinner component in PropertiesViewPanel, incrementing the spinner’s value by one? After the value is updated, a GUI event listener method that is listening for value changes is called, opacitySpinnerStateChanged(), which in turn calls the controller and then updates the appropriate property in the model.
    With a traditional MVC design, the view would still contain the previous value, and the change in the model would update the view to the current value. However, there is no need to update the Swing component because it has already reset itself to the correct value – it did so before it even passed an event to the controller.
    How do you get around this? One way is to write a mechanism that tells the model or the controller not to propagate a change notification under these circumstances, but this is not a good idea. Remember that more than one view may be listening for changes on the model. If you shut down the change notification for the model, no other listeners, including other views, will be notified of the change. In addition, other components in the same view may rely on the property change notification, with a slider and spinner combination, for example.
    Ideally, each Swing component would be aware of its current value and the value that the view is trying to set it to. If they match, no change notifications will be sent. However, some Swing components include this logic, and others do not. One possible solution is to check the incoming changed value of the model against the current value stored in the Swing component. If they are identical, there is no need to reset the value of the Swing component.
    Common Swing Component Listeners
    As this article has shown throughout, part of the initialization of each delegate or controller requires you to subscribe to various Swing component events. However, individual Swing components can often generate multiple event types. Table 1 presents some common listener methods.

附录 2 中文译文
图形用户接口
一个基本的设计方针是“简单的事情变得容易,困难的事情成为可能。”
劳在Java的图形用户界面(GUI)库原设计目标是允许程序员建立一个GUI ,在所有平台上看起来好。这一目标没有实现。相反,Java的罗湖抽象窗口工具包(AWT )产生一个GUI,看着所有系统上同样表现平平。此外,它是限制性的,你可以用四种字体,你不能访问任何更复杂的GUI元素,在你的操作系统存在。也尴尬和非面向对象的Java 1.0 AWT编程模型。一个学生在我的一个研讨会(曾在Sun公司一直在创造Java的)解释原因:原来的AWT已经构思,设计,并在一个月内实施。一定的生产力的奇迹,也是为什么设计对象的教训是非常重要的。
Java 1.1 AWT的事件模型,这需要一个更清晰的,面向对象的方法的JavaBeans组件的编程模型是面向可视化编程环境容易创造此外,情况有所好转。的Java 2( JDK 1.2 ) ,基本上取代Java基础类(JFC) ,被称为GUI部分的所有“摇摆完成了转型。”从旧的Java 1.0 AWT的这是一个易于使用的一整套丰富,易于理解的JavaBeans ,可以拖动和下降(以及手工编程) ,以建立一个合理的GUI 。 “第三次修订版”的软件产业规则(一个产品是不是良好,直到第三次修订版) ,似乎与编程语言也是如此。
本章介绍了现代的Java Swing库,使得Swing是Sun公司的最终目的地的GUI库,为Java.2合理的假设,如果你有一些原因,因为你支持旧的代码,你需要使用原有的“老”的AWT (或浏览器的限制) ,你可以找到介绍,在这本书的第一版在www.MindView.net下载。请注意,一些AWT组件保持在Java中,并在某些情况下,你必须使用他们。
请注意,这是不是所有的Swing组件或描述类的所有方法的综合词汇。你在这里看到的是一个简单的介绍。 Swing库是巨大的,本章的目的是只让你的要领和舒适的概念开始。如果你需要做的比你在这里看到,那么Swing可以可能会给你想要的东西,如果你愿意做研究。
在这里,我假设您已经下载并安装JDK文档从http://java.sun.com和浏览该文件的javax.swing类Swing库的全部细节和方法。您也可以在网上搜索,但最好的地方开始,是Sun公司自己的Swing教程http://java.sun.com/docs/books/tutorial/uiswing。
有许多(而厚)专门到Swing的书,你要到那些如果您需要更深入,或者如果你想修改默认的Swing行为。
正如你关于Swing学习,你会发现:
1.Swing是一个大为改善的编程模型相比,许多其他语言和开发环境(不认为它是完美的,但前进道路上的一个步骤) 。 JavaBeans的朝着结束本章介绍该库的框架。
2.“ GUI构建器” (可视化编程环境)是一个平常的一个完整的Java开发环境方面。 JavaBeans和Swing的GUI生成器为你写的代码,你使用图形化工具的形式放置到组件。
因为Swing是相当简单,即使你使用GUI构建器,而不是通过手工编码,生成的代码仍然应该理解。这解决了一个大问题,从过去,这很容易产生不可读的代码的GUI建设者。
Swing包含所有组件,您会看到在一个现代的UI :一切从树木和表包含图片按钮。这是大的一个图书馆,但它在手头的任务适当的复杂性;如果事情是简单的,你不要不有写很多代码,但作为你尝试做更复杂的事情,你的代码变得比例更复杂。
你会喜欢关于Swing的大部分可能被称为“正交使用。 ”也就是说,一旦你拿起对图书馆的总体思路,你通常可以申请他们无处不在。这主要是因为标准的命名约定,当我在写这些例子,我通常可以猜测成功的方法名。这当然是一个好的库设计的标志。此外,您通常可以插入到其他组件和事物的组成部分,将正常工作。
键盘导航是自动的,可以不使用鼠标的情况下运行的Swing应用程序,这并不需要任何额外的编程。滚动支持是毫不费力;你只是包裹在一个JScrollPane组件,你把它添加到您的表单。如工具提示功能,通常需要使用一个单一的代码行。
可移植性, Swing是完全用Java编写的。
Swing也支持一个相当激进的功能,称为“可插拔的外观和感觉,”这意味着用户界面的外观,可以动态改变,以适应不同的平台和操作系统下工作的用户的期望。它甚至有可能(虽然很难)发明自己的外观和感觉。你可以找到这些Web。
尽管所有的积极方面,Swing是并不适合每一个人,也没有解决所有的用户界面,其设计意图的问题。在本章的结尾,我们来看看两个备选方案摆动: IBM赞助的SWT的Eclipse编辑器,但可以作为一个开放源码的,独立的GUI库,以及Macromedia的Flash客户端开发的Flex工具开发端前端Web应用程序。
如果你编程图形用户界面(GUI)在过去10年左右的图书馆,你有可能遇到的模型 - 视图 - 控制器(MVC)设计。首先介绍了MVC的是,在施乐帕洛阿尔托研究中心在1979年的Smalltalk开发特里夫Reenskaug,有助于分离数据访问和业务逻辑,从它被显示给用户的方式。更确切地说,MVC的可以分解成三个要素:
•模型 - 模型表示数据和管理这些数据的访问和更新规则。在企业软件,模型往往是作为一个真正的世界的过程中软件逼近。
•查看 - 视图模型呈现的内容。它指定模型中的数据应提交究竟如何。如果模型数据的变化,认为必须更新其介绍需要。这可以通过使用推模型,在该视图注册变更通知,或拉模型,在其中的观点是负责调用模型时,它需要检索的最新数据模型本身。
•控制器 - 控制器转换到该模型将执行的行动的看法与用户的交互。在一个独立的GUI客户端,用户交互可能是点击按钮或菜单选择,而在企业Web应用程序,他们似乎GET和POST HTTP请求。视图注册为模型的侦听器。模型基础数据的任何改变立即导致广播变更通知,认为收到的。这是前面所述的推模型的例子。请注意,该模型是不知道的视图或控制器 - 它只是通知所有感兴趣的听众广播的变化。
1 该控制器绑定到视图。这通常意味着,任何用户在视图上执行的操作将调用一个控制器类中注册的监听器方法。
2 控制器底层模型的参考。
一旦用户与视图的交互,将发生以下操作:
1 的观点认识到,一个GUI操作 - 例如,按下一个按钮或拖动滚动条 - 已经发生,使用一个监听器的方法,发生这样的行动时,被称为注册。
2 视图控制器上调用适当的方法。
3 控制器的访问模型,在适当的方式向用户的行动,它可能更新。
4 如果模型已经改变,它会通知有兴趣的听众,如视图的变化。在某些架构中,控制器也可能是负责更新视图。这是常见的,基于Java技术的企业应用。
正如本文前面提到的,该模型不进行视图的引用,而是使用事件通知模型改变通知有关方面。这个强大的设计的后果之一是,很多意见可以有相同的底层模型。在数据模型发生变化时,每个视图属性更改事件通知,并可以相应地更新自己。
修改MVC设计一个更近的实施放在MVC设计模型和视图之间的控制器。
MVC的设计和更传统的版本之间的主要区别在于,通过控制器的看法传达给模型对象的状态变化通知。因此,控制器的中介模型,并在两个方向查看对象之间的数据流。查看对象,一如既往地使用控制器转化为模型的属性更新用户操作。此外,在模型状态的变化传达给观看对象通过应用程序的控制器对象。
因此,当所有三个组件被实例化,视图和模型都将登记与控制器。一旦用户与视图进行交互,这些事件几乎是相同的:
1 的观点认识到,一个GUI操作 - 例如,按下一个按钮或拖动滚动条 - 已经发生,使用一个监听器的方法,发生这样的行动时,被称为注册。
2 视图控制器上调用适当的方法。
3 控制器的访问模型,在适当的方式向用户的行动,它可能更新。
4 如果模型已经改变,它的变化通知有兴趣的听众。然而,在这种情况下,改变被发送到控制器。
为什么要采取这样的设计呢?使用这种改良的MVC有助于更彻底脱钩视图模型。在这种情况下,该控制器可以决定模型的性质,它希望能够找到一个或多个模型控制器注册。此外,它也可以提供的方法,效果模型的属性更改一个或多个登记的意见。
假设你想画一些文字,用五个属性的一个简单的显示模式。控制器在于模型和视图之间的控制器。首先,看看抽象控制器的超代码。 AbstractController的类包含两个ArrayList对象,这是用来保持跟踪注册的模型和意见。请注意,只要注册一个模型,控制器也寄存器模型上的属性更改侦听器本身。这样,每当一个模型改变其状态,propertyChange()方法被称为控制器将通过适当的意见,此事件。最后的方法,setModelProperty(),采用了一些神奇的完成它的工作。为了保持完全脱钩,从控制器模式,在这篇文章中的代码示例使用Java反射API。在这种情况下,与所需的属性名调用此方法时,通过注册的模型,以确定哪一个包含适当的方法,你打猎。一旦你找到它,你调用的方法,使用新的价值。如果方法不叫,getMethod()会抛出一个NoSuchMethodException,异常处理程序将忽略的,允许继续for循环。检视这个例子中,将有两方面的意见,从模型数据显示:属性编辑器视图和图形的页面视图。这些都是实现一个JPanel,插入到一个JDialog或JFrame的。该对话框允许用户在更新模型值,帧面板,只是反映了作为最后的文本显示的变化。本文作者建立这个例子中,使用了NetBeans的Swing GUI Builder中,以前称为项目马蒂斯,设计的图形用户界面形式。
如果你使用NetBeans IDE,这种做法是极力推荐。
再次,此代码示例省略部分代码是类似的部分所示。
问题与应用设计一旦应用程序是建立和运行,你马上遇到一个问题。考虑以下的事件链:
1 视图中的Swing组件之一,收到了变化,大概从用户操作。
2 相应的控制器方法被调用。
3 该模型被更新。通知其财产的变化控制器。
4 视图接收来自控制器的变化,并尝试以适当的Swing组件的值重置事件。
5 相应的控制器方法被调用,并再次更新模型。
在这一点上,任何三种不同的情况下可以发生,这取决于你使用Swing组件和你的模型是多么强大。
•促使初步改变了拒绝更新自己的第二次,并指出其财产状态,不能被再次更新,而在过程中的初始状态变化通知听众的Swing组件。这主要发生当您使用Swing文本组件。
该模型指出,第一,其当前值,第二次更新的值匹配,拒绝发送变更通知。这始终是一个安全的编程实践,它会自动出现,如果你使用java.beans包中提供的PropertyChangeSupport类。然而,它不继续接收冗余更新模型。
•无保障到位模型或Swing组件,程序进入一个无限循环。
发生此问题,因为Swing组件是自主的。如果用户按向上箭头的JSpinner的PropertiesViewPanel的组件,微调器的值加1,例如,会发生什么?值更新后,被称为一个GUI事件监听器的方法,为价值变动听,opacitySpinnerStateChanged(),这反过来又调用控制器,然后更新模型中的相应的属性。
与传统的MVC设计视图仍然包含以前的值,模型中的变化,将当前值更新视图。然而,有没有需要更新Swing组件,因为它已自行复位,以正确的价值 - 它这样做之前,它甚至到控制器通过事件。
你如何解决这个问题?一种方式是写一个机制,告诉模型或控制器不传播在这种情况下,更改通知,但是,这不是一个好主意。请记住,多个视图可用于监听模式上的变化。如果您关闭该模型的更改通知,没有其他的听众,包括其他的意见,将通知的变化。此外,在同一视图中的其他组件可以依赖的属性更改通知,滑块和微调的组合,例如。理想的情况下,每个Swing组件将其目前的价值和价值的看法是,试图将其设置为知道。如果它们匹配,没有变更通知将被发送。然而,一些Swing组件包括这个逻辑,和别人不一样。一种可能的解决方案是在Swing组件中存储的电流值核对传入的改变模型的价值。如果它们是相同的,有没有必要,重置价值的Swing组件。

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

广西千灵通网络科技有限公司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值