图书馆系统源码详解

本项目是一个基于Scala语言开发的图书馆管理系统。系统主要由以下几个部分组成:数据访问层(DAO)、数据模型层(Models)、服务层(Service)以及用户界面层(UI)。以下是对项目中各个文件和文件夹的详细解释。

项目目录结构

复制代码
scala_tushu2/
│
├── .idea/               # IntelliJ IDEA的项目配置文件夹
├── out/                 # 编译输出文件夹
├── src/                 # 源代码文件夹
│   ├── dao/             # 数据访问层
│   ├── models/          # 数据模型层
│   ├── service/         # 服务层
│   └── ui/              # 用户界面层
├── scripts/             # 脚本文件夹
├── scala_tushu2.iml     # IntelliJ IDEA的模块文件
├── books.txt            # 图书信息文件
├── borrow_records.txt    # 借阅记录文件
└── users.txt            # 用户信息文件

详细文件解释

1. 数据访问层(DAO)

文件:BookDAO.scala
  • 负责图书信息的增删改查操作。
  1. 提供与数据库交互的方法,如添加新书、删除书籍、更新书籍信息和查询书籍。

    Scala 复制代码
    package app.org
    package dao
    
    import models.BookModel
    
    import java.io.File
    import scala.collection.mutable.ListBuffer
    
    // 图书,数据操作
    class BookDAO {
      // 加载图书,从件中读入
      def loadBooks(): ListBuffer[BookModel] = {
        val books = new ListBuffer[BookModel]()
        val source = scala.io.Source.fromFile("books.txt")
        for (line <- source.getLines()) {
          val Array(id, name, author, available) = line.split(",")
          // 实例化一本书,保存到List中
          books += BookModel(id.toInt, name, author, available.toBoolean)
        }
        // 关闭连接
        source.close()
        books
      }
    
      // 保存图书,将图书写入文件
      def saveBooks(books: ListBuffer[BookModel]): Unit = {
        val writer = new java.io.PrintWriter(new File("books.txt"))
        for (book <- books) {
          writer.println(book.id + "," + book.name + "," + book.author + "," + book.available)
        }
        writer.close()
      }
    }
文件:BorrowRecordDAO.scala
  • 负责借阅记录的增删改查操作。

  • 提供与数据库交互的方法,如添加借阅记录、删除记录、更新记录和查询记录。

Scala 复制代码
package app.org
package dao

import models.BorrowRecordModel

import java.io.PrintWriter
import scala.collection.mutable.ListBuffer
import scala.io.Source

class BorrowRecordDAO {
  // 读出借阅记录
  def loadBorrowRecord(): ListBuffer[BorrowRecordModel] = {
    val borrowRecords =  ListBuffer[BorrowRecordModel]()
    val lines = Source.fromFile("borrow_records.txt")
    for (line <- lines.getLines()) {
      val parts =line.split(",")

      borrowRecords += BorrowRecordModel(
        parts(0),
        parts(1).toInt,
        parts(2),
        parts(3),
        if (parts.length>4) Some(parts(4)) else None
        )
    }
    borrowRecords
  }

  // 写入借阅记录
  def saveBorrowRecord(records: ListBuffer[BorrowRecordModel]): Unit = {
    val writer = new PrintWriter("borrow_records.txt")
    for (record <- records) {
      writer.println(record.userName + "," + record.bookID + "," + record.bookName + "," + record.borrowDate + "," + record.returnDate.getOrElse(""))
    }
    writer.close()
    }
}
文件:UserDAO.scala
  • 负责用户信息的增删改查操作。

  • 提供与数据库交互的方法,如添加新用户、删除用户、更新用户信息和查询用户信息。

Scala 复制代码
package app.org
package dao

import models.UserModel

import java.io.File
import scala.collection.mutable.ListBuffer

class UserDAO {
  //加载所有的用户
  def loadUsers(): ListBuffer[UserModel] = {
    val users = new ListBuffer[UserModel]()
    val source = scala.io.Source.
      fromFile("users.txt")
    for (line <- source.getLines()) {
      val Array(username,password,role) = line.split(",")
      // 实例化一用户,保存到List中
      users += UserModel(username,password,role)
    }
    // 关闭连接
    source.close()
    users
  }

  //保存用户
  // 保存图书,将图书写入文件
  def saveUsers(users: ListBuffer[UserModel]): Unit = {
    val writer = new java.io.PrintWriter(new File("users.txt"))
    for (user <- users) {
      writer.println(user.username + "," + user.password + "," + user.role)
    }
    writer.close()
  }
}

2. 数据模型层(Models)

文件:BookModel.scala
  • 定义图书的数据模型。

  • 包含图书的属性,如ID、书名、作者、是否可借等。

Scala 复制代码
package app.org
package models

// 图书类
// id,书名,作者,状态
case class BookModel(id: Int, name: String, author: String, var available: Boolean) {
  override def toString: String ={
    val availableStr = if (available) "可外借" else "已借出"
    s"编号:$id \t 书名: $name \t 作者:$author \t 这本书------$availableStr"
  }
}
文件:BorrowRecordModel.scala
  • 定义借阅记录的数据模型。

  • 包含借阅记录的属性,如用户ID、书籍ID、借阅时间、归还时间等。

Scala 复制代码
package app.org
package models

case class BorrowRecordModel(
                            userName:String,               // 借书人
                            bookID:Int,                  // 图书ID
                            bookName:String,           // 书名
                            borrowDate:String,          // 借阅日期
                            var returnDate:Option[String] =None   // 归还日期
                            )
文件:UserModel.scala
  • 定义用户的数据模型。

  • 包含用户的属性,如ID、用户名、密码、用户类型(管理员或普通用户)等。

Scala 复制代码
package app.org
package models

case class UserModel(
                    username:String,
                    password:String,
                    role:String
                    )

3. 服务层(Service)

文件:BookService.scala
  • 提供图书相关的业务逻辑。

  • 调用DAO层的方法,实现图书的增删改查等业务操作。

Scala 复制代码
package app.org
package service

import models.{BookModel, BorrowRecordModel}
import dao.{BookDAO, BorrowRecordDAO}

import java.time.LocalDateTime
import scala.collection.mutable.ListBuffer

// 图书业务逻辑层
class BookService {
  private val bookDAO = new BookDAO()
  private val borrowRecordDAO = new BorrowRecordDAO()
  // 查询所有的图书
//  def searchBooks(query:String): 图书列表List(Book对象)
  def searchBooks(query:String): ListBuffer[BookModel] = {
    // 从文本文件中读取书本信息,并保存列表中,返回
    val books = bookDAO.loadBooks()
    query match {
      case "" => books  // 没有条件,就返回全部
      case _ => books.filter(b => b.name.contains(query) || b.author.contains(query))  // 根据条件过滤
    }
  }

  // 普通用户,借阅图书
  def borrowBook(username:String,bookId:Int): Boolean = {
    //   (1) 根据图书的ID,查询图书, 判断图书是否存在
    val books = bookDAO.loadBooks()
    val records = borrowRecordDAO.loadBorrowRecord()
    val book = books.find(b => b.id == bookId)
    if (book.nonEmpty) {
      val b = book.get
      //   (2) 判断图书是否已经被借出
      if (b.available) {
        //   (3) 借阅图书
        //        更新这本书的状态
        b.available = false
        // 把更新之后的图书的信息写回txt文件中
        bookDAO.saveBooks(books)
        //    TODO    添加一条借书记录
        // 读出当前全部的记录
        // 添加一条记录
        records += BorrowRecordModel(username,b.id,b.name,LocalDateTime.now().toString)
        // 写回txt文件中
        borrowRecordDAO.saveBorrowRecord(records)
        println("借阅成功,已保存借阅记录!!!")
        true
      } else {
        println("这本书已经被借走了!!!")
        false
      }
    } else {
      false
    }
  }

  // 普通用户,查询自己的借阅记录
  def queryBorrowRecords(username: String):ListBuffer[BorrowRecordModel] = {
    // 读出全部的借阅记录
    val records = borrowRecordDAO.loadBorrowRecord()
    // 过滤出当前用户的借阅记录
    records.filter(r => r.userName == username)

  }

  // 普通用户,归还自己借的某一本书
  def returnBook(username: String, bookId: Int): Boolean = {
    // 1.确定这本书是他本人借的并归还处于没有归还的状态
    queryBorrowRecords(username).find(r => r.bookID == bookId && r.returnDate.isEmpty) match {
      case Some(record) =>
        // 2.更新这本书的状态
        // 2.1 加载全部的图书信息
        val books = bookDAO.loadBooks()
        // 2.2选择当前这一本书
        val b = books.find(_.id == bookId).get
        b.available = true
        // 2.3 把更新之后的状态写回txt文件中
        bookDAO.saveBooks(books)
        // 3.更新借阅记录的状态
        // 3.1 加载全部的借阅记录
        val records = borrowRecordDAO.loadBorrowRecord()
        // 3.2 找到当前这本书的借阅记录
        val r = records.find(r => r.bookID == bookId && r.userName ==username && r.returnDate.isEmpty).get
        r.returnDate = Some(LocalDateTime.now().toString)
        // 3.3 把更新之后的状态写回txt文件中
        borrowRecordDAO.saveBorrowRecord(records)
        true
      case None => false
    }
  }

  // 添加图书
  def addBook(book: BookModel): Unit = {
    // 1. 生成一个book ID
    // 查询所有的图书,找到最大的ID,+1
    var id = 1
    val books = bookDAO.loadBooks()
    if (books.nonEmpty) {
      id = books.map(_.id).max + 1
    }
    // 2. 更新
    val newBook = book.copy(id = id)
    // 3. 把新的图书添加到books.txt中
    books += newBook
    // 4. 把更新之后的状态写回txt文件中
    bookDAO.saveBooks(books)
  }

  private def queryBooks(): ListBuffer[BookModel] = {
    // 1. 加载全部的图书
    val books = bookDAO.loadBooks()
    // 2. 返回
    books
  }

}
文件:UserService.scala
  • 提供用户相关的业务逻辑。

  • 调用DAO层的方法,实现用户的增删改查等业务操作。

Scala 复制代码
package app.org
package service

import dao.UserDAO

import models.UserModel

class UserService {
  private val userDAO = new UserDAO()
  // 身份校验
  def authenticateUser(username: String, password: String): Option[UserModel] = {
    // 去根据用户名和密码查询,是否有符合要求的用户
    val users = userDAO.loadUsers()
    users.find(user => user.username == username && user.password == password)
  }

  // 注册用户
  def addUser(username: String): Boolean = {
    // 1. 查询用户名是否已经存在
  val users = userDAO.loadUsers()
  val user =users.find( _.username == username)
    if (user.isEmpty) {
      // 可以继续添加
      // 2.添加
      // 2.1 读取所有的用户
      // 2.2 创建新的用户
      users += UserModel(username, "[\\d]", "普通用户")
      // 2.3 保存用户
      userDAO.saveUsers(users)
      true
    } else {
      false
    }
  }
}

4. 用户界面层(UI)

文件:LPT.scala
  • 提供用户界面的实现。

  • 负责与用户的交互,如显示图书列表、显示借阅记录、用户登录等。

Scala 复制代码
package app.org
package ui

import models.{BookModel, UserModel}
import service.{BookService, UserService}

import scala.io.StdIn
import scala.io.StdIn.readLine

class LPT {

  private val BookService = new BookService()
  private val UserService = new UserService()

  // 辅助方法: 输入图书的信息,返回一个BookModel对象
  private def inputBookInfo(): BookModel = {
    println("请输入图书的名称:")
    val name = readLine().trim
    println("请输入图书的作者:")
    val author = readLine().trim
    println("请输入图书是否可以外借(true/false):")
    val available = StdIn.readBoolean()
    // 初始设置编号为0
    BookModel(0,name, author, available)
  }
  // 显示游客的菜单
  def showVisitorMenu(): Unit = {
    var running = true
    while (running) {
      println("欢迎来到我的图书管理系统,请选择:")
      println("1. 查看所有图书")
      println("2. 查询图书")
      println("3. 登录")
      println("4. 退出")

      // 获取用户操作
      val choice = StdIn.readLine().trim
      choice match {
        case "1" =>
          // 调用业务逻辑层的方法
          val results = BookService.searchBooks("")
          if (results.nonEmpty) {
            results.foreach(println)
          } else {
            println("没有找到图书")
          }
        case "2" =>
          // 提示用户输入查询关键字
          val query = readLine("请输入查询关键字:").trim
          // 根据关键字去查询图书列表,找到满足条件的书
          val results = BookService.searchBooks(query)
          // 显示出来
          if (results.nonEmpty) {
            println("=================查询图书的结果结果====================")
            results.foreach(println)
          } else {
            println("没有找到图书")
          }


        case "3" =>
          println("请输入用户名:")
          val username = StdIn.readLine().trim
          println("请输入密码:")
          val password = StdIn.readLine().trim
          // 调用service的方法,进行登录
          val userOPT =UserService.authenticateUser(username, password)
          if (userOPT.isEmpty) {
            println("用户名或密码错误")
          } else {
            // 登录成功,显示登录用户的菜单
            val user = userOPT.get
            user.role match {
              case "管理员" => showAdminMenu(user)
              case "普通用户" => showUserMenu(user)
            }
          }

        case "4" =>
          running = false
          println("感谢你的使用,下次再见")
        case _ => println("无效的选择,请重新输入")
      }
    }
  }

  // 显示管理员的菜单
  def showAdminMenu(user: UserModel): Unit = {
    var running = true
    while (running) {
      println(s"欢迎管理员${user.username}来到我的图书管理系统,请选择:")
      println("1. 添加图书")
      println("2. 查询图书")
      println("3. 添加用户")
      println("4. 退出")

      // 获取用户的操作
      val choice = StdIn.readLine().trim
      choice match {
        case "1" =>
          // 1.获取图书信息-书名,作者,状态
          val book = inputBookInfo()
          // 2. 调用service的方法,做添加到books.txt中操作
          BookService.addBook(book)
          println(s"图书《${book.name}》添加成功")
        case "2" =>
          // 提示用户输入查询关键字
          println("请输入查询关键字:")
          val query = readLine().trim
          val results = BookService.searchBooks(query)
          if (results.nonEmpty) {
            println("=================查询图书的结果====================")
            results.foreach(println)
            println("=================以上是查询图书的结果!!!!====================")
            println()
          } else {
            println("没有找到图书")
          }

        case "3" =>
          // 1.获取用户信息-用户名,密码,角色
          val username = StdIn.readLine("请输入用户名:")
          // 2. 调用service的方法,做添加到users.txt中操作
        if (UserService.addUser(username)) {
          println(s"用户${username}添加成功")
        } else {
          println("用户添加失败")
        }
        case "4" => running = false
        case _ => println("无效的选择,请重新输入")
      }
    }
  }



  // 显示登录用户的菜单
  def showUserMenu(user: UserModel): Unit = {
    var running = true
    while (running) {
      println(s"欢迎用户${user.username}来到我的图书管理系统,请选择:")
      println("1. 借阅图书")
      println("2. 查询借阅图书")
      println("3. 还书")
      println("4. 退出")

      // 获取用户的操作
      val choice = StdIn.readLine().trim
      choice match {
        case "1" =>
          // UI : 提示用户输入图书ID。校验:判断是否整数
          try {
            val id = readLine("请输入图书的ID:").toInt
            println(id)
            BookService.borrowBook(user.username,id)
          } catch {
            case e: Exception =>
              println(e)
              println("输入的图书ID无效,请重新输入:")
          }
        case "2" => println("查询图书")
          val borrowRecords = BookService.queryBorrowRecords(user.username)
          //
          if (borrowRecords.isEmpty) {
            println("您还没有借阅过任何图书!!!")
          } else {
            // 打印借阅记录
            println("查询结果,一共借了?本,?本已归还,?本未归还")
            for (record <- borrowRecords) {
              val returnDate = record.returnDate.getOrElse("未归还")
              println(s"用户名:${record.userName},图书ID:${record.bookID},图书名称:${record.bookName},借阅日期:${record.borrowDate},归还日期:$returnDate")
            }
          }
        case "3" => println("还书")
          try {
            val id = readLine("请输入要归还的图书的ID:").toInt
            if(BookService.returnBook(user.username, id)) {
              println("归还图书成功!!!")
            } else {
              println("归还图书失败,请检查输入的图书ID是否正确")
            }
          } catch {
            case e: Exception =>
              println(e)
              println("输入的图书ID无效,请重新输入")
          }
        case "4" => running = false
        case _ => println("无效的选择,请重新输入")
      }
    }
  }

  def showMenu(): Unit = {
    showVisitorMenu()
  }
}

文件:Main.scala

Main.scala 文件是Scala应用程序的入口点,它通常包含 main 函数,该函数是程序执行的起始点。在这个图书馆管理系统中,Main.scala 可能承担以下职责:

  1. 初始化系统:设置系统运行所需的环境,例如初始化数据库连接、加载配置文件等。

  2. 启动服务:启动系统中的服务层,例如图书服务、用户服务等,这些服务可能负责处理业务逻辑。

  3. 用户界面启动:启动用户界面层,例如命令行界面或图形用户界面,允许用户与系统交互。

  4. 运行主循环 :对于需要持续运行的系统,Main.scala 可能包含一个主循环,用于不断监听用户输入或处理后台任务。

  5. 错误处理:设置全局错误处理机制,确保系统在遇到错误时能够优雅地处理并给出用户友好的反馈。

    Scala 复制代码
    package app.org
    
    import ui.LPT
    
    
    
    object Main {
      def main(args: Array[String]): Unit = {
        val m = new LPT()
        m.showMenu()
      }
    }

5. 其他文件

文件:books.txt
  • 存储图书信息的文本文件。

  • 每行包含图书的ID、书名、作者和是否可借的信息。

文件:borrow_records.txt
  • 存储借阅记录的文本文件。

  • 每行包含用户ID、图书ID、借阅时间和归还时间的信息。

文件:users.txt
  • 存储用户信息的文本文件。

  • 每行包含用户的用户名、密码和用户类型(管理员或普通用户)的信息。

总结

本项目通过分层架构实现了一个图书馆管理系统,各层之间职责明确,便于维护和扩展。数据访问层负责与数据库的交互,数据模型层定义了系统中使用的数据结构,服务层实现了具体的业务逻辑,用户界面层负责与用户的交互。通过这种方式,系统具有良好的可读性和可维护性。

# #本项目并不是完美的项目, 嗨有缺少的功能自行添加!!!!!!!!!!!!

相关推荐
我不想当小卡拉米几秒前
C++:继承+菱形虚拟继承的一箭双雕
开发语言·jvm·c++
weixin_457885823 分钟前
JavaScript智能对话机器人——企业知识库自动化
开发语言·javascript·自动化
孤独得猿26 分钟前
Qt常用控件第一部分
服务器·开发语言·qt
uhakadotcom29 分钟前
OpenTelemetry入门:让你的应用程序更透明
后端·面试·github
慕斯策划一场流浪31 分钟前
fastGPT—nextjs—mongoose—团队管理之团队列表api接口实现
开发语言·前端·javascript·fastgpt env文件配置·fastgpt团队列表接口实现·fastgpt团队切换api·fastgpt团队切换逻辑
橘猫云计算机设计37 分钟前
基于springboot的考研成绩查询系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·考研·django·毕业设计
时光呢42 分钟前
JAVA常见的 JVM 参数及其典型默认值
java·开发语言·jvm
橙橙子23043 分钟前
c++柔性数组、友元、类模版
开发语言·c++·柔性数组
程序媛学姐1 小时前
SpringKafka错误处理:重试机制与死信队列
java·开发语言·spring·kafka
有一只柴犬1 小时前
深入Spring AI:6大核心概念带你入门AI开发
spring boot·后端