图书管理系统
Posted 秋风&
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图书管理系统相关的知识,希望对你有一定的参考价值。
目录
3、实体类需要实现Serializable接口以及指定serialVersionUID的值
一、需求分析
1、项目功能结构图
2、 分析
图书管理系统分为五个模块每个模块下包含了增删改查的功能,主要使用IO流实现,可以把每个实体类看作一个对象,把这个对象存储到一个集合里进行操作,然后再把这个集合作为一个对象进行序列化,这样便实现了多个对象的数据存储。在需要使用这些数据时,再把文件里的内容(集合)反序列化出来,通过遍历集合得到文件中的数据,整个图书馆里系统均在使用对象序列化,所以我们可以把序列化以及反序列化封装成方法,直接调用,大大提高了代码的复用性和效率。
3、封装的方法:
序列化:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(array);
oos.close();
反序列化:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object obj = ois.readObject();
二、使用对象序列化流需要注意的事项
1、序列化追加对象产生多个头
使用对象序列化流时如果需要序列化多个对象,那么就要考虑到追加,然而Java默认的对象序列化是每次写入对象都会写入一个头aced 0005(占4个字节),如果追加序列化就会导致出现多个头结点,从而出现异常!所以如果要实现对象的追加,就只能出现一个头,解决方法就是先判断文件是否存在且为空。如果不存在,就先创建文件,当文件内容为空就正常写入第一个对象,也写入了头aced 0005。追加的时候就需要判断文件不为空时,要把那个4个字节的头aced 0005截取掉,然后在把对象写入到文件,这样就实现了对象序列化的追加。
但是这种方法每一次都需要进行复杂的去头操作,显然太繁琐了,在需求分析时提到用一个集合来存储对象,再把集合作为一个大的对象进行序列化,这样巧妙的避免了序列化追加对象所产生多个头的问题。并且在集合里进行操作更便于我们提取数据以及存储数据。鉴于图书管理系统是使用IO流知识点来实现的,那么对象序列化流就正好能满足我们的要求,整个图书管理系统贯穿了对象序列化和对象反序列化,所有数据的存储以及提取都离不开序列化,因此,我们把对象序列化与反序列化封装成为方法。
2、序列化集合在使用集合前需要先加载文件内容到集合
集合存储了对象的数据,在使用集合时,一开始集合里面是没有对象数据的,所以每次使用集合前都必须先把文件内容反序列化到集合,这个时候集合里面才有了数据,而这些数据正式通过集合添加的对象序列化到文件中的,其实理解起来就是,把集合序列化到文件中了,就相当于集合把数据借给了文件,那么集合就没有这些数据了,下次需要通过集合使用数据时,就需要文件把数据先还给集合,这时集合才有了数据。同时需要注意在反序列化文件前要确保文件存在并且不为空,如果反序列化一个空文件会出现异常。
//当文件存在且文件内容为空时先序列化
if (file.exists() && file.length() == 0)
ReaderType rt = new ReaderType(typeid, typename, limit, maxborrownum);
array.add(rt);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(array);
oos.close();
System.out.println("添加成功!");
else
//反序列化文件内容加载到集合中
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object obj = ois.readObject();
ArrayList<ReaderType> array = (ArrayList<ReaderType>) obj;
boolean idflag = true;
for (ReaderType rt : array)
if (typeid.equals(rt.getTypeid()))
System.out.println("此读者类型编号已存在,请重新添加!");
idflag = false;
new SelectReaderType().addReaderType();
if (idflag)
ReaderType rt = new ReaderType(typeid, typename, limit, maxborrownum);
array.add(rt);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(array);
oos.close();
System.out.println("添加成功!");
3、实体类需要实现Serializable接口以及指定serialVersionUID的值
在Java中只有实现了Serializable接口后, JVM才会在底层帮我们实现序列化和反序列化,如果不实现serializable接口则Java虚拟机则不会实现序列化。同时需要指定serialVersionUID的值。在用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据就会出问题,会抛出InvalidClassException异常。这是因为如果不显示指定serialVersionUID, JVM在序列化时会根据属性自动生成一个serialVersionUID, 然后与属性一起序列化, 再进行持久化或网络传输. 在反序列化时, JVM会再根据属性自动生成一个新版serialVersionUID, 然后将这个新版serialVersionUID与序列化时生成的旧版serialVersionUID进行比较, 如果相同则反序列化成功, 否则报错。而当我们给对象所属的类加一个serialVersionUID,即便更改了文件的内容,只要serialVersionUID相同,JVM进行比较时就不会报错。
public class Book implements Serializable
private static final long serialVersionUID = 42L;
三、项目实现
1、结构分析
在弄清楚用什么方法去完成整个项目后,应该着手整个项目的逻辑结构,明白具体要写什么,从哪开始写,每个模块之间的联系。
流程图:
如图所示,整个图书管理项目都在进行增删改查,而增删改查的数据来源以及存储的地方,我们将使用对象序列化来实现。放在最前面的当然是登录注册功能,而其中,用户管理模块与其它四个模块是独立的,所以我们先从用户管理开始,而图书借阅管理涉及到了图书类型、读者类型、罚金标准、读者、图书这些实体,所以图书借阅应该放在最后写;读者,图书,又需要确定读者类型与图书类型,故而,基础信息维护模块应在用户管理后就要设置好。这样得到整个逻辑顺序为登录注册--用户管理--基础信息维护--读者信息管理--图书信息管理--图书借阅管理--退出系统。如此一来整个图书管理系统的流程就清晰明了了。
2、代码实现
整个项目的代码其实大同小异,但是都数据进行增删改查,我就不一一列举了,只演示一部分功能的代码了。
图书类型的设置代码演示:
//创建集合对象,指定文件路径
ArrayList<BookType> array = new ArrayList<>();
File file = new File("ItemTwo\\\\src\\\\Data\\\\booktype");
图书类型的添加:
//添加图书类型
public void addBookType() throws InterruptedException, IOException, ClassNotFoundException
TSUtility.loadSpecialEffects();
System.out.println("开始添加图书类型!");
System.out.println("***************");
System.out.println("请输入图书类型编号!");
String typeid = TSUtility.readKeyBoard(12, false);
System.out.println("请输入图书类型名称!");
String typename = TSUtility.readKeyBoard(12, false);
//当文件存在且文件内容为空时先序列化
if (file.exists() && file.length() == 0)
BookType bt = new BookType(typeid, typename);
array.add(bt);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(array);
oos.close();
System.out.println("添加成功!");
else
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object obj = ois.readObject();
ArrayList<BookType> array = (ArrayList<BookType>) obj;
boolean idflag = true;
for (BookType bt : array)
if (typeid.equals(bt.getTypeid()))
System.out.println("此图书类型编号已存在,请重新添加!");
idflag = false;
new SelectBookType().addBookType();
if (idflag)
BookType bt = new BookType(typeid, typename);
array.add(bt);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(array);
oos.close();
System.out.println("添加成功!");
图书类型的删除:
//删除指定类型编号的图书类型
public void deleteBookType() throws IOException, ClassNotFoundException
System.out.println("开始图书类型的删除!");
System.out.println("请输入需要删除的图书类别编号!");
String typeid = TSUtility.readKeyBoard(12, false);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object obj = ois.readObject();
ArrayList<BookType> array = (ArrayList<BookType>) obj;
boolean delete = true;
for (BookType bt : array)
if (typeid.equals(bt.getTypeid()))
array.remove(bt);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(array);
oos.close();
System.out.println("删除成功!");
delete = false;
break;
if (delete)
System.out.println("无此图书类别编号,请核对后操作!");
图书类型的修改:
//修改指定编号的图书类型信息
public void modifyBookType() throws IOException, ClassNotFoundException
System.out.println("开始图书类型的修改!");
System.out.println("请输入你需要修改的图书类别的编号");
String typeid = TSUtility.readKeyBoard(12, false);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object obj = ois.readObject();
ArrayList<BookType> array = (ArrayList<BookType>) obj;
boolean modify = true;
for (BookType bt : array)
if (typeid.equals(bt.getTypeid()))
System.out.println("请输入你将要修改的图书类别名称!");
String newtypeid = TSUtility.readKeyBoard(6, false);
bt.setTypename(newtypeid);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(array);
oos.close();
modify = false;
System.out.println("修改成功!");
break;
if (modify)
System.out.println("无此图书类别编号,请核对后操作!");
图书类型的查看:
//查询所有图书类型信息
public void allBookType() throws IOException, ClassNotFoundException
//反序列化文件内容
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object obj = ois.readObject();
ArrayList<BookType> array = (ArrayList<BookType>) obj;
for (BookType bt : array)
System.out.println("图书类别编号:" + bt.getTypeid() + ",图书类别:" + bt.getTypename());
//查询指定类型名的图书类型信息
public void appointBookType() throws IOException, ClassNotFoundException
System.out.println("请输入你要查询的图书类别");
String booktype = TSUtility.readKeyBoard(12, false);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object obj = ois.readObject();
ArrayList<BookType> array = (ArrayList<BookType>) obj;
boolean appoint = true;
for (BookType bt : array)
if (booktype.equals(bt.getTypename()))
System.out.println("查询的图书类别信息如下:");
System.out.println("图书类别编号:" + bt.getTypeid() + ",图书类别:" + bt.getTypename());
appoint = false;
break;
if (appoint)
System.out.println("无此图书类别,请核对后操作!");
从这段代码中可以看出其实都是在进行序列化与反序列化,增删改查的实现但是在集合中完成的,数据都是通过文件反序列化到集合,然后遍历集合得到的,遍历时要注意一个地方,应为集合里面存储的是一个对象,所以导致只会判断第一条数据是否满足,而后的数据就会直接进入else里面,那么就不能直接else;而应该把所有满足条件遍历得到在结束,那么要实现查找所有数据后还是没有满足条件的就可以使用一个Flag作为阀门,在遍历时只要有数据满足条件,Flag就变为false,若Flag一直为true就说明所有数据均不满足条件。
四、项目心得
1、remove与delete的区别
在进行集合的删除时发现集合的remove与文件的delete是不一样的,所以特意去查询了一下。
delete()方法主要用在文件操作上,用于删除文件或文件夹,语法如下File file=new File("文件名或目录名");file.delete(); remove()方法:主要用在集合上,对于集合中的元素进行移除。
2、return与break的区别
return;表示结束当前方法。
break;可以使流程跳出switch语句体,也可以用break语句在循环结构终止本层循环体,从而提前结束本层循环。
3、传参的使用
//读取罚金设置文件内容返回罚金标准
public String fine(String typename) throws IOException
//把罚金设置文件的内容加载到集合中
BufferedReader br = new BufferedReader(new FileReader("ItemTwo\\\\src\\\\Data\\\\fine"));
Properties p = new Properties();
p.load(br);
String value;
try
value = p.getProperty(typename);
catch (Exception e)
System.out.println("无此类型的罚金标准");
return null;
br.close();
return value;
//返回读者类型规定的最大可借天数
ReaderType readertype = readertype(readerid);
int limit = Integer.parseInt(readertype.getLimit());
int Intday = (int) day;
//返回读者类型
String typename = readertype.getTypename();
4、运行过程
You work hard all the end ,worthy of the way of the displaced.
图书馆图书管理系统开发前期需求探索
鉴于近期给一个客户开发图书馆图书管理系统,在与客户的合作过程中,遇到了很多问题,总结起来主要是前期需求不明确!因此,本文的目的主要是探讨关于图书管理系统开发前的客户需求调研,只有充分了解了客户的需求,才能做出满意的系统。
一、功能模块需求
1、图书管理:图书管理、新增图书、作者、图书分类、批量导入、条码管理
2、借阅管理:图书借阅、图书归还、图书丢失、借出图书、已还图书、逾期管理等
3、用户管理:借阅人管理、新增、删除,用户类型、班级/职务、借阅卡等
4、申请购书:用户在线提交购书申请、后台审核并回复
5、统计功能:图书采购量、贮藏量、外借量、丢失量、图书价值等数据
二、系统使用便捷性
本项目中客户提出非常重要的两个功能就是:最好能自动录入基础数据;逾期短信提醒;扫码枪录入。无疑,这三个功能也正是系统使用便捷性的最好体现。
先看第一个问题:图书基础数据录入便捷性:经分析目前最经济实用的就是通过第三方api来实现,我们的方案是用户只需输入(扫描)图书的条形码,通过api接口自动拉取书籍信息,然后入库本系统
第二个问题:逾期提醒功能:这个主要是因为逾期还书现象很多,需要实现逾期前短信通知
第三个问题:扫码枪:这个无需多说,绝对是人工输入的绝对替代,错误率低。
三、系统扩展能力
一套好的图书管理系统应该是具备功能拓展接口的!原理大家都懂,现今主流的各类系统都按照模块化的方式进行开发,目的之一就是方便系统功能的拓展,增删功能无需大动干戈,从拓展接口出发快速实现新功能的集成即可。
拓展接口举例:可对接到小程序、对接到APP、对接到自助终端...
四、其他需求
在项目实施、交付使用的过程中,肯定会遇到各种功能需求,需要我们不断的与客户沟通,才能做出更好的图书管理系统!
好了,这就是我们承接的客户项目前期的需求分析,如果您有好的idea,欢迎您与我联系交流。
五、下期预告
1、图书管理系统的界面风格设计
2、具体代码实施
3、填充数据并实战测试
4、系统部署
欢迎大家持续关注我哟~
以上是关于图书管理系统的主要内容,如果未能解决你的问题,请参考以下文章