图书管理系统

这个项目是关于图书管理的,并没有用到框架,只是一些IO流的操作,看这个项目是对IO流的一种复习。

1 环境搭建

首先需要下载项目文件library,之后在idea中创建一个空项目,将模块文件解压到该空项目文件夹里;在idea中导入刚才的项目文件夹,注意编码格式需要改为GBK

2 登陆代码分析

image-20210827150530789

在Login类里面通过

1
2
@FXML private TextField username;
@FXML private TextField password;

来获取登录界面里面用户输入的密码,之后enter()方法中的

1
2
AdminService adminService = new AdminServiceImpl();
Admin admin = adminService.get(username.getText());

根据输入的用户名查找到用户,获取到文件中的用户名和密码与输入的相匹配,如果一样就跳转到登录界面。

3 分层的代码思想

  • Controller(请求处理层):负责与界面数据进行交互处理
  • Service(业务逻辑层):负责业务逻辑相关处理
  • DAO(数据持久层):负责数据的持久化,全称是Data Access Object

4 用户的相关功能

4.1 用户数据的初始化

4.1.1 功能概述

创建若干User对象放到List中,通过对象输出流将List对象写出到硬盘的user.txt文件中,从而达到持久化的操作。

4.1.2 Serializable接口

通过IO流将List对象数据持久化到硬盘的文件中,List中存放的数据是User类型,所以要让User类实现Serializable接口。倘若我们要对某个类的对象进行IO操作时,别忘了让这个类实现Serializable接口

4.1.3 代码部分

首先我们要将数据进行初始化,方法是利用IO流的操作创建一个文件user.txt用来保存用户数据,进行持久化管理。这里面有一些细节需要注意,比如判断文件夹/文件是否存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class InitDataUtil {
public static void main(String args[]) {
initUser(null);
}
/**
* 初始化用户数据
*/
public static void initUser(List<User> userList) {
ObjectOutputStream oos = null;
//创建相关文件夹
try {
File directory = new File("user/");
File file = new File(PathConstant.USER_PATH);

//判断文件夹是否存在
if (!directory.exists()) {
directory.mkdir();
}

//判断文件是否存在
if (!file.exists()) {
file.createNewFile();
List<User> list = new ArrayList<>();
//userList如果没有数据需要自己创建
if (userList == null) {
list.add(new User(1001, "张大虎", Constant.USER_OK, BigDecimal.TEN));
} else {
list = userList;
}

//利用对象输出流将list数据写出到文件中
oos = new ObjectOutputStream(new FileOutputStream(PathConstant.USER_PATH));
oos.writeObject(list);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

4.2 用户的查询操作

我们在点击用户管理的时候,界面会出现所有用户,但是按照默认的代码,这三个用户是在内存中读取的,数据并没有进行持久化处理,所以我们需要做些更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void initialize(URL location, ResourceBundle resources) {

users.add(new User(1, "张三", "正常", new BigDecimal(("100"))));
users.add(new User(2, "李四", "正常", new BigDecimal(("100"))));
users.add(new User(3, "王五", "正常", new BigDecimal(("100"))));
c1.setCellValueFactory(new PropertyValueFactory<>("id"));
c2.setCellValueFactory(new PropertyValueFactory<>("name"));
c3.setCellValueFactory(new PropertyValueFactory<>("money"));
c4.setCellValueFactory(new PropertyValueFactory<>("status"));
userTableView.setItems(users);

}

更改为以下:

查询到所有的用户数据

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public void initialize(URL location, ResourceBundle resources) {
//调用service层查询用户数据
List<User> userList = userService.select();

users.addAll(userList);
c1.setCellValueFactory(new PropertyValueFactory<>("id"));
c2.setCellValueFactory(new PropertyValueFactory<>("name"));
c3.setCellValueFactory(new PropertyValueFactory<>("money"));
c4.setCellValueFactory(new PropertyValueFactory<>("status"));
userTableView.setItems(users);
}

在service接口中写select方法,然后在serviceimpl层进行实现

1
2
3
4
5
6
7
8
9
public class UserServiceImpl implements UserService {

private UserDao userDao = new UserDaoImpl();

@Override
public List<User> select() {
return userDao.select();
}
}

接下来到dao接口中写select方法,然后在daoimpl实现这个方法。

这里使用IO流进行操作,try()里面的内容会自动进行关闭,我们需要在user.txt文件中读取数据,并且把数据保存在集合list里面,之后返回集合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserDaoImpl implements UserDao {
@Override
public List<User> select() {

try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PathConstant.USER_PATH))) {
List<User> list = (List<User>) ois.readObject();
return list;

} catch (Exception e) {
e.printStackTrace();
}
return new ArrayList<>();
}
}

4.3 用户的添加操作

管理员添加新用户,因为这里我们的管理员只有一个,暂时不考虑多线程的问题,所以为了方便,我们将编号和状态默认设置,不需要用户输入。

首先逻辑关系上是,用户点击添加按钮,弹出添加页面,用户输入数据,完成添加功能。

Controller层实现是:

首先我们要获取到输入的用户编号,如果不为空,那么就是硬盘文件中已经存在这条数据,只需要进行修改;如果为空,就需要进行添加操作了,接下来就需要new新对象,polulate()方法是设置操作者输入的默认值;然后调用service的add方法,添加用户到集合中,再存入文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private void addOrEditUser() {
try {
String id = userIdField.getText();
if ("".equals(id) || null == id) {
//添加操作
User user = new User();
populate(user);
//设置状态为正常
user.setStatus(Constant.USER_OK);

//调用service将数据持久化
userService.add(user);

//将user数据持久化到文件中
users.add(user);
}else {
//修改操作
populate(this.user);
//刷新
userTableView.refresh();
}

stage.close();
Alerts.success("成功", "操作成功");
} catch (Exception e) {
e.printStackTrace();
Alerts.error("失败","操作失败");
}
}

serviceimpl类:

1
2
3
4
@Override
public void add(User user) {
userDao.add(user);
}

daoimpl类:

需要创建文件的输入流和输出流,首先输入流获取文件中的数据并存放在list集合中,如果集合为空,就是说硬盘文件中没有内容,默认编号就从1001开始;如果不为空,需要拿到放在list数据中的最后一条数据,这样可以拿到硬盘文件里面用户的编号,并且+1就是即将保存的新的用户编号。最后将集合写出到硬盘文件中去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* 添加操作
*
* @param user
*/
@Override
public void add(User user) {
ObjectInputStream ois = null;
ObjectOutputStream oos = null;

try {
//读取文件中的list对象
ois = new ObjectInputStream(new FileInputStream(PathConstant.USER_PATH));
List<User> list = (List<User>) ois.readObject();

if (list != null) {
//获取list中最后的User对象
User lastUser = list.get(list.size() - 1);
//生成用户编号
user.setId(lastUser.getId() + 1);
//将user对象放入到list中,然后将list写出到文件当中
list.add(user);

} else {
list = new ArrayList<>();
user.setId(1001);
list.add(user);
}

oos = new ObjectOutputStream(new FileOutputStream(PathConstant.USER_PATH));
oos.writeObject(list);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (ois != null) {
ois.close();
}
if (oos != null) {
oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

4.4 用户的修改操作

用户的修改操作,操作者再点击修改按钮之后,弹出来的修改框,会显示用户的名字和金额,这一步在代码中的体现是需要在硬盘文件中将数据读出来,然后放入list集合中,在获取到这一数据的信息保存为即将修改的originUser,之后操作者才能进行修改。

daoimpl类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Override
public void update(User user) {
//首先需要将list数据从文件中查出来
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try {
ois = new ObjectInputStream(new FileInputStream(PathConstant.USER_PATH));
List<User> list = (List<User>)ois.readObject();

if(list != null){
//从list中查找要修改的数据
User originUser = list.stream().filter(u -> u.getId() == user.getId()).findFirst().get();

//进行修改
originUser.setName(user.getName());
originUser.setMoney(user.getMoney());

//将数据持久化到文件中
oos = new ObjectOutputStream(new FileOutputStream(PathConstant.USER_PATH));
oos.writeObject(list);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally{
try{
if(ois != null){
ois.close();
}

if(oos != null){
oos.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}