精华内容
下载资源
问答
  • 检测图书ISBN编号校检位

    千次阅读 2016-08-30 09:45:05
    公司应用要求,扫图书码之后去搜索图书信息,结果无论使用Zbar还是ZXing,都会出来很...国际标准书号(International Standard Book Number),简称ISBN,是专门为识别图书等文献而设计的国际编号。ISO于1972年颁布了I


    公司应用要求,扫图书码之后去搜索图书信息,结果无论使用Zbar还是ZXing,都会出来很多稀奇古怪的数字出来,因此需要手工过滤一下无效ISBN号。于是就有了下文:

    开车,同学们!请抓好扶手,我们先来了解一下ISBN号是什么:

    国际标准书号(International Standard Book Number),简称ISBN,是专门为识别图书等文献而设计的国际编号。ISO于1972年颁布了ISBN国际标准,并在西柏林普鲁士图书馆设立了实施该标准的管理机构---国际ISBN中心。现在,采用ISBN编码系统的出版物有:图书、小册子、缩微出版物、盲文印刷品等。2007年1月1日前,ISBN由10位数字组成,分四个部分:组号(国家、地区、语言的代号),出版者号,书序号和检验码。2007年1月1日起,实行新版ISBN,新版ISBN由13位数字组成,分为5段,即在原来的10位数字前加上3位EAN(欧洲商品编号[1]  )图书产品代码“978”。在联机书目中ISBN可以作为一个检索字段,从而为用户增加了一种检索途径。

    第一组号码是国家代码(State Identifier),最短的是一位数字,最长的达五位数字,大体上兼顾文种、国别和地区。把全世界自愿申请参加国际标准书号体系的国家和地区,划分成若干地区,各有固定的编码:美国所出版的书国家代码为0,1代表英语,使用这两个代码的国家有:澳大利亚、加拿大、爱尔兰、新西兰、波多黎各、南非、英国、美国、津巴布韦等;2代表法语,法国、卢森堡以及比利时、加拿大和瑞士的法语区使用该代码;3代表德语,德国、奥地利和瑞士德语区使用该代码;4是日本出版物的代码;5是俄语系国家出版物的代码;7为中国大陆出版物使用的代码等等。国家领域最长可能为5位数字(如不丹为99936),但相对剩下能使用、分配的位数就较为狭隘。组号分为五个档次,长度为1-5位数字。

    第二组号码段

    第二组号码是出版社代码(Publisher Identifier),由其隶属的国家或地区ISBN中心分配,允许取值范围为2-5位数字。出版社的规模越大,出书越多,其号码就越短。

    第三组号码段

    第三组号码是书序码(Title Identifier)由出版社自己给出,而且每个出版社的书序号是定长的(数字9,减去组号、出版社代码所占的位数,就是书序码的位数)。最短的一位,最长的六位。出版社的规模越大,出书越多,书序码越长(如人民文学出版社的出版社代码为02,书序码即为6位,译林出版社代码5447,书序码即为4位)。

    第四组号码段

    第四组号码是校验码,其数值由前九位数字依次以9~1加权之和并以11为模计算得到。
    四组数字之间应该用连字符( - )连接(如2-02-033598-0)。但是,有些图书馆集成系统不能自动分配连字符,图书馆编目人员也对ISBN的分段方式不甚了解,所以人们经常在书目记录中省略 连字符
    ---->以上摘自百度百科
    敲黑板,划重点了!:
     示范数据:
    9 7 8- 7- 8 1 0 9 0- 0 2 1- ?(?标示 校验位)
    代码位置:

    13 12 11 10 9 8 7 6 5 4 3 2 1 

    除位数1外;所有偶数位的数字代码求和

    取末位数为a。将a乘以3 取末位数为b。
     
    所有奇数位的数字代码求和取末位数为c。

    将b和c相加求和 取末位数为d(因模数为10,所以余数即末位数d)。

    用10减去d即为校验位数值。
    7+7+1+9+0+1 = 25 取末位数为a=5 5*3 = 15 取末位数为b=5 
    9+8+8+0+0+2 = 27 取末位数为c=7 5+7 = 12 
    取末位数为d=2 (余数)10-2= 8 差数为校验位: 8 

    有效的ISBN 是ISBN 978-7-81090-021-8 
    上面是我们公司老同事给我的算法,本人凭借自己优秀的数学功底(括弧笑~),稍稍进行了简化,比如 
    (x%10)*3%10 等效于 x*3%10
    (x%10+y%10)%10 等效 (x+y)%10
    等等~
    于是自己心动,立马敲代码,得出如下结果
    	/**
    	 * @author franer
    	 * @param str_ISBN ISBN numbers
    	 * @return true if ISBN is legal,false otherwise 
    	 * */
    	private static boolean checkISBN(String str_ISBN) {
    		//不满足978开头的13位数字这返回false
    		if (!Pattern.matches("978[0-9]{10}", str_ISBN)) {
    			return false;
    		}
    		int sumOdd = 0;//奇数位总和
    		int sumEvn = 0;//偶数位总和
    		for (int i = 0; i < str_ISBN.length()-1; i++) {
    			if (i%2==0==false) {
    				sumOdd += str_ISBN.charAt(i)-48;//奇数位
    			} else{
    				sumEvn += str_ISBN.charAt(i)-48;//偶数位
    			}
    		}
    		//奇数位总和自乘3
    		sumOdd *= 3;
    		int num13 =  10 - (sumOdd + sumEvn)%10;
    		num13 %= 10;
    		if ((num13+48) == str_ISBN.charAt(str_ISBN.length()-1)) {
    			return true;
    		} else {
    			return false;
    		}
    	}



    展开全文
  • 书柜(编号20110925)

    2011-09-25 23:09:27
    书柜(编号20110925) 《人月神话》 弗雷德里克·布鲁克斯 著. 清华大学出版社 ISBN 7-302-05932-2/TP·3530 附: 写书柜的一封道歉信 亲爱的书柜: 我要说一声对不起!让你荒废了很久,想必你...
    书柜(编号20110925)
    

    《人月神话》     弗雷德里克·布鲁克斯  著.     清华大学出版社    ISBN 7-302-05932-2/TP·3530


    附:
    写给书柜的一封道歉信

    亲爱的书柜:

    我要说一声对不起!让你荒废了很久,想必你对我这个主人已经很不满了吧!都是我的错!我让你跟随自己,结果,你一直孤单地在那边立着,布满了灰尘!虽然你不开口说话,但是你心中一定认定我很残忍吧!这不是我的风格!在我心中一直存在一个梦想,我要让自己的书柜有更多的好书。当然了,让书躺在书柜里睡觉,也是很残忍的事情。这,也非我的风格!所以,我的梦想还有半句没有说完“我要好好地读完书柜里的书”!

    亲爱的书柜,现在你应该开心了吧!我不会,绝对不会再让你一个人在角落里孤单了,再也不会让你布满灰尘了!我会拿很多我喜欢的书陪着你,那些书都曾经走进过我的心里,我也曾经走进过他们的心里!

    亲爱的书柜,你放心,我说过的这些话一定会实现的。虽然现在没有人监督,只能自我监督!自我监督,已经被证明是腐败诞生的温床!那该怎么办呢?好吧!那就让博客来监督我吧!今后看完一本书后,定当出一篇读书笔记。“可行否?”“当然可以!”“好,那就这么说定了!”“君子一言九鼎!绝不打诳语!”

    亲爱的书柜,虽然你是无形的,但是你一直都存在于我心中,永远!所以,我会好好爱护你的!
    展开全文
  • 《程序设计综合训练实践报告》 此项目为图书信息管理系统,是一个采用了mysql+mybatis框架+java编写的maven项目

    一、实验目的

    题目七 图书信息管理系统

    1 功能描述

    设计一个图书信息管理系统,使之具有新建图书信息、显示、插入、删除、查询和排序等功能。

    2 具体设计要求

    图书信息包括:图书编号、书名、作者名、出版单位、出版时间、价格等。

    系统以菜单方式工作:

    ① 图书信息录入(要求图书信息用文件保存)

    ② 图书信息浏览

    ③ 插入图书信息

    ④ 查询(可以有多种查询方式,如按书名查询、按作者名查询、按价格查询等);

    ⑤ 排序(可以按图书编号排序、按书名排序、按出版时间排序、按价格排序等);

    ⑥ 修改图书信息

    ⑦ 删除图书信息

    二、项目概况

    1.总述

    此项目为图书信息管理系统,是一个采用了mysql+mybatis框架+java编写的maven项目

    2. 技术栈选择

    Mysql,mybatis

    3.环境介绍

    数据库:mysql8.0

    框架:mybatis

    项目结构:maven3.0

    语言:Java

    Jdk版本:jdk11.0.5(Jdk8.0以上)

    编写的IDE:IDEA 2020.01

    依赖jar包:
    在这里插入图片描述

    4. 功能概述

    该图书信息管理系统实现了便捷的图书信息管理,利用命令行操作的方式让用户的操作更为简洁。

    本系统提供Sql和noSql两种运行模式。

    Sql模式直接对mysql数据库进行操作,便于数据的持久化和规范化,让数据能够更加便捷高效,同时可以存储大量数据,便于进行大数据的管理,如果你想真正用此系统管理你的信息,建议采用此种模式。

    noSql模式是把数据载入内存中,优点是速度快,但缺点也很明显,在面对大量数据的情况下显得有些力不从心,此模式建议在数据量小的情况下使用。

    两种模式都支持以下功能:

    在这里插入图片描述

    5.功能结构

    在这里插入图片描述

    6.项目文件结构

    在这里插入图片描述

    三、数据结构描述

    1.实体类Book(持久化层)

    在这里插入图片描述

    2.Sql模式下的数据库结构

    在这里插入图片描述

    库名:library

    表名:books

    字段名代表含义数据类型格式
    id图书编号INT主键,PK,not null
    title书名VARCHAR(20)not null
    name作者名VARCHAR(20)not null
    publisher出版商VARCHAR(20)
    time出版时间DATE
    price价格DECIMAL(7,4)

    3.Sql模式下的Mapper映射(接口结构)

    在这里插入图片描述

    4.noSql模式下的数据结构

    采用LinkedList<Book>来维护图书信息
    在这里插入图片描述

    四、程序模块描述

    该项目大致分为两个一级模块,分别在两个java文件中
    在这里插入图片描述

    各个文件内用分别有若干个二级模块

    1.图书信息录入(通过文件录入)模块

    在这里插入图片描述

    2. 图文信息浏览模块

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cjHHTSx8-1592834754185)(media/image13.png)]{width="3.058333333333333in" height="0.25in"}

    3. 插入模块

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijayrnyv-1592834754186)(media/image14.png)]{width="3.3in" height="0.3in"}

    4. 查询模块

    在这里插入图片描述

    其下按查询条件有分为若干个三级模块

    5. 排序模块

    在这里插入图片描述

    其下按排序条件有分为若干个三级模块

    6. 更新模块

    7. 删除模块

    8. 写出模块

    至于各模块的功能,见名知意,在此就不一一赘述了。

    而对于各个模块的返回值和参数,容我卖个关子,此内容将在下个模块中讲解!

    五、主要功能模块的算法流程图

    1.Sql模式下的算法流程(以查找为例)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Do8u8qto-1592834754194)(media/image20.png)]{width="5.763194444444444in" height="6.290972222222222in"}

    2. 各个模块间的连接算法流程

    "套娃"式的连接方式

    何为"套娃"?

    可以理解为类似递归的连接方式。

    与递归有什么不同?

    如果采用递归,就要把低层级的模块套在高层级的模块里。这样子虽然连接了各个模块,达到了类似菜单的效果,但有以下两个较为致命的缺点:

    1. 当运行完一个模块后,该模块就运行结束,无法做到循环操作,这与实验要求不符

    2. 由于该项目是一个系统,各模块间要不断退出重进,循环多次的递归会造成堆栈不断压缩,有堆栈溢出风险

      那我们该如何做呢?

      对于第一个缺点,我采用了一个死循环来解决;对于第二个缺点,我的思路就是把改变模块重复调用的时机和位置,让它既能达到效果,又不会导致堆栈溢出

      基本思路:

      每个函数都有一个整数类型的返回值,只要返回1,就说明该级模块需要退回上一级;返回0则说明不需要,即留在当前模块。

      而是留在当前模块还是返回上一级模块,由该模块(记为模块3)的上一级(记为模块2)控制,如果模块3返回一了,就在模块2的上一级(记为模块1)再次调用模块2,即可做到返回上一层;而如果模块3返回0则在模块2再次循环调用,直至模块返回1
      这样做不仅能实现功能,而且能避免多次"套娃"导致堆栈溢出的风险

      在这里插入图片描述

    六、代码清单

    1.项目结构全览

    在这里插入图片描述

    2. 实体类Book

    ackage com.dreamchaser.domain;
    
    import java.math.BigDecimal;
    import java.util.Date;
    
    /**
     * books
     * 
     * @author 金昊霖
     */
    public class Book {
    
        /** 图书编号 */
        private Integer id;
    
        /** 图书名称 */
        private String title;
    
        /** 作者姓名 */
        private String name;
    
        /** 出版社 */
        private String publisher;
    
        /** 出版时间 */
        private Date time;
    
        /** 价格 */
        private BigDecimal price;
    
        public Book() {
        }
    
        /**
         * 用于清空对象里的数据
         */
        public void clear(){
            this.id=null;
            this.title=null;
            this.name=null;
            this.publisher=null;
            this.time=null;
            this.price=null;
        }
    
        public Book(Integer id, String title, String name, String publisher, Date time, BigDecimal price) {
            this.id = id;
            this.title = title;
            this.name = name;
            this.publisher = publisher;
            this.time = time;
            this.price = price;
        }
    
        public Book(BigDecimal price) {
            this.price = price;
        }
    
        /**
         * 获取图书编号
         * 
         * @return 图书编号
         */
        public Integer getId() {
            return this.id;
        }
    
        /**
         * 设置图书编号
         * 
         * @param id
         *          图书编号
         */
        public void setId(Integer id) {
            this.id = id;
        }
    
        /**
         * 获取图书名称
         * 
         * @return 图书名称
         */
        public String getTitle() {
            return this.title;
        }
    
        /**
         * 设置图书名称
         * 
         * @param title
         *          图书名称
         */
        public void setTitle(String title) {
            this.title = title;
        }
    
        /**
         * 获取作者姓名
         * 
         * @return 作者姓名
         */
        public String getName() {
            return this.name;
        }
    
        /**
         * 设置作者姓名
         * 
         * @param name
         *          作者姓名
         */
        public void setName(String name) {
            this.name = name;
        }
    
        /**
         * 获取出版社
         * 
         * @return 出版社
         */
        public String getPublisher() {
            return this.publisher;
        }
    
        /**
         * 设置出版社
         * 
         * @param publisher
         *          出版社
         */
        public void setPublisher(String publisher) {
            this.publisher = publisher;
        }
    
        /**
         * 获取出版时间
         * 
         * @return 出版时间
         */
        public Date getTime() {
            return this.time;
        }
    
        /**
         * 设置出版时间
         * 
         * @param time
         *          出版时间
         */
        public void setTime(Date time) {
            this.time = time;
        }
    
        /**
         * 获取价格
         * 
         * @return 价格
         */
        public BigDecimal getPrice() {
            return this.price;
        }
    
        /**
         * 设置价格
         * 
         * @param price
         *          价格
         */
        public void setPrice(BigDecimal price) {
            this.price = price;
        }
    
      
    }
    

    3.Mapper映射

    ①接口类 BooKMapper

    package com.dreamchaser.mapper;
    
    import com.dreamchaser.domain.Book;
    
    import java.util.List;
    import java.util.Map;
    
    public interface BookMapper {
        public List<Book> selectSmaller(Map<String,Object> map);
        public List<Book> selectAll();
        public List<Book> selectBigger(Map<String,Object> map);
        public List<Book> findBookByCondition(Map<String,Object> map);
        public List<Book> findBooksById(int id);
        public void insertBook(Map<String,Object> map);
        public void insertBooks(List<Book> books);
        public void updateBookById(Map<String,Object> map);
        public void updateBooks(List<Map<String,Object>> list);
        public void deleteBookById(int id);
        public void deleteBooksByIds(List<Integer> ids);
        /**
         * @param map 要注意这里的map中只能有一个对象
         * @return
         */
        public List<Book> findBookByConditionO(Map<String,Object> map);
    }
    

    ②BookMapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!-- books 路径不是/,而是.!!!-->
    <mapper namespace="com.dreamchaser.mapper.BookMapper">
        <!-- 字段映射 -->
        <resultMap id="booksMap" type="Book">
            <!--设置主键,提高mybatis性能-->
            <id property="id" column="id"/>
        </resultMap>
    
    
    
        <!-- 表查询字段 -->
        <sql id="allColumns">
            b.id, b.title, b.name, b.publisher, b.time, b.price
        </sql>
    
        <!-- 查询小于条件的结果 多条会自动打包成list  注:&lt;指的是<,在xml中<是非法的 -->
        <select id="selectSmaller" parameterType="map" resultMap="booksMap">
            SELECT
            <include refid="allColumns"/>
            from books b
            <where>
                <if test="time != null and time!=''">
                    AND b.time &lt;=#{time}
                </if>
                <if test="price != null and price !=''">
                    AND b.price &lt;=#{price}
                </if>
            </where>
        </select>
    
        <!-- 查询小于条件的结果   注:&lt;指的是<,在xml中<是非法的 -->
        <select id="selectBigger" parameterType="map" resultMap="booksMap">
            SELECT
            <include refid="allColumns"/>
            from books b
            <where>
                <if test="time != null and time!=''">
                    AND b.time >=#{time}
                </if>
                <if test="price != null and price !=''">
                    AND b.price >=#{price}
                </if>
            </where>
        </select>
        <!-- 查询所有数据 -->
        <select id="selectAll" resultMap="booksMap">
            SELECT
            <include refid="allColumns" />
            FROM books b
        </select>
        
        <!-- 根据条件参数查询数据列表 -->
        <select id="findBookByCondition" resultMap="booksMap" parameterType="map">
            SELECT
            <include refid="allColumns" />
            FROM books b WHERE 1 = 1
            <if test="title != null and title != ''">
                AND b.title LIKE CONCAT('%', #{title}, '%')
            </if>
            <if test="name != null and name != ''">
                AND b.name LIKE CONCAT('%', #{name}, '%')
            </if>
            <if test="publisher != null and publisher != ''">
                AND b.publisher LIKE CONCAT('%', #{publisher}, '%')
            </if>
            <if test="time != null">
                AND b.time = #{time}
            </if>
            <if test="price != null">
                AND b.price = #{price}
            </if>
        </select>
        
        <!-- 根据主键查询数据 -->
        <select id="findBooksById" resultMap="booksMap" parameterType="int">
            SELECT
            <include refid="allColumns" />
            FROM books b WHERE b.id =#{id}
        </select>
        
        <!-- 插入数据 -->
        <insert id="insertBook" parameterType="map">
            INSERT INTO books (
                id, title, name, publisher, time, price
            ) VALUES (
                #{id},
                #{title},
                #{name},
                #{publisher},
                #{time},
                #{price}
            )
        </insert>
        
        <!-- 批量插入数据 -->
        <insert id="insertBooks" parameterType="list">
            INSERT INTO books (
                id, title, name, publisher, time, price
            ) VALUES
            <foreach collection="list" index="index" item="item" separator=",">
                (
                    #{item.id},
                    #{item.title},
                    #{item.name},
                    #{item.publisher},
                    #{item.time},
                    #{item.price}
                )
            </foreach>
        </insert>
        
        <!-- 修改数据 -->
        <update id="updateBookById" parameterType="map">
            UPDATE books
            <set>
                <if test="title != null">
                    title = #{title},
                </if>
                <if test="name != null">
                    name = #{name},
                </if>
                <if test="publisher != null">
                    publisher = #{publisher},
                </if>
                <if test="time != null">
                    time = #{time},
                </if>
                <if test="price != null">
                    price = #{price}
                </if>
            </set>
            WHERE id = #{id}
        </update>
        
        <!-- 批量修改数据 -->
        <update id="updateBooks" parameterType="list">
            <foreach collection="list" index="index" item="item" separator=";">
                UPDATE books
                <set>
                    <if test="item.title != null">
                        title = #{item.title},
                    </if>
                    <if test="item.name != null">
                        name = #{item.name},
                    </if>
                    <if test="item.publisher != null">
                        publisher = #{item.publisher},
                    </if>
                    <if test="item.time != null">
                        time = #{item.time},
                    </if>
                    <if test="item.price != null">
                        price = #{item.price}
                    </if>
                </set>
                WHERE id = #{item.id}
            </foreach>
        </update>
        
        <!-- 根据主键删除数据 -->
        <delete id="deleteBookById" parameterType="int">
            DELETE FROM books WHERE id = #{id}
        </delete>
        
        <!-- 根据主键批量删除数据 -->
        <delete id="deleteBooksByIds" parameterType="list">
            DELETE FROM books WHERE id IN
            <foreach collection="list" index="index" item="id" open="(" separator="," close=")">
                #{id}
            </foreach>
        </delete>
    
        <!-- 根据条件排序查询-->
        <select id="findBookByConditionO" resultMap="booksMap" parameterType="map">
            SELECT
            <include refid="allColumns" />
            FROM books b WHERE 1 = 1
            <if test="title != null and title != ''">
                ORDER BY title
            </if>
            <if test="name != null and name != ''">
                ORDER BY name
            </if>
            <if test="time != null">
                ORDER BY time
            </if>
            <if test="price != null">
                ORDER BY price
            </if>
        </select>
    </mapper>
    

    4.工具类 {#工具类 .list-paragraph}

    ①日期工具类 DateUtil

    用于Date和字符串之间的转换

    package com.dreamchaser.util;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * 日期工具类,用于date和字符串之间的转换
     * @author 金昊霖
     */
    public class DateUtil {
        public static String dateToString(Date date,String format){
            return new SimpleDateFormat(format).format(date);
        }
        public static Date stringToDate(String date,String format){
            try {
                return new SimpleDateFormat(date).parse(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

    ②展示工具类 Displayer

    用于展示传入的数据

    package com.dreamchaser.util;
    
    import com.dreamchaser.domain.Book;
    import java.util.List;
    
    /**
     * 显示类,用于展示传入的数据
     *
     * @author 金昊霖
     */
    public class Displayer {
    //    public static void main(String[] args) {
    //        Book book = new Book(123, "狂人日记", "鲁迅", "追梦出版社", new Date("2020/6/18"),
    //                new BigDecimal("30.06"));
    //        List<Book> list = new LinkedList<>();
    //        list.add(book);
    //        show(list);
    //    }
    
    
        public static void show(List<Book> list) {
            System.out.println("--------------------------------------------------------------------------");
            System.out.println("| 图书编号    书名           作者名     出版单位       出版时间            价格  |");
            for (Book book : list) {
                String date="";
                if (book.getTime()!=null){
                    date=DateUtil.dateToString(book.getTime(),"yyyy-MM-dd");
                }
                System.out.println("| " + book.getId() + "       " + book.getTitle() + "         " + book.getName() + "     " +
                        book.getPublisher() + "     "+date+ "      " + book.getPrice() + " |");
            }
            System.out.println("--------------------------------------------------------------------------");
        }
    
        public static void show(Book book) {
            System.out.println("-------------------------------------------------------------------------");
            System.out.println("| 图书编号    书名           作者名     出版单位       出版时间            价格 |");
    
    
            String date="";
            if (book.getTime()!=null){
                date=DateUtil.dateToString(book.getTime(),"yyyy-MM-dd");
            }
            System.out.println("| " + book.getId() + "       " + book.getTitle() + " " + book.getName() + "     " +
                    book.getPublisher() + "     "+date+ "      " + book.getPrice() + " |");
    
            System.out.println("-------------------------------------------------------------------------");
        }
    }
    

    ③文件工具类 FileUtil

    package com.dreamchaser.util;
    
    import com.dreamchaser.domain.Book;
    
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 读取文件工具类
     */
    public class FileUtil {
        /**
         * 读取txt文件内容
         * @param path 文件路径
         * @return List<String> txt文件内容封装成一个list返回,如果文件不存在就返回null
         */
        public static List<String> readTxtFile(String path){
            File file=new File(path);
            List<String> list=new ArrayList<>();
            if (file.exists()&&file.isFile()){
                BufferedReader reader=null;
                try {
                    reader=new BufferedReader(new FileReader(file));
                    String line=null;
                    while ((line=reader.readLine())!=null){
                        list.add(line);
                    }
    
                    return list;
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    try {
                        //最后将输入流关闭
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
            }
            return null;
        }
    
        public static boolean writeFile(List<Book> list,String path){
            File file=new File(path);
            if (file.exists()&&file.isFile()){
                try {
                    BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter(file));
                    for (Book book:list){
                        bufferedWriter.write(book.getId()+"    ");
                        bufferedWriter.write(book.getTitle()+"    ");
                        bufferedWriter.write(book.getName()+"    ");
                        bufferedWriter.write(book.getPublisher()+"    ");
                        bufferedWriter.write(book.getTime()+"    ");
                        bufferedWriter.write(book.getPrice()+"    ");
                        bufferedWriter.newLine();
                        bufferedWriter.flush();
                        bufferedWriter.close();
                        return true;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
            return false;
        }
    

    ④SqlSession工具类

    用于返回所需的SqlSession对象

    package com.dreamchaser.util;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * SqlSession工具类
     * 用于产生sqlSession
     */
    public class SqlSessionUtil {
        public SqlSession getSqlSession(){
            // 指定全局配置文件
            String resource = "mybatis-config.xml";
            // 读取配置文件
            InputStream inputStream = null;
            try {
                inputStream = Resources.getResourceAsStream(resource);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 构建sqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            return sqlSessionFactory.openSession();
        }
    }
    

    5.模块类 {#模块类 .list-paragraph}

    ①总驱动类 Driver

    用于整个项目的驱动

    package com.dreamchaser;
    
    
    import java.util.Scanner;
    
    /**
     * 驱动类
     * 主要负责统一Sql和NoSql两个模式
     * 为了便捷,功能之间采用“套娃”的方式连接(实质就是避免递归调用造成堆栈溢出)
     * 套娃的基本思路:每个函数都有一个整数类型的返回值,只要返回1,就能返回上一级(实现原理,由该函数(记为函数1)的
     * 上一级(记为函数2)控制,如果函数1返回一了,就在函数2的上一级(记为函数3)再次调用函数2,即可做到返回上一层;
     * 而如果函数1返回0则在函数2再次循环调用,直至函数返回1)
     * 这样做不仅能实现功能,而且能避免多次“套娃”导致堆栈溢出的风险
     * @author 金昊霖
     */
    public class Driver {
    
        static Scanner scanner = new Scanner(System.in);
    
        public  static void main(String[] args) {
    
            while (true) {
                if (choosePattern(1) == 1) {
                    break;
                }
            }
        }
        /**
         * 一级模块
         * 选择模式模块
         * i 用于递归时判断其是否是第一次来还是输入错误来的
         *
         * @return 用于判断函数状态,0表示继续呆在这层,1表示退回上一层
         */
        private  static int choosePattern(int i) {
            if (i == 1) {
                System.out.println("\n\n\n||||图书信息管理系统||||       \n");
                System.out.println("技术栈选择:mysql+mybatis+java");
                System.out.println("作者:软工1902 金昊霖\n");
                System.out.println("请选择存储模式:");
                System.out.println("1.mysql存储(持久化规范数据存储)");
                System.out.println("2.简单运存存储(如要数据持久化,则需导出文件)");
                System.out.println("3.退出该系统\n\n");
                System.out.println("请输入你的选择(序号):");
            }
    
            switch (scanner.nextInt()) {
                case 1:
                    //这样做既能使其能返回上一级,而且想留在此级时不会造成“无限套娃”,即堆栈不断压缩的情况
                    while (true) {
                        if (PatternSql.chooseFunction(1) == 1) {
                            return 0;
                        }
                    }
                case 2:
                    while (true) {
                        if (PatternNoSql.chooseFunction(1) == 1) {
                            return 0;
                        }
                    }
                case 3:
                    return 1;
                default:
                    System.out.println("抱歉,输入的是非法字符,请重新输入:");
                    //这里是采用递归,暂时没办法,如不采用会很麻烦
                    return choosePattern(0);
            }
        }
    }
    

    ②SqlPattern模块类

    集成Sql模式

    package com.dreamchaser;
    
    import com.dreamchaser.mapper.BookMapper;
    import com.dreamchaser.domain.Book;
    import com.dreamchaser.util.DateUtil;
    import com.dreamchaser.util.Displayer;
    import com.dreamchaser.util.FileUtil;
    import com.dreamchaser.util.SqlSessionUtil;
    import org.apache.ibatis.session.SqlSession;
    
    import java.math.BigDecimal;
    import java.util.*;
    
    /**
     * Sql模式
     */
    public class PatternSql {
        static Scanner scanner = new Scanner(System.in);
        /**
         * mybatis中的sql
         */
        static SqlSession sqlSession = new SqlSessionUtil().getSqlSession();
        /**
         * 获取mybatis为我们创建好的Mapper对象
         */
        static BookMapper bookMapper = sqlSession.getMapper(BookMapper.class);
        /**
         * 空map,用于记录数据,每次方法加载时都要清空
         */
        static Map<String, Object> map = new HashMap<>();
        /**
         * 测试xml到底有没有载入
         * 这里就不删了,留作纪念
         * @param args
         */
    //    public static void main(String[] args) {
            PatternSql patternSql=new PatternSql();
    //        SqlSession sqlSession =new SqlSessionUtil().getSqlSession();
    //        List list = sqlSession.selectList("com.dreamchaser.mapper.BookMapper.selectAll");
    //        Displayer.show(list);
    //    }
    
        /**
         * 二级模块
         *
         * @param i 用于递归时判断其是否是第一次来还是输入错误来的
         * @return 用于返回上一级, 返回1就表示需要返回上一级,返回0则说明继续执行
         */
        public static int chooseFunction(int i) {
            if (i == 1) {
                System.out.println("\n\n功能:");
                System.out.println("1.图书信息录入");
                System.out.println("2.图书信息浏览");
                System.out.println("3.插入图书信息");
                System.out.println("4.查询");
                System.out.println("5.排序");
                System.out.println("6.修改图书信息");
                System.out.println("7.删除图书信息");
                System.out.println("8.导出为文件");
                System.out.println("9.返回模式选择");
                System.out.println("\n\n请输入你需要选择的功能(序号):");
            }
    
            while (true) {
                switch (scanner.nextInt()) {
                    case 1:
                        saveFile();
                        return 0;
                    case 2:
                        selectAll();
                        return 0;
                    case 3:
                        addOneBook();
                        return 0;
                    case 4:
                        while (true) {
                            if (chooseSelect(1) == 1) {
                                return 0;
                            }
                        }
                    case 5:
                        while (true) {
                            if (chooseOrder(1) == 1) {
                                return 0;
                            }
                        }
                    case 6:
                        updateBook();
                        return 0;
                    case 7:
                        deleteOne();
                        return 0;
                    case 8:
                        writeToFile();
                        return 0;
                    case 9:
                        return 1;
                    default:
                        System.out.println("抱歉,输入的是非法字符,请重新输入:");
                        return chooseFunction(0);
                }
            }
        }
    
        private static void deleteOne() {
            System.out.println("请输入你要删除书籍的图书编号:");
            bookMapper.deleteBookById(scanner.nextInt());
            System.out.println("删除成功!");
        }
    
        private static void updateBook() {
            map.clear();
            System.out.println("请输入你要更新的书籍图书编号:");
            map.put("id", scanner.nextInt());
            scanner.nextLine();
            System.out.println("是否要修改其图书名称(若是,请输入其名称,若否,则输入“否”):");
            String title = scanner.nextLine();
            if (!title.equals("否")) {
                map.put("title", title);
            }
            System.out.println("是否要修改其作者姓名(若是,请输入其姓名,若否,则输入“否”):");
            String name = scanner.nextLine();
            if (!name.equals("否")) {
                map.put("name", name);
            }
            System.out.println("是否要修改其出版社(若是,请输入其出版社名称,若否,则输入“否”):");
            String publisher = scanner.nextLine();
            if (!publisher.equals("否")) {
                map.put("publisher", publisher);
            }
            System.out.println("是否要修改其出版时间(若是,请输入其时间,请以“2020/10/06”的形式输入时间,若否,则输入“否”):");
            String time = scanner.nextLine();
            if (!time.equals("否")) {
                map.put("time", new Date(time));
            }
            System.out.println("是否要修改其价格(若是,请输入其价格,若否,则输入“否”):");
            String price = scanner.nextLine();
            if (!price.equals("否")) {
                map.put("price", new BigDecimal(price));
            }
            bookMapper.updateBookById(map);
            System.out.println("更新成功!");
        }
        private static void writeToFile() {
            System.out.println("请输入你要保存的文件名(如:dreamchaser.txt):");
            scanner.nextLine();
            Boolean flag=FileUtil.writeFile(bookMapper.selectAll(),scanner.nextLine());
            if (flag){
                System.out.println("保存成功!");
            }else {
                System.out.println("保存失败,请确认输入的文件路径是否正确!");
            }
    
        }
    
        private static void saveFile() {
            System.out.println("请输入要录入的文件(txt,且需每一行都是一条记录)路径(绝对路径或者相对路径皆可):");
            //把回车吃掉
            scanner.nextLine();
            List<String> list = FileUtil.readTxtFile(scanner.nextLine());
            String[] strings=null;
            if (list!=null){
                for (String s:list){
                    strings=s.split(" |\n");
                    map.clear();
                    map.put("id",strings[0]);
                    map.put("title",strings[1]);
                    map.put("name",strings[2]);
                    map.put("publisher",strings[3]);
                    map.put("time", DateUtil.stringToDate(strings[4],"yyyy/MM/dd"));
                    map.put("price",new BigDecimal(strings[5]));
                    bookMapper.insertBook(map);
                }
                System.out.println("录入成功");
            }else {
                System.out.println("文件未找到或者文件不符合要求。请重新输入!");
            }
    
        }
    
        private static void selectAll() {
            List<Book> books = bookMapper.selectAll();
            Displayer.show(books);
        }
    
        private static void addOneBook() {
            map.clear();
            System.out.println("请输入你要插入书籍的图书编号:");
            map.put("id", scanner.nextInt());
            scanner.nextLine();
            System.out.println("请输入你要插入书籍的图书名称:");
            String title = scanner.nextLine();
            map.put("title", title);
            System.out.println("请输入你要插入书籍的作者姓名:");
            String name = scanner.nextLine();
            map.put("name", name);
            System.out.println("请输入你要插入书籍的出版社(若是,请输入其出版社名称,若否,则输入“否”):");
            String publisher = scanner.nextLine();
            if (!publisher.equals("否")) {
                map.put("publisher", publisher);
            }
            System.out.println("请输入你要插入书籍的出版时间(若是,请输入其时间,请以“2020/10/06”的形式输入时间,若否,则输入“否”):");
            String time = scanner.nextLine();
            if (!time.equals("否")) {
                map.put("time", new Date(time));
            }
            System.out.println("请输入你要插入书籍的价格(若是,请输入其价格,若否,则输入“否”):");
            String price = scanner.nextLine();
            if (!price.equals("否")) {
                map.put("price", new BigDecimal(price));
            }
            bookMapper.insertBook(map);
            System.out.println("插入成功");
        }
    
        /**
         * 排序模块
         * 三级模块
         *
         * @param i
         * @return
         */
        private static int chooseOrder(int i) {
            if (i == 1) {
                System.out.println("\n\n排序:");
                System.out.println("1.按图书编号排序");
                System.out.println("2.按书名排序");
                System.out.println("3.按出版时间排序");
                System.out.println("4.按价格排序等");
                System.out.println("5.返回功能选择");
                System.out.println("\n\n请输入你需要的排序方式(序号):");
            }
    
            while (true) {
                switch (scanner.nextInt()) {
                    case 1:
                        selectOrderById();
                        return 0;
                    case 2:
                        selectOrderByTitle();
                        return 0;
                    case 3:
                        selectOrderByTime();
                        return 0;
                    case 4:
                        selectOrderByPrice();
                        return 0;
                    case 5:
                        return 1;
                    default:
                        System.out.println("抱歉,输入的是非法字符,请重新输入:");
                        return chooseFunction(0);
                }
            }
        }
    
        private static void selectOrderByPrice() {
            map.clear();
            map.put("price", "1");
            List<Book> books = bookMapper.findBookByConditionO(map);
            Displayer.show(books);
        }
    
        private static void selectOrderByTime() {
            map.clear();
            map.put("time", "1");
            List<Book> books = bookMapper.findBookByConditionO(map);
            Displayer.show(books);
        }
    
        private static void selectOrderByTitle() {
            map.clear();
            map.put("title", "1");
            List<Book> books = bookMapper.findBookByConditionO(map);
            Displayer.show(books);
        }
    
        private static void selectOrderById() {
            map.clear();
            map.put("id", "1");
            List<Book> books = bookMapper.findBookByConditionO(map);
            Displayer.show(books);
        }
    
        /**
         * 查询模块
         * 三级模块
         *
         * @param i
         * @return
         */
        private static int chooseSelect(int i) {
            if (i == 1) {
                System.out.println("\n\n查询:");
                System.out.println("1.按书名查询");
                System.out.println("2.按作者名查询");
                System.out.println("3.按价格查询(小于)");
                System.out.println("4.按价格查询(等于)");
                System.out.println("5.按价格查询(大于)");
                System.out.println("6.返回模式选择");
                System.out.println("\n\n请输入你需要的查询方式(序号):");
            }
    
            while (true) {
                switch (scanner.nextInt()) {
                    case 1:
                        selectByTitle();
                        return 0;
                    case 2:
                        selectByName();
                        return 0;
                    case 3:
                        selectByPriceS();
                        return 0;
                    case 4:
                        selectByPrice();
                        return 0;
                    case 5:
                        selectByPriceB();
                        return 0;
                    case 6:
                        return 1;
                    default:
                        System.out.println("抱歉,输入的是非法字符,请重新输入:");
                        return chooseFunction(0);
                }
            }
        }
    
        private static void selectByPriceB() {
            System.out.println("请输入你要查询的价格:");
            map.clear();
            map.put("price", scanner.nextInt());
            List<Book> books = bookMapper.selectBigger(map);
            Displayer.show(books);
        }
    
        private static void selectByPrice() {
            System.out.println("请输入你要查询的价格:");
            map.clear();
            map.put("price", scanner.nextInt());
            List<Book> books = bookMapper.findBookByCondition(map);
            Displayer.show(books);
        }
    
        private static void selectByPriceS() {
            System.out.println("请输入你要查询的价格:");
            map.clear();
            map.put("price", new BigDecimal(scanner.nextInt()));
            List<Book> books = bookMapper.selectSmaller(map);
            Displayer.show(books);
        }
    
        private static void selectByName() {
            System.out.println("请输入你要查询的作者姓名:");
            map.clear();
            //因为后面是nextLine,而之前是nextInt,会算上回车键,所以得先用nextLine吃掉回车
            scanner.nextLine();
            map.put("name", scanner.nextLine());
            List<Book> books = bookMapper.findBookByCondition(map);
            Displayer.show(books);
        }
    
        private static void selectByTitle() {
            System.out.println("请输入你要查询的书籍名称:");
            map.clear();
            scanner.nextLine();
            map.put("title", scanner.nextLine());
            List<Book> books = bookMapper.findBookByCondition(map);
            Displayer.show(books);
        }
    
    }
    

    ③noSql模块类

    集成noSql模式

    package com.dreamchaser;
    
    import com.dreamchaser.domain.Book;
    import com.dreamchaser.util.DateUtil;
    import com.dreamchaser.util.Displayer;
    import com.dreamchaser.util.FileUtil;
    
    import java.math.BigDecimal;
    import java.util.*;
    
    public class PatternNoSql {
        static Scanner scanner = new Scanner(System.in);
        /**
         * 维护的链表
         */
        static List<Book> list = new LinkedList<>();
        static Book book = new Book();
    
    
    
        /**
         * 二级模块
         *
         * @param i 用于递归时判断其是否是第一次来还是输入错误来的
         * @return 用于返回上一级, 返回1就表示需要返回上一级,返回0则说明继续执行
         */
        public static int chooseFunction(int i) {
            if (i == 1) {
                System.out.println("\n\n功能:");
                System.out.println("1.图书信息录入");
                System.out.println("2.图书信息浏览");
                System.out.println("3.插入图书信息");
                System.out.println("4.查询");
                System.out.println("5.排序");
                System.out.println("6.修改图书信息");
                System.out.println("7.删除图书信息");
                System.out.println("8.导出为文件");
                System.out.println("9.返回模式选择");
                System.out.println("\n\n请输入你需要选择的功能(序号):");
            }
    
            while (true) {
                switch (scanner.nextInt()) {
                    case 1:
                        saveFile();
                        return 0;
                    case 2:
                        selectAll();
                        return 0;
                    case 3:
                        addOneBook();
                        return 0;
                    case 4:
                        while (true) {
                            if (chooseSelect(1) == 1) {
                                return 0;
                            }
                        }
                    case 5:
                        while (true) {
                            if (chooseOrder(1) == 1) {
                                return 0;
                            }
                        }
                    case 6:
                        updateBook();
                        return 0;
                    case 7:
                        deleteOne();
                        return 0;
                    case 8:
                        writeToFile();
                        return 0;
                    case 9:
                        return 1;
                    default:
                        System.out.println("抱歉,输入的是非法字符,请重新输入:");
                        return chooseFunction(0);
                }
            }
        }
    
        private static void writeToFile() {
            System.out.println("请输入你要保存的文件名(如:dreamchaser.txt):");
            scanner.nextLine();
            Boolean flag=FileUtil.writeFile(list,scanner.nextLine());
            if (flag){
                System.out.println("保存成功!");
            }else {
                System.out.println("保存失败,请确认输入的文件路径是否正确!");
            }
        }
    
        private static void deleteOne() {
            System.out.println("请输入你要删除书籍的图书编号:");
            int id = scanner.nextInt();
            boolean flag = list.removeIf(a -> a.getId() == id);
            if (flag) {
                System.out.println("删除成功!");
            } else {
                System.out.println("未找到相应的图书!");
            }
        }
    
        private static void updateBook() {
            book.clear();
            System.out.println("请输入你要更新的书籍图书编号:");
            book.setId(scanner.nextInt());
            scanner.nextLine();
            System.out.println("是否要修改其图书名称(若是,请输入其名称,若否,则输入“否”):");
            String title = scanner.nextLine();
            if (!title.equals("否")) {
                book.setTitle(title);
            }
            System.out.println("是否要修改其作者姓名(若是,请输入其姓名,若否,则输入“否”):");
            String name = scanner.nextLine();
            if (!name.equals("否")) {
                book.setName(name);
            }
            System.out.println("是否要修改其出版社(若是,请输入其出版社名称,若否,则输入“否”):");
            String publisher = scanner.nextLine();
            if (!publisher.equals("否")) {
                book.setPublisher(publisher);
            }
            System.out.println("是否要修改其出版时间(若是,请输入其时间,请以“2020/10/06”的形式输入时间,若否,则输入“否”):");
            String time = scanner.nextLine();
            if (!time.equals("否")) {
                book.setTime(new Date(time));
            }
            System.out.println("是否要修改其价格(若是,请输入其价格,若否,则输入“否”):");
            String price = scanner.nextLine();
            if (!price.equals("否")) {
                book.setPrice(new BigDecimal(price));
            }
            for (Book book1 : list) {
                if (book1.getId().equals(book.getId())) {
                    list.remove(book1);
                    list.add(book);
                }
            }
            System.out.println("更新成功!");
        }
    
        private static void saveFile() {
            System.out.println("请输入要录入的文件(txt,且需每一行都是一条记录)路径(绝对路径或者相对路径皆可):");
            //把回车吃掉
            scanner.nextLine();
            List<String> list1 = FileUtil.readTxtFile(scanner.nextLine());
            String[] strings = null;
            if (list1 != null) {
                for (String s : list1) {
                    strings = s.split(" |\n");
                    book.clear();
                    book.setId(Integer.parseInt(strings[0]));
                    book.setTitle(strings[1]);
                    book.setName(strings[2]);
                    book.setPublisher(strings[3]);
                    book.setTime(DateUtil.stringToDate(strings[4], "yyyy/MM/dd"));
                    book.setPrice(new BigDecimal(strings[5]));
                    list.add(book);
                }
                System.out.println("录入成功");
            } else {
                System.out.println("文件未找到或者文件不符合要求。请重新输入!");
            }
    
        }
    
        private static void selectAll() {
            Displayer.show(list);
        }
    
        private static void addOneBook() {
            book.clear();
            System.out.println("请输入你要插入书籍的图书编号:");
            book.setId(scanner.nextInt());
            scanner.nextLine();
            System.out.println("请输入你要插入书籍的图书名称:");
            String title = scanner.nextLine();
            book.setTitle(title);
            System.out.println("请输入你要插入书籍的作者姓名:");
            String name = scanner.nextLine();
            book.setName(name);
            System.out.println("请输入你要插入书籍的出版社(若是,请输入其出版社名称,若否,则输入“否”):");
            String publisher = scanner.nextLine();
            if (!publisher.equals("否")) {
                book.setPublisher(publisher);
            }
            System.out.println("请输入你要插入书籍的出版时间(若是,请输入其时间,请以“2020/10/06”的形式输入时间,若否,则输入“否”):");
            String time = scanner.nextLine();
            if (!time.equals("否")) {
                book.setTime(new Date(time));
            }
            System.out.println("请输入你要插入书籍的价格(若是,请输入其价格,若否,则输入“否”):");
            String price = scanner.nextLine();
            if (!price.equals("否")) {
                book.setPrice(new BigDecimal(price));
            }
            list.add(book);
            System.out.println("插入成功");
        }
    
        /**
         * 排序模块
         * 三级模块
         *
         * @param i
         * @return
         */
        private static int chooseOrder(int i) {
            if (i == 1) {
                System.out.println("\n\n排序:");
                System.out.println("1.按图书编号排序");
                System.out.println("2.按书名排序");
                System.out.println("3.按出版时间排序");
                System.out.println("4.按价格排序等");
                System.out.println("5.返回功能选择");
                System.out.println("\n\n请输入你需要的排序方式(序号):");
            }
    
            while (true) {
                switch (scanner.nextInt()) {
                    case 1:
                        selectOrderById();
                        return 0;
                    case 2:
                        selectOrderByTitle();
                        return 0;
                    case 3:
                        selectOrderByTime();
                        return 0;
                    case 4:
                        selectOrderByPrice();
                        return 0;
                    case 5:
                        return 1;
                    default:
                        System.out.println("抱歉,输入的是非法字符,请重新输入:");
                        return chooseFunction(0);
                }
            }
        }
    
        private static void selectOrderByPrice() {
            /**
             * 把 x -> System.out.println(x) 简化为 System.out::println 的过程称之为 eta-conversion
             * 把 System.out::println 简化为 x -> System.out.println(x) 的过程称之为 eta-expansion
             * 范式:
             * 类名::方法名
             * 方法调用
             *
             * person -> person.getAge();
             * 可以替换成
             * Person::getAge
             *
             * x -> System.out.println(x)
             * 可以替换成
             * System.out::println
             * out是一个PrintStream类的对象,println是该类的方法,依据x的类型来重载方法
             * 创建对象
             *
             * () -> new ArrayList<>();
             * 可以替换为
             * ArrayList::new
             */
            list.sort(Comparator.comparing(Book::getPrice));
            Displayer.show(list);
        }
    
        private static void selectOrderByTime() {
            list.sort(Comparator.comparing(Book::getTime));
            Displayer.show(list);
        }
    
        private static void selectOrderByTitle() {
            list.sort(Comparator.comparing(Book::getTitle));
            Displayer.show(list);
        }
    
        private static void selectOrderById() {
            list.sort(Comparator.comparing(Book::getId));
            Displayer.show(list);
        }
    
        /**
         * 查询模块
         * 三级模块
         *
         * @param i
         * @return
         */
        private static int chooseSelect(int i) {
            if (i == 1) {
                System.out.println("\n\n查询:");
                System.out.println("1.按书名查询");
                System.out.println("2.按作者名查询");
                System.out.println("3.按价格查询(小于)");
                System.out.println("4.按价格查询(等于)");
                System.out.println("5.按价格查询(大于)");
                System.out.println("6.返回模式选择");
                System.out.println("\n\n请输入你需要的查询方式(序号):");
            }
    
            while (true) {
                switch (scanner.nextInt()) {
                    case 1:
                        selectByTitle();
                        return 0;
                    case 2:
                        selectByName();
                        return 0;
                    case 3:
                        selectByPriceS();
                        return 0;
                    case 4:
                        selectByPrice();
                        return 0;
                    case 5:
                        selectByPriceB();
                        return 0;
                    case 6:
                        return 1;
                    default:
                        System.out.println("抱歉,输入的是非法字符,请重新输入:");
                        return chooseFunction(0);
                }
            }
        }
    
        private static void selectByPriceB() {
            System.out.println("请输入你要查询的价格:");
            List<Book> result = new LinkedList<>();
            for (Book book1 : list) {
                if (book1.getPrice().compareTo(new BigDecimal(scanner.nextInt())) == 1) {
                    result.add(book1);
                }
            }
            Displayer.show(result);
        }
    
        private static void selectByPrice() {
            System.out.println("请输入你要查询的价格:");
            List<Book> result = new LinkedList<>();
            for (Book book1 : list) {
                if (book1.getPrice().compareTo(new BigDecimal(scanner.nextInt())) == 0) {
                    result.add(book1);
                }
            }
            Displayer.show(result);
        }
    
        private static void selectByPriceS() {
            System.out.println("请输入你要查询的价格:");
            List<Book> result = new LinkedList<>();
            for (Book book1 : list) {
                if (book1.getPrice().compareTo(new BigDecimal(scanner.nextInt())) == -1) {
                    result.add(book1);
                }
            }
            Displayer.show(result);
        }
    
        private static void selectByName() {
            System.out.println("请输入你要查询的作者姓名:");
            //因为后面是nextLine,而之前是nextInt,会算上回车键,所以得先用nextLine吃掉回车
            scanner.nextLine();
            List<Book> result = new LinkedList<>();
            for (Book book1 : list) {
                if (book1.getName().equals(scanner.nextLine())) {
                    result.add(book1);
                }
            }
            Displayer.show(result);
        }
    
        private static void selectByTitle() {
            System.out.println("请输入你要查询的书籍名称:");
            scanner.nextLine();
            List<Book> result = new LinkedList<>();
            for (Book book1 : list) {
                if (book1.getTitle().equals(scanner.nextLine())) {
                    result.add(book1);
                }
            }
            Displayer.show(result);
        }
    }
    

    6.配置文件 {#配置文件 .list-paragraph}

    ①db.properties

    配置数据库的路径,用户密码等

    dbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/library?serverTimezone=UTC
    jdbc.username=root
    jdbc.password=jinhaolin
    

    ②log4j.properties

    配置log4j

    log4j.rootCategory=DEBUG, CONSOLE,LOGFILE
    
    
    
    
    
    
    log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
    log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    log4j.appender.CONSOLE.layout.ConversionPattern=-%p-%d{yyyy/MM/dd HH:mm:ss,SSS}-%l-%L-%m%n
    
    
    log4j.appender.LOGFILE=org.apache.log4j.FileAppender
    log4j.appender.LOGFILE.File=E:/axis.log
    log4j.appender.LOGFILE.Append=true
    log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.LOGFILE.layout.ConversionPattern=-%p-%d{yyyy/MM/dd HH:mm:ss,SSS}-%l-%L-%m%n
    

    ③mybatis-config.xml

    配置mybatis框架

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
        <properties resource="db.properties"/>
    
        <!--用于开启缓存,优化查询速度,但基本没什么用,效果很不明显。
        优化查询速度一般采取的措施:
        1.构建索引
        2.使用redio缓存数据库
        3.使用搜索引擎(一般用于电商项目)-->
    
    
        <typeAliases>
            <!--方式一:为类起别名-->
    <!--        <typeAlias type="com.dreamchaser.domain.User" alias="user"/>-->
            <!--方式二:使用package起别名,该包下的类别名是mybatis自动为我们取好的,就是类名(不区分大小写,但最好按照约定
            俗成的标准去写)-->
            <package name="com.dreamchaser.domain"/>
        </typeAliases>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
        <!--注册中心,指定mapper映射文件-->
        <mappers>
            <!--方式一:单独注册-->
    <!--        <mapper resource="com/dreamchaser/dao/UserDao.xml"/>-->
    <!--        <mapper resource="com.dreamchaser.mapper/BookMapper.xml"/>-->
            <!--方式二:使用接口的全路径注册-->
            <!--方式三:批量注册,该包下的所有mapper映射文件自动注册(通常采用此种方法注册)-->
            <mapper resource="com.dreamchaser/mapper/BookMapper.xml"/>
    <!--        <package name="com.dreamchaser.mapper"/>-->
        </mappers>
    </configuration>
    

    ④pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>org.example</groupId>
      <artifactId>library</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <name>图书信息管理系统 Maven Webapp</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.5.4</version>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.18</version>
        </dependency>
      </dependencies>
    
      <build>
        <finalName>图书信息管理系统</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
          <plugins>
            <plugin>
              <artifactId>maven-clean-plugin</artifactId>
              <version>3.1.0</version>
            </plugin>
            <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
            <plugin>
              <artifactId>maven-resources-plugin</artifactId>
              <version>3.0.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
            <plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.22.1</version>
            </plugin>
            <plugin>
              <artifactId>maven-war-plugin</artifactId>
              <version>3.2.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-install-plugin</artifactId>
              <version>2.5.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-deploy-plugin</artifactId>
              <version>2.8.2</version>
            </plugin>
          </plugins>
        </pluginManagement>
          <plugins>
              <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <configuration>
                      <source>8</source>
                      <target>8</target>
                  </configuration>
              </plugin>
          </plugins>
    
          <resources>
          <resource>
            <directory>src/main/java</directory>
            <includes>
              <include>**/*.xml</include>
              <include>**/*.properties</include>
            </includes>
          </resource>
          <resource>
            <directory>src/main/resources</directory>
            <includes>
              <include>**/*.xml</include>
              <include>**/*.properties</include>
            </includes>
          </resource>
        </resources>
      </build>
    </project>
    
    

    七、部分测试结果展示

    1.Sql模式

    在这里插入图片描述

    ①录入信息:

    在这里插入图片描述

    ②图书信息浏览

    在这里插入图片描述

    ③插入图书信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fjBQlm3d-1592834754202)(media/image26.png)]{width="5.766666666666667in" height="4.794444444444444in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aH4ifBAq-1592834754203)(media/image27.png)]{width="5.768055555555556in" height="4.034027777777778in"}

    注:因为我数据库里的时钟设置的是UTC

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2gnHtt4j-1592834754204)(media/image28.png)]{width="5.558333333333334in" height="0.25in"}

    所以存储的日期比我输入的日期提早一天

    ④查询,以按价格查询(小于)为例

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MgOCow8g-1592834754206)(media/image30.png)]{width="4.525in" height="6.2in"}

    ⑤排序,以按价格排序为例

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BO1iCREb-1592834754206)(media/image31.png)]{width="5.766666666666667in" height="6.126388888888889in"}

    ⑥修改图书信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-isAdUUHz-1592834754208)(media/image32.png)]{width="5.768055555555556in" height="5.129861111111111in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ELFMT4xw-1592834754208)(media/image33.png)]{width="5.768055555555556in" height="4.222916666666666in"}

    ⑦删除图书信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kcMsEHdY-1592834754209)(media/image34.png)]{width="4.25in" height="4.183333333333334in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jga4kSbf-1592834754210)(media/image35.png)]{width="5.763194444444444in" height="4.084722222222222in"}

    ⑧导出为文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-emBgVxoe-1592834754210)(media/image36.png)]{width="4.133333333333334in" height="3.941666666666667in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MlGT7mHX-1592834754212)(media/image37.png)]{width="3.683333333333333in" height="4.016666666666667in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4QIAIPtj-1592834754213)(media/image38.png)]{width="5.756944444444445in" height="3.3340277777777776in"}

    2.noSql模式

    NoSql模式与Sql模式区别只是底层实现原理不同,其测试效果是几乎一致的,在此,就只展现该模式的部分功能

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gyhdh4AS-1592834754213)(media/image39.png)]{width="3.675in" height="3.2583333333333333in"}

    ①插入图书信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bbcx53IR-1592834754214)(media/image40.png)]{width="5.7652777777777775in" height="4.627777777777778in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vi6EX8P0-1592834754215)(media/image41.png)]{width="5.763194444444444in" height="3.5729166666666665in"}

    其余功能就不展示测试效果图了,其效果和Sql模式是一致的。

    八、调试过程中的主要问题、难点以及解决过程

    实话说,在调试的过程中我遇到了很多问题,也查阅了很多技术博客,这之中有些确实能解决问题,而有些则是查阅了很多博客,尝试了很多方法还是没能解决问题,或者说出现了另一个问题,对此,我也渐渐摸索出了一套查找解决bug的方法,收获还是蛮大的。

    以下列举了我调试中的几个主要问题和解决过程。

    1.如何组织各个模块?

    我一开始是采用递归循环的方式,但仔细一想,不对!经过我不断调试改进,最终用"套娃"的方式解决了问题,详细思路可以回到 第五部分、主要功能模块的算法流程图 去查看。

    2.如何让整个项目有条不紊,井然有序?

    整个项目累计代码总量超过千行,如果代码之间逻辑不清晰,关系复杂,那么这个项目调试,后期维护将变得举步维艰。

    那么如何做到有条不紊,井然有序呢?

    首先要做到项目结构清晰,可以像下面这样,实体类和实体类放在一起,工具类单独放在一起,资源配置文件放在一起,做到项目结构条理清晰。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eb1kZj8d-1592834754216)(media/image42.png)]{width="4.166666666666667in" height="5.916666666666667in"}

    其次,要做到代码封装抽象,具体做法就是把复用性高的代码抽离出来,封装成一个工具类,比如我要每个模块都有打印图书信息结果的需求,那么我们完全可以把它封装起来,比如这里我就把它封装成Displayer工具类,其内部有两个方法,如下图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UfhixQRw-1592834754217)(media/image43.png)]{width="5.7659722222222225in" height="4.5055555555555555in"}

    可以看到Displayer类有两个方法,但方法名其实都是show,只是针对不同情况进行重载,让方法用起来更加方便。这里还有个小细节,就是方法都是采用静态的方式,因为这里并没有要初始化的数据,所以采用静态,这样可以让代码调用的时候并不需要实例化即可调用其内的方法,让工具类使用起来就更加方便。

    3.Maven项目,Mybatis框架,IDEA 的坑

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FFHKe28f-1592834754218)(media/image44.png)]{width="5.949305555555555in" height="3.3833333333333333in"}

    上图是我在调试遇到的一个问题,可以看到程序报了Mapped Statements collection does not contain value for xxx的异常,这很明显是mybatis框架报的异常,通过报错信息大概猜测是mybatis XXX容器内不包含我写的Mapper(因为那时候我还不知道Mapped Statement是什么东西),然后我就无脑将这段报错信息贴到百度上搜,确实有很多博客记录了此错误及解决方法,我截了一个下来,如图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3jIQMgpS-1592834754218)(media/image45.png)]{width="5.761805555555555in" height="3.923611111111111in"}

    但实际上我按照博客上一个个去做,并没有解决问题,这时候我已经花了一个下午时间去查找,问题没解决,倒是把mybatis框架复习了一遍。

    苦思之下,我开始逐步调试,以下是我的思考过程:

    因为问题肯定出在mybatis框架上,所以我逐步调试,但是呢,我又不懂mybatis源码,看得云里雾里。不过我之前自学Java的时候,跟着视频写过一个类似mybatis的框架------SORM框架(不过功能肯定没mybatis框架复杂,是个小型版的框架),做完后学了其他知识后,自己又回头帮它迭代优化了一下,增加了新的功能,优化了结构。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xgD3bEPv-1592834754219)(media/image46.png)]{width="5.7652777777777775in" height="2.5256944444444445in"}

    这段经历让我能大概理解mybatis框架的一些行为,比如在这个地方我就注意到了mappedStatement对象size为0。这时我就猜测这应该是框架本身并没有读取到我写的sql语句,那是由什么造成的呢?

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lhLJdZAA-1592834754220)(media/image47.png)]{width="7.3493055555555555in" height="4.134722222222222in"}

    这时候我就开始测试,不用接口类的方式(因为创建实体类也是mybatis框架底层做的),为了缩小问题的范围,我们采用原始的方式(但不是原生jdbc),发现还是这个错误,然后我开始怀疑mapper注册问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-935VOvTl-1592834754221)(media/image48.png)]{width="3.7333333333333334in" height="0.2916666666666667in"}

    这里我原本是采用包扫描的方式注册,然后我开始尝试用指定路径文件方式去注册

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xOySgCVz-1592834754221)(media/image49.png)]{width="5.716666666666667in" height="0.375in"}

    然后异常变了,说找不到这个文件

    好家伙,之前包扫描的时候报的是Mapped Statements collection does not contain value for xxx,现在直接报没找到这个文件!

    这时候我就开始思考为什么?

    为什么我用包扫描的方式就不报错呢?而用具体的文件路径就报错呢?

    真的是包扫描时找到了xml文件而具体文件路径没找到吗?

    不对,不是这样的,换个角度讲,包扫描没扫描到,会报错吗?不会,那问题区间缩小,很可能就是因为xml文件路径的问题。而其他配置文件是找到了的,不然它根本不会提示找不到(路径是写在mybatis-config.xml文件里的),既然我们确定了问题所在,这时候我们就需要尝试改变路径

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OzSr4kNB-1592834754222)(media/image50.png)]{width="5.759722222222222in" height="3.2402777777777776in"}

    这时候我再去查博客,搜索的不是异常信息,而是配置文件的路径该怎么写?

    在搜索的过程中我逐渐意识到我的项目结构可能与别人不同,所以我在搜索时加了Maven限定词,好家伙,不搜不知道,一搜我找到了原因所在。

    原来Maven项目编译时会把文件全都输出到Target文件夹下面

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c5SmxUUw-1592834754223)(media/image51.png)]{width="3.2083333333333335in" height="2.625in"}

    而默认情况下配置文件只会把resource文件夹下面的配置文件输出,这就造成Java文件夹下面的Mapper文件根本不会输出到target里,这样当然就找不到了,于是我修改了Maven项目中核心配置文件pom.xml信息,加入了下面的配置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z36E0Xmk-1592834754224)(media/image52.png)]{width="4.45in" height="3.558333333333333in"}

    然后呢?

    还是找不到…

    本着不抛弃不放弃的精神,我开始关注target文件夹的文件结构

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nPRweG5A-1592834754225)(media/image53.png)]{width="4.216666666666667in" height="4.65in"}

    什么,居然有两个com.dreamchser,这是为什么呢?

    然后我开始测试加百度,然后发现了IDEA的神坑之处------当我们创建一个包时,com.dreamchser和com/dreamchaser是不同的!

    com.dreamchaser就是指第二个圈里的包,com/dreamchaser指的是第一个圈里的包

    .和/的差别真的是坑死我我了!

    我仔细思考了下,之前查询博客的时候,确实有博客提到idea中创建包时/和.是不一样,但当时我以为我的mapper是被读取进去了,所以没在意,只是检查了其他部分,知道后面调试运行底层源码时MappedStatement这个对象的size=0,通过字面意思猜测mybatis实际上是没有读取进去的,进而开始了这方面的排查,最终找到了原因。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p0USVokk-1592834754227)(media/image54.png)]{width="5.759722222222222in" height="3.2402777777777776in"}

    如果用使用动态代理改造CRUD的方式,用接口实现,这意味着接口路径要和xml中那么namespace中的值一致,而在mybatis配置中mapper注册的时候路径要写的是被打包进target/classes下的路径,注意.和/ 的区别

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N0EWl5HT-1592834754228)(media/image55.png)]{width="5.767361111111111in" height="1.9770833333333333in"}

    这次经历让我明白了该如何去解决问题。要解决问题的前提就是要知道问题的原因,需要定位问题,而不是报个错就盲目复制粘贴报错报错信息去搜博客,这确实可能会让你解决问题,但是有很大几率是你搜遍了网上的解决方式也没有解决问题,因为通常一个框架的同一个异常其实是有很多原因,你就会像无头苍蝇那样乱转,运气好可能会解决问题,运气不好就会到处碰壁。

    九.必做题和附加题

    1.必做题

    此部分另外已提交,就不在此赘述了

    2. 附加题

    ①题目要求

    要求写出算法思想和代码

    编写三个函数分别实现高精度加法、减法和乘法运算。在主函数中输入任意两个很大的正整数,可根据菜单提示,反复选择相应的操作进行计算。

    菜单:1、输入任意两个正整数

    2、高精度加法

    3、高精度减法

    4、高精度乘法

    0、退出

    ②算法思想

    我们知道正常的类型是无法存储这种大数值的,这里我们采用两个String来存储两个正整数,然后模拟我们平常计算加减乘除的过程来写代码,对每一位分别处理,最终得到我们想要的结果。

    ③代码

    package com.dreamchaser;
    
    import java.util.Scanner;
    
    public class Main {
        static Scanner scanner = new Scanner(System.in);
        static String s1 = "";
        static String s2 = "";
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            while (true) {
                if (choosePattern(1) == 1) {
                    break;
                }
            }
        }
    
        private static int choosePattern(int i) {
            if (i == 1) {
                System.out.println("\n\n1.输入任意两个正整数");
                System.out.println("2.高精度加法");
                System.out.println("3.高精度减法");
                System.out.println("4、高精度乘法");
                System.out.println("0、退出");
                System.out.println("\n\n请输入你的选择(序号):");
            }
            switch (scanner.nextInt()) {
                case 1:
                    //吃掉回车
                    scanner.nextLine();
                    print();
                    return 0;
                case 2:
                    add();
                    return 0;
                case 3:
                    delete();
                    return 0;
                case 4:
                    multiplication();
                    return 0;
                case 5:
                    return 1;
                default:
                    System.out.println("抱歉,输入的是非法字符,请重新输入:");
                    return choosePattern(0);
            }
        }
    
        private static void multiplication() {
            //表示进位
            int i, j, k;
            int[] c = new int[202];
            s1 = new StringBuilder(s1).reverse().toString();
            s2 = new StringBuilder(s2).reverse().toString();
            for (i = 0; i < s1.length(); i++) {
                for (j = 0; j < s2.length(); j++) {
                    c[i + j] += (s1.charAt(i) - 48) * (s2.charAt(j) - 48);
                }
            }
            for (k = 1; k <= s1.length() + s2.length(); k++) {
                c[k] += c[k - 1] / 10;
                c[k - 1] %= 10;
            }
    
            while (c[k] == 0 && k >= 1) {
                k--;
            }
            for (; k >= 0; k--) {
                System.out.print(c[k]);
            }
            System.out.println();
    
        }
    
        private static void delete() {
            //表示进位
            int i, j, r = 0, k = 0;
            boolean flag = true;
            int[] c = new int[101];
            for (i = s1.length() - 1, j = s2.length() - 1; j >= 0; i--, j--) {
                //两个位数相减再减去接的位数
                c[k++] = (s1.charAt(i) - s2.charAt(j) - r);
                //清零标记
                r = 0;
                if (c[k - 1] < 0) {
                    c[k - 1] += 10;
                    r = 1;
                }//如果是负数就借十,并标记
            }
            //剩下的继续减
            while (i >= 0) {
                //减去借的
                c[k++] = (s1.charAt(i) - '0' - r);
                //清零标记
                r = 0;
                //如果是负数就借十,并标记
                if (c[k - 1] < 0) {
                    c[k - 1] += 10;
                    r = 1;
                }
                i--;
            }
            //输出
            for (i = k - 1; i >= 0; i--) {
                //防止前导0输出的操作
                if (c[i] != 0 || flag) {
                    System.out.print(c[i]);
                    flag = true;
                }
            }
            //如果都没有输出,说明相减结果为0,应当输出0
            if (flag == false) {
                System.out.print(0);
            }
            System.out.println();
    
        }
    
        private static void add() {
            //表示进位
            int i, j, r = 0, k = 0;
            boolean flag = true;
            int[] c = new int[101];
            //从最低位相加,相加他们的公共部分,所以j>=0
            for (i = s1.length() - 1, j = s2.length() - 1; j >= 0; i--, j--) {
                //两个位数和进位的相加后取个位
                c[k++] = (r + s1.charAt(i) - '0' + s2.charAt(j) - '0') % 10;
                //记录进位
                r = (r + s1.charAt(i) - '0' + s2.charAt(j) - '0') / 10;
            }
            //再把剩下的继续加
            while (i >= 0) {
                //位数和进位的相加后取个位
                c[k++] = (r + s1.charAt(i) - '0') % 10;
                //记录进位
                r = (r + s1.charAt(i) - '0') / 10;
                i--;
            }
            //如果还有进位,进到最高位
            if (r != 0) {
                c[k++] = r;
            }
            //输出
            for (i = k - 1; i >= 0; i--) {
                //防止前导0输出的操作
                if (c[i] != 0 || flag) {
                    System.out.print(c[i]);
                    ;
                    flag = true;
                }
            }
            if (flag == false) {
                System.out.print(0);
            }
            System.out.println();
        }
    
        private static void print() {
            System.out.println("请输入第一个整数:");
            s1 = scanner.nextLine();
            System.out.println("请输入第二个整数:");
            s2 = scanner.nextLine();
            //把大的字符串放前面,方便操作
            if (s1.length() < s2.length() || (s1.length() == s2.length() && s1.compareTo(s2) > 0)) {
                String temp = "";
                temp = s1;
                s1 = s2;
                s2 = temp;
            }
        }
    
    }
    

    ④测试结果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iKZlSIsN-1592834754228)(media/image56.png)]{width="2.533333333333333in" height="3.1416666666666666in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gxU7w2uK-1592834754230)(media/image57.png)]{width="2.4833333333333334in" height="2.2583333333333333in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-exS3HWy1-1592834754230)(media/image58.png)]{width="2.4916666666666667in" height="2.5416666666666665in"}

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wzznsxKt-1592834754230)(media/image59.png)]{width="3.591666666666667in" height="2.375in"}

    十、短学期实践的心得体会

    花了三天时间写代码,一天时间写实验报告,总计四天的努力,累计超过千行的代码(确切是1632行,没错,我真的算了!),虽然过程艰辛,但是结果令人满意。

    这个项目是我第一个独立完成的项目!说真的,很多东西你看似会了,但是真正到自己去做项目的时候,会发现很多问题,这个不会,那个不会,最后还是要靠百度解决,毕竟面向百度编程这句话不是可不是白讲的。

    在这个过程中其实我也学到了很多,尤其是关于mybatis框架和Maven的认识更加深入了。而且这个过程中我渐渐形成了一套属于自己代码风格和编程习惯,而且我对于如何去定位查找解决bug也有了更加清晰的认识。

    在这个过程中,我也认识到了自己的很多不足,未来我也要更加扎实的学习,更要尝试去多做项目,这样才能将知识技术化为内在,才能做到真正的融汇贯通,游刃有余!

    谨以此记,共勉!

    软件工程1902 金昊霖

    如果对此项目有什么疑惑或者建议,欢迎在评论区评论。

    ------------------------2020.7.28------------------------------------
    应评论要求,该项目已上传至码云
    推荐我的一些其他博客:
    适合初学Java的人自学的:用我的亲身经历来告诉你如何自学Java?
    适合刚学完SpringBoot的练手项目:【项目实战】个人博客(SpringBoot,SSM,thymeleaf,Semantic UI)——从设计思路到成品

    展开全文
  • 在Word中,如何文本添加如下图所示的项目编号(有序列表)呢? 上图中的文本被添加了4级列表,仅做参考,用来展示项目编号的使用效果。 方法:解决文本添加项目编号的问题 选中文本 点击开始选项卡,找到段落...

    在Word中,如何给文本添加如下图所示的项目编号(有序列表)呢?

    在这里插入图片描述
    上图中的文本被添加了4级列表,仅做参考,用来展示项目编号的使用效果。

    方法:解决给文本添加项目编号的问题
    选中文本
    点击开始选项卡,找到段落分类左上角的编号(在前一张讲到的项目符号右侧)并点击其下拉三角
    选择想要的项目编号即可。

    方法:解决给文本添加多级列表的问题
    在文本已添加了一级列表的基础上
    选中想要成为二级列表的文本
    点击开始选项卡,找到段落分类左上角的编号(在前一张讲到的项目符号右侧)并点击其下拉三角
    点击更改列表级别©
    选择二级列表即可(鼠标停靠会有列表级别显示)

    方法:解决自定义项目编号的问题
    在前两个方法中,可能找不到自己想要的项目编号,例如[1]、<1>、等等,此时需要进行一下操作:
    选中想要更改项目编号的文本
    点击开始选项卡,找到段落分类左上角的编号(在前一张讲到的项目符号右侧)并点击其下拉三角
    点击定义新编号格式(D)…,弹出定义新编号格式对话框
    在**编号样式(N)中选择合适的编号样式(必选)
    下方
    编号格式(O)**中输入想要的格式(不能把原有的编号删掉,只需在其两侧添加或修改符号即可)

    展开全文
  • 1. 能按各种方式(比如书名、编号、作者)查询图书馆的藏书情况。...可以对图书进行的精确、模糊查询并讲查询信息以列表的方式呈现用户,方便用户查找信息,另外,对超期的借阅情况能自动出提示信息。
  • 初学者可以学习下 Big Number Farmer John摘苹果 编号计数 疯狂的赛车 级数求和 绩点计算 津津的储蓄计划 可怜的班长 明明的随机数 奶牛们的图书馆 乒乓球记录 谁拿了最多的奖学金 外星人的信号
  • from inserted select @借证编号=借证编号 from inserted select @图书编号=图书编号 from inserted if @是否续借=0 begin update 借阅 set 还日期=@新还日期 where 借证编号=@借证编号 and 图书编号=@...
  • 当我们在进行大篇幅word文档的编写时,为了节约修改文章中图片所花费的大量时间,可以将图片自动编号,且让文中引用的顺序跟着图片顺序的变化而变化,具体操作如下: 1.将鼠标定在欲加编号的下方,点击“引用”→...
  • LaTeX参考文献不加编号

    千次阅读 2021-03-11 08:51:25
    主要是在投稿论文的时候,有一些期刊要求参考文献不加编号,但是在期刊所的模板中,却没有参考文献的代码。上一次自己在编写不加编号的参考文献的时候找了很久的资料没有完整版的,浪费了很多时间,故记下来。 我...
  • Word2016创建多行公式,多行公式在等号处对齐,创建自动编号和引用,多行公式居中,编号右对齐
  • 如题,在latex项目中有时候需要制作表格,比如需要罗列出几十种最新的研究技术(每一行对应一个技术),如果能够自动编号,那就可以不断更新,而且不用担心序号要重新排。 本文旨在解决此问题。
  • 代码采用Spring+SpringMVC+Mybatis主流设计模式,实现了如下功能,数据库采用的是mysql数据库。 根据用户的不同,功能可分为如下: 图书管理员:登录:以图书...查看借阅记录:可以根据读者学号以及图书编号查询...
  • (1)对于读者在本系统的应用下可实现按照各种方式(如:书名,编号,作者)查询图书馆的藏书请客,方便的借阅图书,续借图书,归还图书,能够查询自己的借阅图书情况。 (2)对于图书馆工作人员能够实现方便的对图书进行查询,...
  • 图书馆管理系统设计说明

    万次阅读 多人点赞 2014-11-06 12:59:28
    文档信息:图书馆信息管理系统软件设计说明 文档类别:管理文档 密 级:机密 版本信息:1.0 建立日期:2014-05-20   创 建 人: 审 核 者: 批 准 人: 批准日期:   编辑软件:Microsoft ...
  • 图书馆管理系统需求规格说明

    万次阅读 多人点赞 2014-11-06 13:07:14
    文档信息:图书馆信息管理系统软件需求规格说明 文档类别:管理文档 密 级:机密 版本信息:1.0 建立日期:2014-05-20   创 建 人: 审 核 者: 批 准 人: 批准日期:   编辑软件:Microsoft Office ...
  • 课程报告 课程名称 程序设计实践 专业班级 信息类1107 学生姓名 王春平 学 号 201116910730 任课教师阎娟 学 期2011-2012学年第二学期 题 目 图书信息管理系统 开发一个图书信息管理系统图书信息包括图书编号书名 ...
  • 今天修改了论文封皮里面的国内图书分类号和国际图书分类号,...如果想自己找的话可以在下面的网址里面去找: 中图分类号查询 中国图书馆分类法 里面类似于目录,是一级一级的形式,你选择一个大的领域之后,会进...
  • (4)先正文中的上标批量添加[ ]。选中正文后,按下Ctrl+H键,调出Word的【查找-替换】功能。然后在查找框中输入“ ^e ”,替换框中输入“ [^&]” 。之后点击【全部替换】即可完成设置。 (5)修改参考文献列表...
  • LATEX之自定义编号列表

    千次阅读 2020-08-22 16:51:19
    自定义编号列表 \documentclass[a4paper]{ctexart} \usepackage{ctex} \usepackage{xeCJK} %导入这个宏包,就可以支持中文 \usepackage{enumitem}[inline] \usepackage{ulem} \begin{document} %编号列表的自定义...
  • 图书馆里系统

    2012-11-25 10:55:43
    数据存储:利用IO操作类(文件的读写)来实现数据的保存 ... 该系统分为表现层,业务逻辑层和DAO层,采用MVC的设计模式来实现该图书管理系统,用户只要在界面输入图书编号就能查询你想要的图书信息。
  • 图书馆管理系统测试计划说明

    万次阅读 多人点赞 2014-11-06 13:03:05
    文档名称:图书馆信息管理系统软件测试计划 密 级:秘密 版本信息:0.01 建立日期:2013-11-06   创 建 人: 审 核 者: 批 准 人: 批准日期:     编辑软件:Microsoft Office 2007 ...
  • 图书:图书编号,书名,作者,出版社,出版日期,库存,图书标签(唯一),ISBN,借阅次数 借者:借者编号,姓名,账号,密码 借书记录:借出日期,期望归还日期,实际归还日期,图书ISBN,借者编号 罚款记录...
  • Vue 实现 图书管理 案例

    千次阅读 热门讨论 2021-01-19 15:07:07
    案例效果 案例思路 图书列表 实现静态列表效果 基于数据实现模板效果 处理每行的操作按钮 ...添加图书 ...添加图书表单域数据绑定 ...侦听器(验证图书编号的存在性) 生命周期(图书数据处理) 代码 基本
  • 一本n页的页码连续编号,则数字0到9在页码中各出现多少次?用c++编程,n自己输入,多次数据:代码如下: #include #include #include using namespace std; void statNum(long long sn[10], long long n) { ...
  • 目录 1 需求分析 3 1.1 系统目标 3 1.2 需求定义 3 ...可以对图书进行的精确、模糊查询并讲查询信息以列表的方式呈现用户,方便用户查找信息,另外,对超期的借阅情况能自动出提示信息。 系统功能结构图
  • 图书借阅项目练习

    万次阅读 多人点赞 2021-06-15 08:23:00
    现在需要该生设计“书籍借阅管理系统”来实现该生对自己书籍的借阅信息的管理。程序操作者为学生本人,无需登录 需要实现的整体功能: 查询书籍信息列表 查询借书信息列表 新增借书信息 还 各省各专业所...
  • Access应用实例——图书借阅管理系统

    万次阅读 多人点赞 2019-06-15 20:00:25
    图书借阅管理系统主要实现对图书管工作的信息化管理,本系统实现对图书的基本信息和会员(图书借遇者)的基本信息的登记,保存,统计,和查询等功能,另外还对会员的借阅信息进行了登记,保存,统计并能查询,同时...
  • 正文涉及章节编号,图表编号,代码段,补充说明内容,脚注,等等。 以下各种方式联系我们 绝对你是想立马着手写一本,还是1年3年5年后抑或在未来不确定的某一天,想写一本,请随时联系我们。你可以通过以下多种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 61,601
精华内容 24,640
关键字:

如何给自己的书编号