图书管理系统

Posted 秋风&

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图书管理系统相关的知识,希望对你有一定的参考价值。

目录

一、需求分析

1、项目功能结构图

2、 分析

3、封装的方法:

二、使用对象序列化流需要注意的事项

1、序列化追加对象产生多个头

2、序列化集合在使用集合前需要先加载文件内容到集合

3、实体类需要实现Serializable接口以及指定serialVersionUID的值

三、项目实现

1、结构分析

2、代码实现

四、项目心得

1、remove与delete的区别

2、return与break的区别

3、传参的使用

 4、运行过程


一、需求分析

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、系统部署

欢迎大家持续关注我哟~

以上是关于图书管理系统的主要内容,如果未能解决你的问题,请参考以下文章

用java编写一个 图书馆图书借阅管理系统

采用JAVA设计一个小型图书管理程序(只要增删查改)

java图书馆管理系统论文

网上书店管理系统项目Java数据库编程实战

java初学者用swing+集合做图书管理系统 要求有登陆 注册 图书管理 管理员管理(增删改查)

Java版本:图书管理系统