前言:如果在接口的声明方法中鼠标右键没有Test的单元测试。
你的鼠标光标问题:要在花括号范围内!!!!
- 数据库表是应⽤程序开发中的⼀个重要环节, 数据库表的设计往往会决定我们的应⽤需求是否能顺利实现, 甚⾄决定我们的实现⽅式. 如何设计表以及这些表有哪些字段, 这些表存在哪些关系 也是⾮常重要的.
- 数据库表设计是依据业务需求来设计的. 如何设计出优秀的数据库表, 与经验有很⼤关系.
- 数据库表通常分两种: 实体表和关系表.
- 分析我们的需求, 图书管理系统相对来说⽐较简单, 只有两个实体: ⽤⼾和图书, 并且⽤⼾和图书之间没有关联关系表的具体字段设计, 也与需求有关.
- ⽤⼾表有⽤⼾名和密码即可(复杂的业务可能还涉及昵称, 年龄等资料)
- 图书表有哪些字段, 也是参考需求⻚⾯(通常不是⼀个⻚⾯决定的, ⽽是要对整个系统进⾏全⾯分析观察后定的)
一.图书管理系统(引入数据库)
1.引入数据库
2.添加依赖(记得刷新)
3.(配置数据库日志)
代码:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/book_test?characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
configuration:
map-underscore-to-camel-case: true #配置驼峰⾃动转换
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句
# 设置⽇志⽂件的⽂件名
logging:
file:
name: spring-book.log
4.创建对象(bookInfo)
代码:
package com.example.demo.model;
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;
// 图书的借阅状态。1表示图书可借阅,2表示图书不可借阅
private Integer status;
// 图书借阅状态的中文描述,用于更直观地展示图书的借阅情况
private String statusCN;
private Data createTime;
private Data updateTime;
}
5.创建对象(UserInfo)
package com.example.demo.model;
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;
}
6.创建接口(声明方法)。
package com.example.demo.mapper;
import com.example.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.*;
@Slf4j
@SpringBootTest
class UserInfoMapperTest {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
void getInfoByName() {
UserInfo userInfo = userInfoMapper.getInfoByName("zhangsan");
log.info("查询数据:{}",userInfo);
}
}
1.创建用户登录的Service
代码:
package com.example.demo.service;
import com.example.demo.mapper.UserInfoMapper;
import com.example.demo.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
public UserInfo getUserInfoByName(String userName) {
return userInfoMapper.getInfoByName(userName);
}
}
2.在controller层写后端(UserController)逻辑
package com.example.demo.controller;
import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import jakarta.servlet.http.HttpSession;
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;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/login")
public String login(String userName, String password, HttpSession session){
if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
return "用户或密码为空!";
}
UserInfo userInfo = userService.getUserInfoByName(userName);
if (userInfo==null){
return "用户不存在";
}
//用户存在, 校验密码是否正确
if (!password.equals(userInfo.getPassword())){
return "密码错误";
}//正确的情况
session.setAttribute("user_session_key",userInfo);
return "ok";
}
}
3.启动项目测试(注意切换,不用变成单元测试)
根据数据库查看一下
二.写插入图书的后端逻辑代码
1.写插入图书的数据层接口
package com.example.demo.mapper;
import com.example.demo.model.BookInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BookMapper {
/**
* 插入图书
*/
@Insert("insert into book_info (book_name, author, count, price, publish, `status`) " +
"values (#{bookName}, #{author}, #{count}, #{price}, #{publish}, #{status})")
Integer insertBook(BookInfo bookInfo);
}
2.在controller中调用
代码:
package com.example.demo.controller;
import com.example.demo.model.BookInfo;
import com.example.demo.service.BookService;
import lombok.extern.slf4j.Slf4j;
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 java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Slf4j
// 使用@RestController注解将类标记为Spring MVC的控制器,并且该类中所有方法的返回值都会自动转换为JSON或XML格式
@RestController
// 使用@RequestMapping注解定义该控制器中所有请求的基础URL路径
@RequestMapping("book")
public class BookController {
@Autowired
private BookService bookService;
/**
* 添加图书
*/
@RequestMapping("/addBook")
public String addBook(BookInfo bookInfo){
//校验参数
log.info("添加图书, 接收到参数bookInfo: {}", bookInfo);
if (!StringUtils.hasLength(bookInfo.getBookName())
|| !StringUtils.hasLength(bookInfo.getAuthor())
|| bookInfo.getCount()==null
|| bookInfo.getPrice()==null
|| !StringUtils.hasLength(bookInfo.getPublish())
|| bookInfo.getStatus()==null){
return "输入参数不合法";
}
//添加图书
try{
Integer result = bookService.insertBook(bookInfo);
if (result >0){
return "";
}
}catch (Exception e){
log.error("添加图书异常, e: ", e);
}
return "添加失败";
}
}
3.调试成功
4. 编写增添图书的前端代码。
<!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">
<path
d="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({
url: "/book/addBook",
type: "post",
data: $("#addBook").serialize(),
success: function(result){
if(result=="ok"){
alert
//添加成功
alert("添加成功");
location.href = "book_list.html";
}else{
alert(result);
}
}
});
}
</script>
</body>
</html>
三.实现图书列表查询(未完成)
实现分页查询(有插件,这里自己实现,修改太多太麻烦,懒得写了)
1.model定义一个类用来接受参数
代码:
package com.example.demo.model;
import lombok.Data;
@Data
public class PageRequest {
private Integer pageNum;
private Integer pageSize = 10;
private Integer offset;
public Integer getOffset() {
return (pageNum-1) * pageSize;
}
}
2.在Mapper实现接口
@Select("select * from book_info limit #{offset}, #{limit}")
List<BookInfo> queryBookByPage(Integer offset, Integer limit);
3.在Service中写
public List<BookInfo> getBookListByPage(PageRequest pageRequest){
return bookMapper.queryBookByPage(pageRequest.getOffset(),pageRequest.getPageSize());
}
4.在Controller写后端逻辑
使用枚举类来表示图书的状态。