文章目录
前言
本次学习总结旨在全面回顾和梳理图书馆管理系统的理论知识与实践操作过程。在此过程中,我将分享自己在学习图书馆管理系统时的心得体会。
所用编译器:
后端——IntelliJ IDEA Community Edition 2023.3.4
前端——WebStorm 2023.3.4
数据库——Navicat Premium 15
环境变量:
JDK——corretto-11.0.22
Tomact——apache-tomcat-9.0.86
Node——node-v20.11.1-x64
一、后端搭建
1.项目结构
2.YAML格式配置
# 服务器配置
server:
# 应用程序运行端口
port: 8088
# Spring Boot 数据源配置
spring:
datasource:
# 数据库驱动类名称
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据库连接URL,包括数据库类型、主机地址、端口号、数据库名及连接参数
url: jdbc:mysql://localhost:3306/vocation?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
# 数据库用户名
username: root
# 数据库密码
password: root
# 数据源类型,这里指定为阿里巴巴开源的Druid数据源
type: com.alibaba.druid.pool.DruidDataSource
# MyBatis 配置
mybatis:
# 映射器配置文件位置,使用通配符加载指定路径下所有.xml映射文件
mapper-locations: classpath:com/kun/web/mapper/*.xml
3.Web应用程序的启动类
package com.kun.web;
// 导入Spring Boot所需的启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @SpringBootApplication 注解是Spring Boot应用的核心注解,它包含了以下三个注解的功能:
* 1. @SpringBootConfiguration:标识该类是一个Spring Boot配置类,可以替代@Configuration注解。
* 2. @EnableAutoConfiguration:启用自动配置特性,Spring Boot会根据当前类路径下的jar包依赖情况,自动配置Bean。
* 3. @ComponentScan:默认会扫描该类所在的包及其子包下的所有组件(如@Service, @Repository, @Controller等)。
* 本类(JKSpringBootApplication)作为整个Spring Boot应用的入口点。
*/
@SpringBootApplication
public class JKSpringBootApplication {
/**
* 主函数,用于启动Spring Boot应用。
* @param args 命令行参数,一般情况下可忽略
*/
public static void main(String[] args) {
// 使用SpringApplication.run()方法启动应用,传入当前类(JKSpringBootApplication.class)作为主配置类,
// 并传递命令行参数args给Spring Boot环境。
SpringApplication.run(JKSpringBootApplication.class, args);
}
}
这个Java类JKSpringBootApplication
是Spring Boot应用的主启动类,通@SpringBootApplication
注解开启Spring Boot的所有核心特性,并在main
方法中调用SpringApplication.run()
方法启动整个Spring Boot应用。当运行此主类时,Spring Boot将根据配置构建起整个应用程序上下文,并开始运行应用。
4.基于MyBatis框架的Java接口
package com.kun.web.mapper;
import com.kun.web.pojo.Book;
import com.kun.web.vo.BookVO;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface BookMapper {
/**
* 添加一本图书到数据库
*
* @param book 需要添加的图书实体对象
*/
void insert(Book book);
/**
* 查询并返回所有图书信息
* @return 所有图书的列表
*/
List<Book> selectAll();
/**
* 根据图书ID删除图书
* @param id 图书ID
*/
@Delete("DELETE FROM book WHERE id = #{id}")
void deleteById(Integer id);
/**
* 查询所有图书的基本信息(书名和价格)
* 通过注解方式编写SQL查询以简化代码
*
* @return 包含图书名称和价格的BookVO对象列表
*/
@Select("SELECT nameBook, price FROM book")
List<BookVO> findAllBookVO();
}
@Mapper
注解表明这是一个MyBatis的Mapper接口,会被MyBatis自动扫描并注册到Spring容器中。
接口中定义了几个方法:
-
void insert(Book book)
:用于向数据库中插入新的图书记录,参数是Book实体对象。 -
List<Book> selectAll()
:查询并返回数据库中的所有图书记录,返回值是Book对象的列表。 -
@Delete("DELETE FROM book WHERE id = #{id}") void deleteById(Integer id)
:通过注解的方式定义了一个删除操作,根据图书ID删除相应的图书记录。 -
@Select("SELECT name, price FROM book") List<BookVO> findAllBookVO()
:通过注解的方式定义了一个查询操作,查询所有图书的名称和价格,并将查询结果转换为BookVO对象列表返回。BookVO是一个视图对象,只包含部分图书信息(在这里是书名name和价格price)。#{id}
是MyBatis的占位符,会在运行时被方法参数值替换。
5.Spring MVC框架下的一个控制器类(Controller)
package com.kun.web.controller;
import com.kun.web.pojo.Book;
import com.kun.web.service.BookService;
import com.kun.web.vo.PieVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("book")
public class BookController {
@Autowired
private BookService bookService;
@RequestMapping("add")
public String addCarInfo(@RequestBody Book book){
bookService.addBook(book);
return "ok";
}
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public String deleteBook(@PathVariable("id") Integer id) {
bookService.deleteBookById(id);
return "删除成功";
}
@RequestMapping("list")
public List<Book> findBookInfo() {
return bookService.list();
}
@RequestMapping("/pieVO")
public List<PieVO> getPieVO(){
return bookService.getPieVO();
}
}
-
@RestController
注解表示这是一个REST风格的控制器,返回的对象会直接转换为JSON格式响应给客户端。 -
@RequestMapping("book")
注解在类级别上,定义了所有方法的公共路径前缀为"/book"。
-
通过addCarInfo
方法:@RequestBody
注解接收前端发送的JSON格式的图书数据,并绑定到Book对象上。调用注入的BookService
实例的addBook
方法将图书数据保存至数据库。方法成功执行后返回字符串"ok",表示添加图书成功。 -
通过deleteBook
方法:@PathVariable
注解获取URL路径参数"id",并将其转换为Integer类型。调用BookService
实例的deleteBookById
方法删除指定ID的图书记录。 -
直接调用findBookInfo
方法:BookService
实例的list
方法获取所有图书信息。 -
调用getPieVO
方法:BookService
实例的getPieVO
方法获取某种统计信息,例如图书类型的饼图数据,并以PieVO对象列表形式返回。
6.Spring的服务类(BookService
)
package com.kun.web.service;
import com.kun.web.mapper.BookMapper;
import com.kun.web.pojo.Book;
import com.kun.web.vo.BookVO;
import com.kun.web.vo.PieVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class BookService {
@Autowired
private BookMapper bookMapper;
public List<Book> list(){
List<Book> bookList = bookMapper.selectAll();
return bookList;
}
public void addBook(Book book){
bookMapper.insert(book);
}
public void deleteBookById(Integer id) {
bookMapper.deleteById(id);
}
public List<PieVO> getPieVO(){
List<BookVO> list = bookMapper.findAllBookVO();
List<PieVO> pieVOList = list.stream()
.map(e -> new PieVO(
e.getPrice(),
e.getNameBook()
)).collect(Collectors.toList());
System.out.println(pieVOList);
return pieVOList;
}
}
-
@Service
注解表明这是一个Spring服务层的Bean,会被Spring容器自动扫描并纳入管理。 -
@Autowired
注解用来自动注入BookMapper
实例,它是MyBatis提供的数据访问接口,用于执行数据库操作。
-
调用list
方法:bookMapper.selectAll()
获取所有图书记录,并返回结果列表。 -
将传入的addBook
方法:Book
对象通过bookMapper.insert(book)
插入到数据库中。 -
根据传入的图书ID,调用deleteBookById
方法:bookMapper.deleteById(id)
从数据库中删除相应图书记录。 -
调用getPieVO
方法:bookMapper.findAllBookVO()
查询所有图书的部分基本信息(书名和价格),并转换为BookVO
对象列表。使用Java 8 Stream API对BookVO
列表进行流式处理,将每个BookVO
对象转换为PieVO
对象,并收集到一个新的PieVO
列表中。最后返回转换后的PieVO
列表。
7.映射器配置文件(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">
<mapper namespace="com.kun.web.mapper.BookMapper">
<!-- 插入图书 -->
<insert id="insert" parameterType="com.kun.web.pojo.Book">
insert into book
values(null, #{nameBook}, #{price}, #{kind}, #{author}, #{publisher})
</insert>
<!-- 查询所有图书 -->
<select id="selectAll" resultType="com.kun.web.pojo.Book">
select *
from book
</select>
<!--根据图书ID删除图书-->
<delete id="deleteByIds" parameterType="int">
delete from book where id = #{id}
</delete>
</mapper>
-
<insert>
标签定义了一个名为insert
的方法,用于向book
表中插入新的图书记录。parameterType
属性指定了传入参数的类型为com.kun.web.pojo.Book
,在Java代码中可以通过Book
对象直接传递参数值。 -
<select>
标签定义了一个名为selectAll
的方法,用于从book
表中查询所有图书记录,并指定查询结果的类型为com.kun.web.pojo.Book
。 -
<delete>
标签定义了一个名为deleteByIds
的方法,用于根据图书ID从book
表中删除记录。
二、前端搭建
1.Vue Router配置
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import BookListView from '../views/BookView.vue'
import EchartsView from '../views/EchartsView.vue';
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/booklist',
name: 'booklist',
component:BookListView
},
{
path: '/echarts',
name: 'echarts',
component: EchartsView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue')
}
]
})
export default router
-
首先,从
vue-router
库导入必要的模块:createRouter
用于创建路由器实例,createWebHistory
用于创建历史模式(history mode)的路由对象。 -
然后,定义路由组件:
HomeView
对应于应用的主页路由;BookListView
对应于图书列表页路由;EchartsView
对应于包含ECharts图表的页面路由。 -
创建路由实例,配置选项如下:
history
: 使用createWebHistory
方法创建一个基于HTML5 History API的路由历史对象,import.meta.env.BASE_URL
指向应用的基础URL。routes
: 数组内定义了一系列路由规则,每个规则包含path
(路由路径)、name
(路由命名,可用于编程式导航)和component
(渲染的组件)。 -
最后一条路由规则
/about
的组件采用异步加载方式,通过() => import('../views/AboutView.vue')
动态导入组件,这样可以在首次加载应用时不加载AboutView组件的代码,只有当用户真正访问/about路由时才加载,实现了按需加载和路由级别的代码分割功能,提高应用加载速度和性能。
2.BookView.vue
<template>
<el-table :data="data.booklist" style="width: 100%">
<el-table-column label="图书号" prop="id" />
<el-table-column label="图书名" prop="nameBook" />
<el-table-column label="图书价格" prop="price" />
<el-table-column label="图书类型" prop="kind" />
<el-table-column label="图书作者" prop="author" />
<el-table-column label="出版社" prop="publisher" />
<el-table-column align="right">
<template #header>
<el-input size="small" placeholder="Type to search"/>
</template>
<template #default="scope">
<el-button size="small" @click="handleEdit(scope.row)"
>Edit</el-button>
<el-button size="small" type="danger" @click="handleDelete(scope.$index)"
>Delete</el-button>
</template>
</el-table-column>
</el-table>
<el-button text @click="showDialog()">
添加图书信息
</el-button>
<el-dialog v-model="dialogAddFormVisible" title="添加图书信息">
<el-form :model="data.bookInfo">
<el-form-item label="图书名" :label-width="formLabelWidth">
<el-input v-model="data.bookInfo.nameBook" autocomplete="off"/>
</el-form-item>
<el-form-item label="图书价格" :label-width="formLabelWidth">
<el-input v-model="data.bookInfo.price" autocomplete="off"/>
</el-form-item>
<el-form-item label="图书类型" :label-width="formLabelWidth">
<el-input v-model="data.bookInfo.kind" autocomplete="off"/>
</el-form-item>
<el-form-item label="图书作者" :label-width="formLabelWidth">
<el-input v-model="data.bookInfo.author" autocomplete="off"/>
</el-form-item>
<el-form-item label="出版社" :label-width="formLabelWidth">
<el-input v-model="data.bookInfo.publisher" autocomplete="off"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogAddFormVisible = false">取消</el-button>
<el-button type="primary" @click="addBook()">添加</el-button>
</span>
</template>
</el-dialog>
<el-button text @click="Echarts()">
Echarts图书可视化
</el-button>
</template>
<script lang="ts" setup>
import {ref, reactive, onMounted} from 'vue'
import axios from "axios";
let data = reactive({
booklist: [
{id: null, nameBook: '', price: '', kind: '', author: '', publisher: ''},
],
bookInfo: {id: null, nameBook: '', price: '', kind: '', author: '', publisher: ''}
});
/*const search = {
}*/
const dialogAddFormVisible = ref(false)
const formLabelWidth = '140px'
/*const form = reactive({
name:'',
region:'',
date1:'',
date2:'',
delivery:false,
type:[],
resource:'',
desc:'',
})*/
function showDialog(){
data.bookInfo = {id: null, nameBook: '', price: '', kind: '', author: '', publisher: ''};
dialogAddFormVisible.value = true;
}
function Echarts(){
location.href="http://localhost:5173/echarts";
}
function loadBookInfo() {
let path = "http://localhost:8088/book/list";
axios.get(path, {}).then(function (response) {
if (response.status == 200) {
data.booklist = response.data;
} else {
console.error("请求出错:", response.status);
}
}).catch(function (error) {
console.error("查询出错:", error);
});
}
onMounted(() => {
loadBookInfo();
});
function addBook(){
let path = "http://localhost:8088/book/add";
axios.post(path, data.bookInfo).then(function(obj){
console.log(data.bookInfo);
if(obj.status === 200){
alert("添加成功!");
dialogAddFormVisible.value = false;
loadBookInfo();
}
}).catch(function(){
alert("添加出错啦!")
})
}
const handleEdit = (row:any) => {
data.bookInfo = { ...row }; // 将当前行的数据复制到编辑表单中
dialogAddFormVisible.value = true; // 打开编辑对话框
}
const handleDelete = (bookId: number | string) => {
const confirmed = window.confirm("确定要删除这条图书信息吗?");
if (confirmed) {
let path = `http://localhost:8088/book/delete/${encodeURIComponent(bookId)}`;
axios.delete(path)
.then((response) => {
if (response.status === 200) {
alert("删除成功!");
// 从数据列表中移除已删除的图书
data.booklist = data.booklist.filter(book => book.id !== bookId);
} else {
console.error(`删除图书时出错,服务器响应状态码:${response.status}`);
alert("删除图书时出错,请稍后重试!");
}
// 重新加载图书列表以确保数据同步
loadBookInfo();
})
.catch((error) => {
console.error("删除图书时发生了错误:", error.message || error);
alert("删除图书时出错,请稍后重试!");
});
}
}
</script>
这段代码是Vue.js结合Element UI组件库编写的图书管理界面的模板代码。主要包括以下几个部分:
-
表格显示图书列表:
使用el-table
组件显示从服务器获取的图书列表数据,列包括图书号、图书名、图书价格、图书类型、图书作者和出版社。表格最后一列包含编辑和删除按钮,点击编辑按钮会弹出编辑模态框;点击删除按钮则会确认是否删除该行图书。 -
添加图书模态框:
有一个“添加图书信息”的按钮,点击后会显示一个el-dialog
模态框,包含一个表单用于输入新的图书信息。表单提交时,调用addBook
方法将新图书信息发送到服务器进行添加。 -
删除图书功能:
在表格中为每一行添加了删除功能,点击删除按钮会触发handleDelete
方法,发送HTTP DELETE请求到服务器删除指定图书。 -
Echarts图书可视化按钮:
提供一个按钮,点击后跳转到Echarts图书可视化的页面。 -
生命周期钩子:
onMounted
钩子中调用了loadBookInfo
方法,初次挂载组件时从服务器获取图书列表并填充到表格中。 -
辅助方法:
loadBookInfo
方法通过axios向服务器发送GET请求获取图书列表数据。addBook
方法向服务器发送POST请求添加新的图书信息。handleEdit
方法用于编辑图书信息,打开模态框并将当前行数据填充到编辑表单中。handleDelete
方法用于删除图书信息,发送HTTP DELETE请求到服务器并更新本地数据。
3.EchartsView.vue
<template>
<div id="main" style="width:1100px;height:780px;"></div>
</template>
<script lang="ts" setup>
import {onMounted} from 'vue'
import axios from "axios";
import * as echarts from "echarts";
function loadBookInfo() {
let path = "http://localhost:8088/book/pieVO";
axios.get(path, {}).then(function (obj) {
if (obj.status == 200) {
let myChart = echarts.init(document.getElementById('main'));
const option = {
title: {
text: 'echarts数据可视化',
subtext: '图书价格数据饼状图',
left: 'center'
},
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
data: obj.data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0,0,0,0.5)'
}
}
}
]
};
myChart.setOption(option);
}
}).catch(function (){
alert("查询出错啦!")
})
}
onMounted(() => {
loadBookInfo();
})
</script>
这段代码是Vue.js中用于绘制Echarts图书价格数据饼状图的组件模板和脚本。组件内部有一个id为main
的div
元素,用于承载Echarts图表。
在脚本部分:
-
引入了Vue的生命周期钩子函数
onMounted
,以及axios用于发起HTTP请求,还引入了Echarts库。 -
loadBookInfo
函数在组件挂载完成后被调用。该函数通过axios发起GET请求到http://localhost:8088/book/pieVO
以获取图书价格的饼状图数据。 -
获取数据成功后,利用Echarts库初始化图表。首先,通过
echarts.init(document.getElementById('main'))
在id为main
的div
元素上创建一个Echarts实例。 -
然后,根据获取到的后台数据(
obj.data
)配置Echarts的option对象,包括标题、提示信息(tooltip)、图例(legend)以及一个饼状图系列(series),其中饼状图的数据来源于后台返回的结果。 -
最后,将配置好的option对象通过
myChart.setOption(option)
设置给Echarts实例,从而在页面上绘制出图书价格的饼状图。
总结
这是一个基于Spring Boot和Vue.js技术栈构建的图书馆管理系统,整合了MyBatis持久层框架、MySQL数据库以及Element UI组件库进行前后端分离开发。系统主要由以下几个部分组成:
-
后端配置:
CrosConfig
类实现了跨域资源共享(CORS)配置,允许来自任何源的请求,并开放了常见的HTTP方法。JKSpringBootApplication
类作为整个Spring Boot应用的入口点,通过SpringApplication.run()
方法启动应用。 -
后端业务逻辑:
BookController
类提供了增删查改图书信息的RESTful API接口,通过BookService
调用数据访问层完成业务逻辑。BookService
类实现了具体的业务操作,如查询所有图书信息、添加图书、删除图书和获取图书统计信息(PieVO)。BookMapper
接口使用MyBatis定义了与数据库交互的SQL操作,包括插入、查询、删除图书记录。 -
数据库配置:
配置文件中包含了Spring Boot应用连接MySQL数据库的相关配置,如数据库URL、用户名、密码、数据源类型等。MyBatis的映射器配置文件(BookMapper.xml)定义了SQL映射,方便进行数据库操作。 -
前端界面:
Vue.js组件展示了图书列表,支持搜索、编辑、删除图书以及新增图书的弹窗功能。使用Element UI组件库美化UI界面,提供了表格展示图书信息,并集成了搜索框、编辑和删除按钮。 -
系统功能概述:
用户可以通过前端页面查看图书列表,搜索、编辑和删除图书信息。后台通过Spring Boot RESTful API接口提供数据操作服务,与前端进行交互。使用MyBatis与MySQL数据库进行数据持久化操作。