当前位置: 首页 > news >正文

Spring-图书管理系统

目录

一.项目准备

        1.创建项目

        2.配置MyBatis 

二.代码编写

        1.创建数据库和数据表

        2.用户登入接口

                创建用于接收登入用户数据的类(和用户数据表匹配,使用驼峰的方式):

                创建Mapper(根据登入用户的用户名来获取数据库中的密码) :

                创建Service: 

                创建Controller:

                HTML页面准备:

                运行结果: 

                3.图书列表接口

                        创建用于接收图书列表数据的类: 

                        创建页面信息类(当前页码和每页显示的条数): 

                        创建用于接收图书信息的类:

                        创建Mapper: 

                 创建Service:

                 创建Controller:

                        返回中文图书状态:

        4.添加图书接口         

                创建Mapper:

                创建Service: 

                创建Controller:

                        在Controller层中有一个设计问题:

                                当需要查看代码条件语句,在某一操作下的执行结果,来判断代码是否执行正确的情况:​编辑

                        HTML代码准备:

        5.图书修改接口

                查询图书信息:

                        创建Mapper: 

                        创建Service: 

                        创建Controller: 

                修改图书信息:

                        创建Mapper:

                        XML文件代码:

                        创建Service: 

                        创建Controller: 

                        HTML代码准备:

                6.删除单个图书和批量删除选中的图书接口 :

                        删除单本图书:

                                批量删除图书:

                                        创建Mapper:

                                        创建Service层: 

                                        创建Controller层: 

                7.强制登入


一.项目准备

        1.创建项目

        2.配置MyBatis 

        在使用yml配置文件的时候一定要注意空格,空格不对会导致yml配置文件读取错误: 


MyBatis配置模板 https://blog.csdn.net/weixin_52159554/article/details/148771292?spm=1001.2014.3001.5501

        试运行检查MySQL数据库连接是否成功: 

        表示连接成功: 

       连接错误日志 https://blog.csdn.net/weixin_52159554/article/details/148848671?sharetype=blogdetail&sharerId=148848671&sharerefer=PC&sharesource=weixin_52159554&spm=1011.2480.3001.8118

二.代码编写

        1.创建数据库和数据表

 -- 创建数据库DROP DATABASE IF EXISTS book_test;CREATE DATABASE book_test DEFAULT CHARACTER SET utf8mb4;-- ⽤⼾表DROP TABLE IF EXISTS user_info;CREATE TABLE user_info (`id` INT NOT NULL AUTO_INCREMENT,`user_name` VARCHAR ( 128 ) NOT NULL,`password` VARCHAR ( 128 ) NOT NULL,`delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now() ON UPDATE now(),PRIMARY KEY ( `id` ),UNIQUE INDEX `user_name_UNIQUE` ( `user_name` ASC )) ENGINE = INNODB DEFAULT
CHARACTERSET = utf8mb4 COMMENT = '⽤⼾表';-- 图书表DROP TABLE IF EXISTS book_info;CREATE TABLE `book_info` (`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,`book_name` VARCHAR ( 127 ) NOT NULL,`author` VARCHAR ( 127 ) NOT NULL,`count` INT ( 11 ) NOT NULL,`price` DECIMAL (7,2 ) NOT NULL,`publish` VARCHAR ( 256 ) NOT NULL,`status` TINYINT ( 4 ) DEFAULT 1 COMMENT '0-⽆效, 1-正常, 2-不允许借阅',`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now() ON UPDATE now(),PRIMARY KEY ( `id` ) ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;-- 初始化数据INSERT INTO user_info ( user_name, PASSWORD ) VALUES ( "admin", "admin" );INSERT INTO user_info ( user_name, PASSWORD ) VALUES ( "zhangsan", "123456" );-- 初始化图书数据INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('活
着', '余华', 29, 22.00, '北京⽂艺出版社');INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('平凡的
世界', '路遥', 5, 98.56, '北京⼗⽉⽂艺出版社');INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('三
体', '刘慈欣', 9, 102.67, '重庆出版社');INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('⾦字塔
原理', '⻨肯锡', 16, 178.00, '⺠主与建设出版社');INSERT INTO `book_info` ( book_name, author, count, price, publish )VALUES( '图书2', '作者2', 29, 22.00, '出版社2' ),( '图书3', '作者2', 29, 22.00, '出版社
3' ),( '图书4', '作者2', 29, 22.00, '出版社1' ),( '图书5', '作者2', 29, 22.00, '出版社
1' ),( '图书6', '作者2', 29, 22.00, '出版社1' ),( '图书7', '作者2', 29, 22.00, '出版社
1' ),( '图书8', '作者2', 29, 22.00, '出版社1' ),( '图书9', '作者2', 29, 22.00, '出版社
1' ),( '图书10', '作者2', 29, 22.00, '出版社1'),( '图书11', '作者2', 29, 22.00, '出版
社1'),( '图书12', '作者2', 29, 22.00, '出版社1'),( '图书13', '作者2', 29, 22.00, '出版
社1'),( '图书14', '作者2', 29, 22.00, '出版社1'),( '图书15', '作者2', 29, 22.00, '出版
社1'),( '图书16', '作者2', 29, 22.00, '出版社1'),( '图书17', '作者2', 29, 22.00, '出版
社1'),( '图书18', '作者2', 29, 22.00, '出版社1'),( '图书19', '作者2', 29, 22.00, '出版
社1'),
( '图书20', '作者2', 29, 22.00, '出版社1'),( '图书21', '作者2', 29, 22.00, '出版
社1');

        2.用户登入接口

                创建用于接收登入用户数据的类(和用户数据表匹配,使用驼峰的方式):
import lombok.Data;import java.util.Date;@Data
public class UserInfo {private Integer id;private String userName;private String password;private Integer deleteFlag;private Date createTime;private Date updateTime;
}

                创建Mapper(根据登入用户的用户名来获取数据库中的密码) :
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.example.springbookmanagerdemo.model.UserInfo;@Mapper
public interface UserInfoMapper {@Select("select * from user_info where user_name = #{userName}")UserInfo selectUserPassword(String userName);
}

                创建Service: 
import org.example.springbookmanagerdemo.mapper.UserInfoMapper;
import org.example.springbookmanagerdemo.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserInfoService {@Autowiredprivate UserInfoMapper userInfoMapper;public UserInfo getUserInfo(String username){return userInfoMapper.selectUserPassword(username);}
}

                创建Controller:
import org.example.springbookmanagerdemo.model.UserInfo;
import org.example.springbookmanagerdemo.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;@RequestMapping("/user")
@RestController
public class UserInfoController {@Autowiredprivate UserInfoService userInfoService;@RequestMapping("/login")public boolean userLogin(String userName, String password, HttpSession session) {if(!StringUtils.hasLength(userName) && !StringUtils.hasLength(password)){return false;}UserInfo userInfo = userInfoService.getUserInfo(userName);if(userInfo.getPassword().equals(password)){//将密码置空保护用户信息安全userInfo.setPassword("");//保存Sessionsession.setAttribute("userName",userInfo);return true;}return false;}
}

                HTML页面准备:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/login.css"><script type="text/javascript" src="js/jquery.min.js"></script>
</head><body><div class="container-login"><div class="container-pic"><img src="pic/computer.png" width="350px"></div><div class="login-dialog"><h3>登陆</h3><div class="row"><span>用户名</span><input type="text" name="userName" id="userName" class="form-control"></div><div class="row"><span>密码</span><input type="password" name="password" id="password" class="form-control"></div><div class="row"><button type="button" class="btn btn-info btn-lg" onclick="login()">登录</button></div></div></div><script src="js/jquery.min.js"></script><script>function login() {$.ajax({type: 'post',url: '/user/login',data:{"userName": $("#userName").val(),"password": $("#password").val()},success: function (result) {if(result){location.href = "book_list.html"}else{alert('登入失败!')}}})}</script>
</body></html>
                运行结果: 

                3.图书列表接口

                        创建用于接收图书列表数据的类: 
import lombok.Data;import java.util.List;@Data
public class PageResult<T> {//图书列表数据private List<T> records;//图书总数private Integer total;public PageResult(Integer total, List<T> records) {this.total = total;this.records = records;}
}

                        创建页面信息类(当前页码和每页显示的条数): 
import lombok.Data;@Data
public class PageRequest {//当前页码private Integer currentPage = 1;//每页的显示条数private Integer pageSize = 10;private Integer offset;public Integer getOffset() {return (currentPage - 1) * pageSize;}
}

                        创建用于接收图书信息的类:
import lombok.Data;import java.math.BigDecimal;@Data
public class BookInfo {private Integer id;private String bookName;private String author;private Integer count;private BigDecimal price;private String publish;private Integer status;private String statusCN;}

                        创建Mapper: 
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.example.springbookmanagerdemo.model.BookInfo;import java.util.List;@Mapper
public interface BookInfoMapper {//获取图书列表@Select("select * from book_info where status != 0" +" order by id asc" +" limit ${offset},${pageSize}")List<BookInfo> selectByPage(@Param("offset") Integer offset, @Param("pageSize")Integer pageSize);//获取图书总量@Select("select count(1) from book_info where status != 0")Integer selectCount();
}

                 创建Service:
import org.example.springbookmanagerdemo.mapper.BookInfoMapper;
import org.example.springbookmanagerdemo.model.BookInfo;
import org.example.springbookmanagerdemo.model.PageRequest;
import org.example.springbookmanagerdemo.model.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class BookInfoService {@Autowiredprivate BookInfoMapper bookInfoMapper;PageResult<BookInfo> pageResult = null;public PageResult<BookInfo> getPageResult(PageRequest pageRequest) {pageResult = new PageResult<>(bookInfoMapper.selectCount(),bookInfoMapper.selectByPage(pageRequest.getOffset(),pageRequest.getPageSize()),pageRequest);return pageResult;};
}

                 创建Controller:
import lombok.extern.slf4j.Slf4j;
import org.example.springbookmanagerdemo.model.BookInfo;
import org.example.springbookmanagerdemo.model.PageRequest;
import org.example.springbookmanagerdemo.model.PageResult;
import org.example.springbookmanagerdemo.service.BookInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/book")
@RestController
@Slf4j
public class BookInfoController {@Autowiredprivate BookInfoService bookInfoService;@RequestMapping("/getListByPage")public PageResult<BookInfo> getListByPage(PageRequest pageRequest) {if(pageRequest.getCurrentPage() < 0 || pageRequest.getPageSize() < 1 ) {return null;}System.out.println(pageRequest.getCurrentPage());System.out.println(pageRequest.getPageSize());PageResult<BookInfo> pageResult = null;try {pageResult =  bookInfoService.getPageResult(pageRequest);}catch (Exception e) {log.error("查询翻页信息错误,e:{}",e);}return pageResult;}
}

                        图书列表页面准备: 

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>图书列表展示</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/list.css"><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/bootstrap.min.js"></script><script src="js/jq-paginator.js"></script></head><body><div class="bookContainer"><h2>图书列表展示</h2><div class="navbar-justify-between"><div><button class="btn btn-outline-info" type="button" onclick="location.href='book_add.html'">添加图书</button><button class="btn btn-outline-info" type="button" onclick="batchDelete()">批量删除</button></div></div><table><thead><tr><td>选择</td><td class="width100">图书ID</td><td>书名</td><td>作者</td><td>数量</td><td>定价</td><td>出版社</td><td>状态</td><td class="width200">操作</td></tr></thead><tbody><tr><td><input type="checkbox" name="selectBook" value="1" id="selectBook" class="book-select"></td><td>4</td><td>大秦帝国第四册</td><td>我是作者</td><td>23</td><td>33.00</td><td>北京出版社</td><td>可借阅</td><td><div class="op"><a href="book_update.html?bookId=4">修改</a><a href="javascript:void(0)" onclick="deleteBook(4)">删除</a></div></td></tr></tbody></table><div class="demo"><ul id="pageContainer" class="pagination justify-content-center"></ul></div><script>getBookList();function getBookList() {$.ajax({type: 'get',url: '/book/getListByPage' + location.search,success: function (result) {bookList = result.records;var trE = ''for(var books of bookList) {trE += '<tr>'trE += '<td><input type="checkbox" name="selectBook" value="'+books.id+'" id="selectBook" class="book-select"></td>'trE += '<td>'+books.id+'</td>'trE += '<td>'+books.bookName+'</td>'trE += '<td>'+books.author+'</td>'trE += '<td>'+books.count+'</td>'trE += '<td>'+books.price+'</td>'trE += '<td>'+books.publish+'</td>'trE += '<td>'+books.statusCN+'</td>'trE += '<td> <div class="op">'trE += ' <a href="book_update.html?bookId='+books.id+'">修改</a>'trE += ' <a href="javascript:void(0)" onclick="deleteBook('+books.id+')">删除</a>'trE += ' </div></td></tr>'$('tbody').html(trE)}//翻页信息$("#pageContainer").jqPaginator({totalCounts: result.total, //总记录数pageSize: 10,    //每页的个数visiblePages: 5, //可视页数currentPage: result.pageRequest.currentPage,  //当前页码first: '<li class="page-item"><a class="page-link">首页</a></li>',prev: '<li class="page-item"><a class="page-link" href="javascript:void(0);">上一页<\/a><\/li>',next: '<li class="page-item"><a class="page-link" href="javascript:void(0);">下一页<\/a><\/li>',last: '<li class="page-item"><a class="page-link" href="javascript:void(0);">最后一页<\/a><\/li>',page: '<li class="page-item"><a class="page-link" href="javascript:void(0);">{{page}}<\/a><\/li>',//页面初始化和页码点击时都会执行onPageChange: function (page, type) {console.log("第" + page + "页, 类型:" + type);if(type == 'change'){location.href="book_list.html?currentPage="+page;}}});}})}function deleteBook(id) {var isDelete = confirm("确认删除?");if (isDelete) {//删除图书alert("删除成功");}}function batchDelete() {var isDelete = confirm("确认批量删除?");if (isDelete) {//获取复选框的idvar ids = [];$("input:checkbox[name='selectBook']:checked").each(function () {ids.push($(this).val());});console.log(ids);alert("批量删除成功");}}</script></div>
</body></html>
                        返回中文图书状态:

                                创建enum枚举类型:

public enum BookStatusEnum {DELETED(0,"删除"),NORMAL(1,"可借阅"),FORBIDDEN(2,"不可借阅");public static BookStatusEnum getBookStatusEnum(int status){switch(status){case 0:return DELETED;case 1:return NORMAL;case 2:return FORBIDDEN;default:return FORBIDDEN;}}private int code;private String name;BookStatusEnum(int code, String name) {this.code = code;this.name = name;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

                               在Service层添加状态处理: 

import org.example.springbookmanagerdemo.enums.BookStatusEnum;
import org.example.springbookmanagerdemo.mapper.BookInfoMapper;
import org.example.springbookmanagerdemo.model.BookInfo;
import org.example.springbookmanagerdemo.model.PageRequest;
import org.example.springbookmanagerdemo.model.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class BookInfoService {@Autowiredprivate BookInfoMapper bookInfoMapper;PageResult<BookInfo> pageResult = null;public PageResult<BookInfo> getPageResult(PageRequest pageRequest) {pageResult = new PageResult<>(bookInfoMapper.selectCount(),bookInfoMapper.selectByPage(pageRequest.getOffset(),pageRequest.getPageSize()),pageRequest);if(pageResult.getRecords() != null && pageResult.getRecords().size() > 0) {for(BookInfo bookInfo : pageResult.getRecords()) {bookInfo.setStatusCN(BookStatusEnum.getBookStatusEnum(bookInfo.getStatus()).getName());}}return pageResult;};
}

                                此时对于图书价格,当图书为整数的时候,会只显示为 22,而不是22.00此时只需要在后端将这个数据的传输格式限制为字符串就可以了:

        4.添加图书接口         

                创建Mapper:
 @Insert("insert into book_info (`book_name`, `author`, `count`, `price`,`publish`,`status`)" +"values (#{bookName}, #{author}, #{count}, #{price}, #{publish}, #{status})")Integer insertBook(BookInfo bookInfo);

                创建Service: 
//新增图书public Integer insertBookInfo(BookInfo bookInfo) {Integer result = 0;try{result = bookInfoMapper.insertBook(bookInfo);}catch (Exception e){log.error("新增图书失败:e:{}",e);}return result;}

                创建Controller:
@RequestMapping("/addBook")public String addBook(BookInfo bookInfo) {if(!StringUtils.hasLength(bookInfo.getBookName())|| !StringUtils.hasLength(bookInfo.getAuthor())|| bookInfo.getCount() < 0|| bookInfo.getPrice() == null|| !StringUtils.hasLength(bookInfo.getPublish())) {return "参数校验失败,请重新传入图书参数";}Integer result = bookInfoService.insertBookInfo(bookInfo);if(result <= 0) {log.error("添加图书错误,bookInfo:{}",bookInfo);return "添加图书错误,请联系管理员";}return "";}

                        在Controller层中有一个设计问题:

                                上图中的这段代码其实也可以写成: 

                                这两段代码的最终的实现结果都是一样的,但是不同的地方在于,图一中的业务逻辑处理在方法的第一层,图二中的业务逻辑处理在方法的第二层。

                                在项目开发规范中,一个方法不建议,循环超过五层。超过五层代码就变得不易读了,不方便后期的维护。

                                当需要查看代码条件语句,在某一操作下的执行结果,来判断代码是否执行正确的情况:

                                这样就可以看到这个条件语句的执行结果了。            

                        HTML代码准备:

                                $("#addBook").serialize() 可以提交整个from表单中的数据,input、select、text area等输入信息都会提交。

                                 提交的内容大概就是输入框的name:输入框的内容,这个是在$.ajax的data中。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>添加图书</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/add.css"></head><body><div class="container"><div class="form-inline"><h2 style="text-align: left; margin-left: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="40"fill="#17a2b8" class="bi bi-book-half" viewBox="0 0 16 16"><pathd="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" /></svg><span>添加图书</span></h2></div><form id="addBook"><div class="form-group"><label for="bookName">图书名称:</label><input type="text" class="form-control" placeholder="请输入图书名称" id="bookName" name="bookName"></div><div class="form-group"><label for="bookAuthor">图书作者</label><input type="text" class="form-control" placeholder="请输入图书作者" id="bookAuthor" name="author" /></div><div class="form-group"><label for="bookStock">图书库存</label><input type="text" class="form-control" placeholder="请输入图书库存" id="bookStock" name="count" /></div><div class="form-group"><label for="bookPrice">图书定价:</label><input type="number" class="form-control" placeholder="请输入价格" id="bookPrice" name="price"></div><div class="form-group"><label for="bookPublisher">出版社</label><input type="text" id="bookPublisher" class="form-control" placeholder="请输入图书出版社" name="publish" /></div><div class="form-group"><label for="bookStatus">图书状态</label><select class="custom-select" id="bookStatus" name="status"><option value="1" selected>可借阅</option><option value="2">不可借阅</option></select></div><div class="form-group" style="text-align: right"><button type="button" class="btn btn-info btn-lg" onclick="add()">确定</button><button type="button" class="btn btn-secondary btn-lg" onclick="javascript:history.back()">返回</button></div></form></div><script type="text/javascript" src="js/jquery.min.js"></script><script>function add() {$.ajax({type: "POST",url: "/book/addBook/",data: $("#addBook").serialize(),success: function (result) {console.log(result);if (result == "") {alert("添加成功!");location.href = "book_list.html";} else {alert("新增图书失败!");}}})}</script>
</body></html>

        5.图书修改接口

                查询图书信息:
                        创建Mapper: 
//查询图书的信息@Select("select * from book_info " +"where id = #{id}")BookInfo selectBookById(Integer id);

                        创建Service: 
 //获取图书信息public BookInfo selectBookInfoById(Integer id) {return bookInfoMapper.selectBookById(id);}

                        创建Controller: 
 //获取图书信息@RequestMapping("/queryBookInfoById")public BookInfo selectBookInfo(Integer bookId) {return bookInfoService.selectBookInfoById(bookId);}

                修改图书信息:
                        创建Mapper:
 //修改图书的信息Integer updateBookInfo(BookInfo bookInfo);
                        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="org.example.springbookmanagerdemo.mapper.BookInfoMapper"><update id="updateBookInfo">update book_info<set><if test = "bookName != null">book_name = #{bookName},</if><if test = "author != null">author = #{author},</if><if test = "count != null">count = #{count},</if><if test = "price != null">price = #{price},</if><if test = "publish != null">publish = #{publish},</if><if test = "status">status = #{status},</if></set>whereid = #{id}</update></mapper>
                        创建Service: 
//修改图书信息public Integer updateBookInfo(BookInfo bookInfo) {Integer result = 0;try{result = bookInfoMapper.updateBookInfo(bookInfo);}catch (Exception e){log.error("修改图书信息失败:e:{}",e);}return result;}

                        创建Controller: 
//修改图书信息@RequestMapping("/updateBook")public String updateBookInfo(BookInfo bookInfo) {if(!StringUtils.hasLength(bookInfo.getBookName())|| !StringUtils.hasLength(bookInfo.getAuthor())|| bookInfo.getCount() < 0|| bookInfo.getPrice() == null|| bookInfo.getPublish() == null) {return "参数校验失败,请重新传入图书参数";}Integer result = bookInfoService.updateBookInfo(bookInfo);if(result <= 0) {log.error("修改图书信息错误,bookInfo:{}",bookInfo);return "修改图书信息错误,请联系管理员";}return "";}

                        HTML代码准备:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>修改图书</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/add.css">
</head><body><div class="container"><div class="form-inline"><h2 style="text-align: left; margin-left: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="40"fill="#17a2b8" class="bi bi-book-half" viewBox="0 0 16 16"><pathd="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" /></svg><span>修改图书</span></h2></div><form id="updateBook"><input type="hidden" class="form-control" id="bookId" name="id"><div class="form-group"><label for="bookName">图书名称:</label><input type="text" class="form-control" id="bookName" name="bookName"></div><div class="form-group"><label for="bookAuthor">图书作者</label><input type="text" class="form-control" id="bookAuthor" name="author" /></div><div class="form-group"><label for="bookStock">图书库存</label><input type="text" class="form-control" id="bookStock" name="count" /></div><div class="form-group"><label for="bookPrice">图书定价:</label><input type="number" class="form-control" id="bookPrice" name="price"></div><div class="form-group"><label for="bookPublisher">出版社</label><input type="text" id="bookPublisher" class="form-control" name="publish" /></div><div class="form-group"><label for="bookStatus">图书状态</label><select class="custom-select" id="bookStatus" name="status"><option value="1" selected>可借阅</option><option value="2">不可借阅</option></select></div><div class="form-group" style="text-align: right"><button type="button" class="btn btn-info btn-lg" onclick="update()">确定</button><button type="button" class="btn btn-secondary btn-lg" onclick="javascript:history.back()">返回</button></div></form></div><script type="text/javascript" src="js/jquery.min.js"></script><script>$.ajax({type: 'POST',url: '/book/queryBookInfoById' + location.search,success: function (result) {console.log(result);$("#bookId").val(result.id)$("#bookName").val(result.bookName)$("#bookAuthor").val(result.author)$("#bookStock").val(result.count)$("#bookPrice").val(result.price)$("#bookPublisher").val(result.publish)$("#bookStatus").val(result.status)}})function update() {$.ajax({type: 'GET',url: '/book/updateBook',data: {"id": $("#bookId").val(),"bookName": $("#bookName").val(),"author": $("#bookAuthor").val(),"count": $("#bookStock").val(),"price": $("#bookPrice").val(),"publish": $("#bookPublisher").val(),"status": $("#bookStatus").val(),},success: function (result) {if (result == "") {alert("更新成功!");location.href = "book_list.html"} else {alert("修改图书信息失败!");}}})}</script>
</body></html>

                6.删除单个图书和批量删除选中的图书接口 :

                        在企业开发中很少使用delete语句来操作数据库中的数据,通常情况下,即使某些项目已经不对用户开放了,也不会将用户的数据彻底删除掉的,因为数据是非常宝贵的,但是也不代表数据就不删除了,只是换了一种方式。

                        对于数据来说,删除的方式通常分为逻辑删除和物理删除。

                        逻辑删除:数据依然在表中,只是将数据表示删除的字段置为删除。

                        物理删除:将数据从保存数据的物理设备上,彻底抹除掉。

                        一般情况下,在企业中会采用物理删除+存档或者逻辑删除+存档的方式对数据库中的数据进行操作。

                        所以,在这里所采用的删除也是逻辑删除。此时就不需要用delete关键字来操作数据了,使用update来更新数据库中需要操作的数据的字段就好了。

                        对于单个删除来说,直接使用之前的修改图书信息的接口就好了。

                        删除单本图书:

                        但是上面的接口在在Controller层进行参数校验的时候会将这样的请求给拦截,此时需要对代码就行修改: 

 //修改图书信息以及删除单本图书@RequestMapping("/updateBook")public String updateBookInfo(BookInfo bookInfo) {if(bookInfo.getStatus() != 0) {if(!StringUtils.hasLength(bookInfo.getBookName())|| !StringUtils.hasLength(bookInfo.getAuthor())|| bookInfo.getCount() < 0|| bookInfo.getPrice() == null|| bookInfo.getPublish() == null) {return "参数校验失败,请重新传入图书参数";}}Integer result = bookInfoService.updateBookInfo(bookInfo);if(result <= 0) {log.error("修改图书信息错误,bookInfo:{}",bookInfo);return "修改图书信息错误,请联系管理员";}return "";}

                                批量删除图书:
                                        创建Mapper:
 //批量删除图书Integer deleteBooksById(@Param("ids") List<Integer> ids);

                                        编写XML代码: 

 <update id = "deleteBooksById">update book_infosetstatus = 0where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></update>
                                        创建Service层: 
//批量删除图书public Integer deleteBooksById(List<Integer> ids) {Integer result = 0;try{result = bookInfoMapper.deleteBooksById(ids);}catch (Exception e){log.error("删除图书失败:e:{}",e);}return result;}
                                        创建Controller层: 
//批量删除图书@RequestMapping("/batchDelete")public String deleteBookInfos(@RequestParam List<Integer> ids) {Integer result = bookInfoService.deleteBooksById(ids);if(result <= 0) {log.error("删除图书错误,ids:{}",ids);return "删除图书错误,请联系管理员";}return "";}

                7.强制登入

                         在没有用户登入检测的时候,直接进入图书列表的html网页,也是可以直接操作数据库信息的,这样是不合理的,所以此时需要进行登入检测,在没有登入信息的时候,进行强制登入。

                        创建Result类,用于后端返回响应的结果:

                                原来是由路径映射的方法直接返回数据,现在将需要返回的数据进行封装,加上了业务状态码和此次响应的信息提示。

import lombok.Data;
import org.example.springbookmanagerdemo.enums.ResultCode;@Data
public class Result {/*业务状态码*/private ResultCode code;/*错误信息*/private String message;/*数据*/private Object data;public static Result success(Object data) {Result result = new Result();result.setCode(ResultCode.SUCCESS);result.setMessage(" ");result.setData(data);return result;}public static Result fail(String message) {Result result = new Result();result.setCode(ResultCode.FAIL);result.setMessage(message);result.setData(null);return result;}public static Result fail(String message ,Object data) {Result result = new Result();result.setCode(ResultCode.FAIL);result.setMessage(message);result.setData(data);return result;}public static Result unlogin(){Result result = new Result();result.setCode(ResultCode.UNLOGIN);result.setMessage("用户未登入");result.setData(null);return result;}
}

public enum ResultCode {SUCCESS(0),FAIL(-1),UNLOGIN(2);private int code;ResultCode(int code) {this.code = code;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}
}

//获取图书列表@RequestMapping("/getListByPage")public Result getListByPage(PageRequest pageRequest, HttpSession session) {UserInfo userInfo = (UserInfo) session.getAttribute(Contants.SESSION_USER_KEY);if(userInfo == null || userInfo.getId() < 0 || "".equals(userInfo.getUserName())) {return Result.unlogin();}if(pageRequest.getCurrentPage() < 0 || pageRequest.getPageSize() < 1 ) {return Result.fail("数据校验错误");}PageResult<BookInfo> pageResult = null;try {pageResult =  bookInfoService.getPageResult(pageRequest);return Result.success(pageResult);}catch (Exception e) {log.error("查询翻页信息错误,e:{}",e);return Result.fail("查询翻译信息错误");}}

        如果使用上面的方式进行强制登入的话,需要在每一个页面的请求方法中都添加,未免也有点太繁琐了,可以采用拦截器。

import lombok.extern.slf4j.Slf4j;
import org.example.springbookmanagerdemo.constant.Contants;
import org.example.springbookmanagerdemo.model.Result;
import org.example.springbookmanagerdemo.model.UserInfo;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession(false);if(session != null && session.getAttribute(Contants.SESSION_USER_KEY) != null) {UserInfo userInfo = (UserInfo) session.getAttribute(Contants.SESSION_USER_KEY);if(userInfo != null && userInfo.getId() >= 0) {return true;}}response.setStatus(401);return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}

                注册拦截器:

import org.example.springbookmanagerdemo.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.Arrays;
import java.util.List;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;private static List<String> excludePath = Arrays.asList("/user/login","/css/**","/js/**","/pic/**","/**/*.html");@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(excludePath);}
}
http://www.lryc.cn/news/575844.html

相关文章:

  • 《Effective Python》第十章 健壮性——显式链接异常,让错误追踪更清晰的艺术
  • 电梯控制系统技术解析:从基础原理到PLC应用
  • Stable Diffusion入门-ControlNet 深入理解 第二课:ControlNet模型揭秘与使用技巧
  • 【RabbitMQ】基于Spring Boot + RabbitMQ 完成应用通信
  • .小故事.
  • Mybatis-Plus源代码走读后记
  • 青少年编程与数学 01-012 通用应用软件简介 15 人工智能助手
  • Rust交互式编程环境Jupyter Lab搭建
  • YOLOv8快速入门
  • HarmonyOS NEXT仓颉开发语言实现画板案例
  • fish安装node.js环境
  • 【开发杂谈】Auto Caption:使用 Electron 和 Python 开发实时字幕显示软件
  • Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory
  • 车联网网络安全渗透测试:深度解析与实践
  • 商品中心—15.库存分桶扣减的技术文档
  • 一款被我拿来处理图片和视频的免费环保软件
  • Web基础关键_003_CSS(一)
  • 小程序学习笔记:加载效果、上拉加载与节流处理
  • Ubuntu安装Docker部署Python Flask Web应用
  • PHP语法基础篇(六):数组
  • 代码随想录|图论|09沉没孤岛
  • LSTM每个变量的shape分析
  • 从输入到路径:AI赋能的地图语义解析与可视化探索之旅
  • 通过ETL从MySQL同步到GaussDB
  • 喜讯 | Mediatom斩获2025第十三届TopDigital创新营销奖「年度程序化广告平台」殊荣
  • LINUX625 DNS反向解析
  • 基于 Spring Boot + Vue 3的现代化社区团购系统
  • 科技如何影响我们的生活?
  • 工业电子 | 什么是SerDes,为何工业和汽车应用需要它?
  • HarmonyOS NEXT仓颉开发语言实战案例:简约音乐播放页