# Java面向对象课设[使用三层架构完成信息管理系统]
# 题目要求
使用三层架构完成信息管理系统
# 相关试题
科研基金信息包括:记录ID、基金名称、基金类型(横向、纵向等)、基金级别(国家级、省市局、厅局级等)、基金金额、批准时间、管理机构、主持教师名称等。
试用面向对象程序设计思想,设计科研基金管理信息系统,使之能提供以下功能:
1、基金信息录入功能
2、基金信息文件读取功能
3、基金信息文件保存功能
4、基金信息浏览功能
5、查询功能:
按ID查询
按类型查询
6、修改功能:
- 根据ID修改相应信息;
7、删除基金功能:
- 删除相应ID的基金信息。
8、排序功能(由用户指定按照基金类型或ID;指定升序或降序)
9、退出
# ToDoList:
使用java swing 开发桌面窗口程序 (view表示层)
实现CRUD的业务逻辑(Service业务逻辑层)
实现到数据的获取与导出(Dao数据访问层)
实体类作为数据容器,层间传递
# 实现流程
# 完成数据的导入及导出
# 创建数据的实体类(Fund.java)
描述 | 实体类属性 |
---|---|
记录ID | id |
基金名称 | fundName |
基金类型 | fundType |
基金级别 | fundLevel |
基金金额 | fundAmount |
批准时间 | approvalTime |
管理机构 | managementOrganization |
主持教师名称 | hostTeacher |
# 创建工具类(FileUtil.java)
描述 | 工具类方法 |
---|---|
将字符串覆盖写入文件 | writeFile(String fileName, String data) |
读取文件 | ReadFile(String fileName) |
# 数据操控层Dao层
使用Alibaba FastJSON 完成数据操作
config.properties
配置文件导入导出路径
file=src\\Fund.json
2
3
使用配置文件配置文件的读取和保存路径
{
resource = ResourceBundle.getBundle("config");
fileName = resource.getString("file");
}
2
3
4
描述 | 数据操控类方法 |
---|---|
将文件中的数据导入List | setAllFund(List |
将程序中List导出到文件 | getAllFund() |
# 具体业务的实现
描述 | 业务实现方法 |
---|---|
展示所有数据 | showAll() |
列表中添加数据 | addFund() |
通过ID从列表中修改数据 | updateFundById() |
通过ID从列表中删除数据 | removeFundByid(int id) |
按ID查询列表数据 | findFundById(int id) |
按类型查询列表数据 | findFundByType(String fundType) |
按照基金类型排序(升序或降序) | sortFundById(int id) |
按照ID排序(升序或降序) | sortFundByType(String fundType) |
# 页面操作逻辑
使用fillTable()进行页面渲染,通过表格的点击事件监听获取选中的数据id进行数据操控,通过按钮的事件监听进行数据操作。
描述 | 业务实现方法 |
---|---|
创建提示框 | createDialog(String msg) |
获取多行数据id(用于删除) | getselectIDList() |
获取单行数据id(用于更新数据) | getselectID() |
清空输入框 | nullText() |
将选中的数据填入输入框 | fillText() |
将数据列表渲染入表格 | fillTable(List |
获取输入框全部内容(用于添加更改数据) | getAllTexts(int id) |
将文件中读取的json转为hashmap | getMap(List |
添加数据 | addFundController(ActionEvent e) |
删除数据 | removeFundController(ActionEvent e) |
修改数据 | updateFundcontroller(ActionEvent e) |
通过id搜索 | findFundListByIdController(ActionEvent e) |
文件导入数据 | fileImportListController(ActionEvent e) |
数据导出文件 | listExportFileController(ActionEvent e) |
清空 | clearTableModel(ActionEvent e) |
通过类型搜索 | findFundListByTypeController(ActionEvent e) |
展示所有 | showAllController(ActionEvent e) |
# 具体实现原理
entity层完成实体类编写在Dao层使用java文件读写流,读出配置文件中路径及对应文件中数据,使用FastJson实现实体类对象与json的互相转化,在service层对实体对象进行数据操作,使用List对实体对象进行存储,对list 进行增删改查等数据操作,最后在view层使用Java swing技术实现页面绘制以及响应渲染,对控件进行监听调用service层方法接口。
# 实现难点
# 1. FastJson使用
public class FundDao {
// config为属性文件名,放在src下
private ResourceBundle resource;
private String fileName;
private Fund fund;
{
resource = ResourceBundle.getBundle("config");
fileName = resource.getString("file");
}
//将实体类对象list转为json数据并写入文件
public void setAllFund(List<Fund> list) {
JSONArray jsonArray = new JSONArray();
jsonArray.addAll(list);
try {
FileUtil.writeFile(fileName, jsonArray.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
//从文件中读取json并转为实体类list
public List<Fund> getAllFund() {
List<Fund> list = null;
String data = FileUtil.ReadFile(fileName);
list = JSON.parseArray(data, Fund.class);
return list;
}
public Fund getFund() {
return fund;
}
public void setFund(Fund fund) {
this.fund = fund;
}
}
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
# 2. view层表格的动态渲染
private void fillTable(List<Fund> fundList) {
DefaultTableModel tableModel = (DefaultTableModel) table1.getModel();
tableModel.setRowCount(0);// 清除原有行
for (Fund fund : fundList) {
String[] arr = new String[8];
arr[0] = String.valueOf(fund.getId());
arr[1] = fund.getFundName();
arr[2] = fund.getFundType();
arr[3] = fund.getFundLevel();
arr[4] = String.valueOf(fund.getFundAmount());
arr[5] = fund.getApprovalTime();
arr[6] = fund.getManagementOrganization();
arr[7] = fund.getHostTeacher();
tableModel.addRow(arr);
table1.invalidate();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
使用方法填充表格
- 设置Jtable的的model
- 清除原有数据
- 遍历list取出对象
- 使用数组存储对象中每个属性
- 调用tableModel.addRow(arr)设置行内数据
- 重绘表格
# 3. 对于对象list实现可有多种实现方式如ArrayList,LinkList,Hashmap等
存储数据时可使用多种数据结构存储操控,返回数据可统一使用Arraylist给view层进行渲染
# 4. 测试与异常处理
在Runtime时会出现各种异常出现,需要我们定义到所在位置对异常进行处理,如使用防御式编程 在测试过程中输入为空值是会抛出空指针异常,因此需要对用户进行提示,而不是无视异常发生。 因此定义了一个提示框控件提示用户操作
public class FundDialog extends JDialog {
public FundDialog(String msg) {
initComponents(msg);
}
private void initComponents(String msg) {
dialogPane = new JPanel();
contentPanel = new JPanel();
button1 = new JButton();
label1 = new JLabel();
label2 = new JLabel();
// ======== this ========
var contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
// ======== dialogPane ========
{
dialogPane.setBorder(new EmptyBorder(12, 12, 12, 12));
dialogPane.setBorder(new javax.swing.border.CompoundBorder(
new javax.swing.border.TitledBorder(new javax.swing.border.EmptyBorder(0, 0, 0, 0), "",
javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.BOTTOM,
new java.awt.Font("D\u0069al\u006fg", java.awt.Font.BOLD, 12), java.awt.Color.red),
dialogPane.getBorder()));
dialogPane.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
@Override
public void propertyChange(java.beans.PropertyChangeEvent e) {
if ("\u0062or\u0064er".equals(e.getPropertyName())) {
throw new RuntimeException();
}
}
});
dialogPane.setLayout(new BorderLayout());
// ======== contentPanel ========
{
contentPanel.setLayout(null);
// ---- button1 ----
button1.setText("\u786e\u5b9a");
button1.addActionListener(e -> {
this.dispose();
});
contentPanel.add(button1);
button1.setBounds(70, 95, 70, button1.getPreferredSize().height);
// ---- label1 ----
label1.setText("\u63d0\u793a\u4fe1\u606f");
contentPanel.add(label1);
label1.setBounds(5, -5, 190, 30);
// ---- label2 ----
label2.setText(msg);
contentPanel.add(label2);
label2.setBounds(new Rectangle(new Point(10, 45), label2.getPreferredSize()));
{
// compute preferred size
Dimension preferredSize = new Dimension();
for (int i = 0; i < contentPanel.getComponentCount(); i++) {
Rectangle bounds = contentPanel.getComponent(i).getBounds();
preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width);
preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height);
}
Insets insets = contentPanel.getInsets();
preferredSize.width += insets.right;
preferredSize.height += insets.bottom;
contentPanel.setMinimumSize(preferredSize);
contentPanel.setPreferredSize(preferredSize);
}
}
dialogPane.add(contentPanel, BorderLayout.CENTER);
}
contentPane.add(dialogPane, BorderLayout.CENTER);
pack();
setLocationRelativeTo(getOwner());
}
private JPanel dialogPane;
private JPanel contentPanel;
private JButton button1;
private JLabel label1;
private JLabel label2;
}
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
之后就可以在view层通过方法创建提示框了
private void createDialog(String msg) {
FundDialog fundDialog = new FundDialog(msg);
fundDialog.setVisible(true);
fundDialog.setAlwaysOnTop(true);
}
2
3
4
5