文章目录
图书管理系统项目第一周后端分析笔记
一、数据库(book_manager)数据分析
1. book_info 表
◼ 存放书籍信息.
属性名 | 说明 |
---|---|
bookId | 图书序号(主码) |
bookName | 图书名称 |
bookAuthor | 图书作者 |
bookPrice | 图书价格 |
bookTypeId | 图书类型序号(外码) |
bookDesc | 图书描述 |
isBorrowed | 图书是否被借阅(1 表示借出,0 表示已还) |
bookImg | 图书图片 |
2. book_type 表
◼ 存放书籍类型信息.
属性名 | 说明 |
---|---|
bookTypeId | 图书类型序号(主码) |
bookTypeName | 图书类型名 |
bookTypeDesc | 图书类型描述 |
此项目设定了以下 7 大类图书类型:(括号里分别对应以上 3 个属性)
INSERT INTO `book_type` VALUES (1, '计算机科学', '计算机相关');
INSERT INTO `book_type` VALUES (2, '历史', '历史相关');
INSERT INTO `book_type` VALUES (3, '文学', '文学相关');
INSERT INTO `book_type` VALUES (4, '科幻', '科幻相关');
INSERT INTO `book_type` VALUES (6, '小说', '小说相关');
INSERT INTO `book_type` VALUES (7, '外语', '外语相关');
3. borrow 表
◼ 存放书籍借阅信息.
属性值 | 说明 |
---|---|
borrowId | 借阅序号(主码) |
userId | 用户序号(外码) |
bookId | 图书序号(外码) |
borrowTime | 借书时间 |
returnTime | 还书时间 |
4. user 表
◼ 存放用户信息.
属性值 | 说明 |
---|---|
userId | 用户序号(主码) |
userName | 用户名称 |
userPassword | 用户密码 |
isAdmin | 用户身份(1 是管理员,0 非管理员) |
二、后端项目主结构分析
1. 结构逻辑
◼ 主要逻辑:MVC框架、业务分层.
2. Java 程序开发目录
包名 | 说明 |
---|---|
config | 包含了项目的配置类 |
exception | 包含了自定义异常类,用于处理项目中的异常情况 |
interceptor | 包含了拦截器类,主要只对 Controller 请求进行拦截并作相应的处理 |
mapper | 包含了数据访问对象,用于与数据库进行交互(4 个类对应数据库的 4 个表) |
model | 包含了实体类,用于描述数据库中的数据结构 |
service | 包含了业务逻辑处理类,处理具体的业务逻辑 |
utils | 包含了一些工具类 |
web | 包含了项目的控制器类,处理 HTTP 请求和响应 |
三、对登录、注册、登出、修改密码模块代码进行分析
1. 相关文件名
相关文件名 | 说明 |
---|---|
User.java | 用户模型类,封装用户属性(对应 User 表) |
UserService.java | 用户服务类,该接口定义了用于操作用户信息的方法 |
UserServiceImpl.java | 实现了 UserService 的方法,是一个用户服务的实现类 |
UserMapper.java | 对应于数据库 User 表,包括对这张表的增删改查(CRUD)等操作 |
UserMapper.xml | 包含了一些操作数据库表的 SQL 语句,用于映射 UserMapper 类和数据库表之间的关系 |
UserController.java | 用户控制器类,主要用于处理与用户相关的 HTTP 请求 |
◼ UserService.java
和 UserServiceImpl.java
作为控制器与 Mapper 的桥梁,能够通过控制器对数据库数据进行相关操作 .
2. User.java
◼ Path:src->main->java com.wangpeng.bms.model
public class User implements Serializable {
private Integer userid;
private String username;
private String userpassword;
private Byte isadmin;
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpassword() {
return userpassword;
}
public void setUserpassword(String userpassword) {
this.userpassword = userpassword;
}
public Byte getIsadmin() {
return isadmin;
}
public void setIsadmin(Byte isadmin) {
this.isadmin = isadmin;
}
}
◼ 该代码定义了一个 Java 类 User
,它实现了 Serializable
接口,表明该类的对象可以被 序列化,即可以在网络上传输或存储到本地磁盘中 .
◼ 该类有 4 个私有成员变量:userid
、username
、userpassword
和 isadmin
,分别代表用户序号、用户名称、用户密码和用户身份,与 User 表一一对应 .
◼ 该类还提供了 4 个公共方法用于获取和设置这些成员变量的值,即 getUserid()
、setUserid()
、getUsername()
、setUsername()
、getUserpassword()
、setUserpassword()
、getIsadmin()
、setIsadmin()
.
3. 前置工具类
◼ Path:src->main->java com.wangpeng.bms.utils
前置工具类 | 说明 |
---|---|
TokenProcessor.java | 生成 Token 用于用户身份验证 |
MyResult.java | 构造自定义格式的结果数据 |
① TokenProcessor.java
◼ getInstance()
方法返回单例的 TokenProcessor
实例 .
◼ makeToken()
方法用于 生成 Token,基于当前时间和一个随机数构成一个字符串,然后通过MD5 哈希算法,计算这个字符串的哈希值,并将哈希值进行Base64 编码后返回 .
② MyResult.java
◼ 主要使用了双括号语法,并通过继承 HashMap
匿名类的方式,在类的初始化块中添加了键值对 .
◼ 参数名即含义:
参数名 | 含义 |
---|---|
status 、code | 状态码 |
message | 信息内容 |
data | 数据对象体 |
count | 数量 |
timestamp | 时间戳 |
4. UserController.java(几个模块的主类)
◼ Path:src->main->java com.wangpeng.bms.web
① 相关注解分析
注解 | 说明 |
---|---|
@RestController | @RestController = @Controller + @ResponseBody ,用于标注控制器类,表明该控制器里面的方法默认都以json 格式返回请求 |
@RequestMapping | 用于将 HTTP 请求映射到控制器方法(未指定请求方式) |
@RequestBody | 标识一个控制器方法的参数,以指示 Spring 应该将 HTTP 请求体转换为该参数类型的对象 |
② 登录模块
◼ API:
// 登录:
@RequestMapping(value = "/login")
public Map<String, Object> login(@RequestBody User user) {
// 登录
User userObj = userService.login(user); // 从数据库中取用户
if(userObj == null) { // 账号或密码错误
// 返回结果对象
return MyResult.getResultMap(420, "账号或密码错误");
} else { // 账号密码正确
// 创建 token
String token = TokenProcessor.getInstance().makeToken();
// 保存到 Redis
userService.saveUser(token, userObj);
// 返回结果对象
return MyResult.getResultMap(200, "登录成功",
new HashMap<String, String>(){{ put("token", token); }});
}
}
◼ 这是一个用于处理登录请求的 Java Spring Boot 控制器(Controller)方法 . 该方法使用 @RequestMapping
注解来指定处理请求的 URL 路径,即 “/login” . 请求体中传入一个 User
对象作为参数,该对象包含了用户的账号和密码 .
◼ 代码首先调用 userService
的 login
方法,通过传入的用户账号和密码在数据库中查找匹配的用户记录,如果找不到(null
)匹配的用户记录,说明账号或密码错误,将会返回一个 MyResult
对象,其状态码为 420,提示“账号或密码错误”;
◼ 如果找到匹配的用户记录,则说明账号密码正确,代码将使用 TokenProcessor
生成一个 token
字符串,并调用 userService
的 saveUser
方法,将该 token
字符串和用户对象保存到 Redis
数据库中,记录用户登录状态,以便后续请求可以进行 身份验证 . 最后,代码返回一个 MyResult
对象,其状态码为 200,提示“登录成功”,并且附带一个包含 token
字符串的 Map
对象 .
注:这段代码使用了一个自定义的
MyResult
类来封装返回的结果对象,其中包含了状态码、提示信息和数据 . 此外,它还使用了一个TokenProcessor
类来生成和处理token
字符串,并将用户信息保存到Redis
数据库中.
③ 注册模块
◼ API:
// 注册
@RequestMapping(value = "/register")
public Integer register(String username, String password){
return userService.register(username, password);
}
◼ 该 API 实现了一个注册功能,当接收到 “/register” 的 HTTP 请求时,会调用 userService
的 register
方法进行注册 .
◼ 代码调用 userService
的 register
方法,将用户名 username
和密码 password
传入到数据库中进行注册(默认是 读者身份) . 该方法返回一个整数值,表示注册操作的结果,该整数值表示注册成功的 用户序号 .
④ 登出模块
◼ API:
// 退出登录
@RequestMapping(value = "/logout")
public Map<String, Object> logout(String token) {
// 从redis中移除用户
userService.removeUser(token);
return MyResult.getResultMap(200, "退出登录成功" );
}
◼ 该 API 是一个处理退出登录请求的方法:当用户想要退出登录时,会发送一个 HTTP 请求到指定的 URL 路径,即 “/logout”,其中包含一个令牌(token
),表示当前用户的身份信息 .
◼ 这个方法会从 Redis 缓存中移除该用户的信息,实现用户退出登录的功能,然后,它会返回一个 Map
对象,其中包含一个键值对:一个表示状态码(200 表示成功),另一个表示状态消息(“退出登录成功”).
⑤ 修改密码模块
◼ API:
// 修改密码
@RequestMapping(value = {"/alterPassword", "reader/alterPassword"})
public Integer alterPassword(Integer userid, String username, Byte isadmin, String oldPassword, String newPassword){
//检查旧密码是否正确
User userObj = new User();
userObj.setUserid(userid);
userObj.setUsername(username);
userObj.setUserpassword(oldPassword);
userObj.setIsadmin(isadmin);
User user = userService.login(userObj);
if(user == null) { //旧密码不正确
return 0;
} else { //旧密码正确,设置新密码
userService.setPassword(userObj.getUserid(), newPassword);
return 1;
}
}
◼ 该 API 是一个用于修改用户密码的方法,接收旧密码和新密码作为参数,使用了 @RequestMapping
注解来处理 HTTP 请求,它接收了两个请求路径:/alterPassword
和 reader/alterPassword
,这两个路径都可以访问该方法 .
◼ 它首先通过调用 userService.login(userObj)
方法来在数据库中检查用户提供的旧密码是否正确,如果旧密码不正确,方法将返回 0,表示修改密码失败 . 如果旧密码正确,则调用 userService.setPassword(userObj.getUserid(), newPassword)
方法来将新密码更新到数据库中,并返回 1,表示修改密码成功 .