图书馆系统源码详解

本项目是一个基于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
  • 存储用户信息的文本文件。

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

总结

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

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

相关推荐
阿祖zu8 分钟前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
松仔log15 分钟前
Java中级——组合和继承
android·java·开发语言
不才不才不不才17 分钟前
Spring 源码系列(16): doDispatch 全流程——一次请求的主干链路
java·后端·spring
IT_陈寒24 分钟前
SpringBoot自动配置失效?这个隐藏配置坑了我一整晚
前端·人工智能·后端
搜狐技术产品小编202339 分钟前
告别“黑盒”与误判:如何用“多智能体对抗辩论”重构内容安全审核系统
后端·多agent
DantyWei1 小时前
controller注册及调用时机
后端
edwarddamon1 小时前
Spring Cloud 配置热更新与 Bean 代理机制梳理
java·后端
码事漫谈2 小时前
我用 Seed Evolving 做了个 AI 小说写作工具
后端
Raas1002 小时前
MAIGateway,魔芋企业级AI网关的FinAPI成本竞争力设计
java·后端·网关·api网关·魔芋ai·finapi·mai gateway
(Charon)2 小时前
【C++】锁与原子操作(四):自旋锁的完整实现与性能优化
c语言·开发语言·c++