上次写了个银行小试牛刀,这次期末考核,尝试了个大一点的家伙,图书管理系统,要求基本不变,但涉及到大量增删改查,让我足足写了6000行代码(冗余估计有一半2333),文章只展示关键代码以及说明,运行截图在最后
项目要求:
数据存到内存,编号是动态的
1:管理员登陆后,可查询所有图书信息,用户信息。管理员能添加和删除用户。
2:用户登录后,每个人最多可借10本书,可借书,还书(相关数量是动态变化的)并且用户的借阅状态要会发生改变。
3:系统支持最多三个用户(包含管理员)同时登录,可切换用户状态(登录和注销)。除管理员外用户只能查询书库实时信息和本人信息。
4:调取当前系统时间,计算罚款(罚金由管理员输入指定,默认罚金为1元,超限时间为30秒,罚金数额=超限时间*默认罚金)
(备注:用户最少5个人,图书最少20种)
5: 输出美观,逻辑清楚。
- 项目要求分析
要求清楚了,基本上还是GUI和数据库的使用(jdbc),涉及到大量的增删改查以 及数据处理,还应有清晰的MVC分包,那我们开干
- 项目结构
- 核心技术
简单的就不讲了,比如GUI设计,增删改查处理,核心流程一句话即可概括:由View包接收数据,借由Service传至Dao层处理,并完成与数据库的数据交互.数据交互主要使用的是Jdbc中一个叫QueryRunner的工具类完成数据库的增删改查. - 部分代码举例展示
view层中的注册界面
package com.vector.view;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import com.vector.bean.Admin;
import com.vector.bean.User;
import com.vector.bean.UserType;
import com.vector.service.AdminRegister;
import com.vector.service.UserRegister;
import com.vector.service.UserTypeFindByTypeService;
import com.vector.service.impl.AdminRegisterImpl;
import com.vector.service.impl.UserRegisterImpl;
import com.vector.service.impl.UserTypeFindByTypeServiceImpl;
public class Register extends JDialog {
public void register() {
this.setTitle("注册");
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
int height = Toolkit.getDefaultToolkit().getScreenSize().height;
this.setBounds(width / 2 - 200, height / 2 - 180, 780, 492);
// 普通用户注册Tab
Container c = this.getContentPane();
c.setLayout(null);
JTextField name = new JTextField();
name.setBounds(156, 66, 65, 30);
name.setFont(new Font("宋体", Font.PLAIN, 18));
JPasswordField password1 = new JPasswordField();
password1.setBounds(156, 114, 150, 30);
password1.setFont(new Font("宋体", Font.PLAIN, 18));
JPasswordField password2 = new JPasswordField();
password2.setFont(new Font("宋体", Font.PLAIN, 18));
password2.setBounds(156, 168, 150, 30);
JTextField department = new JTextField();
department.setFont(new Font("宋体", Font.PLAIN, 18));
department.setBounds(156, 222, 150, 30);
JTextField sex = new JTextField();
sex.setFont(new Font("宋体", Font.PLAIN, 16));
sex.setBounds(462, 66, 65, 30);
JTextField age = new JTextField();
age.setBounds(618, 66, 65, 30);
age.setFont(new Font("宋体", Font.PLAIN, 16));
JTextField PhoneNumber = new JTextField();
PhoneNumber.setFont(new Font("宋体", Font.PLAIN, 18));
PhoneNumber.setBounds(533, 114, 150, 30);
JButton j1 = new JButton("注册");
JButton j2 = new JButton("取消");
j1.setBounds(12, 385, 72, 36);
j1.setFont(new Font("宋体", Font.PLAIN, 14));
j2.setBounds(685, 385, 72, 36);
j2.setFont(new Font("宋体", Font.PLAIN, 14));
JRadioButton j3 = new JRadioButton("我已阅读服务条款");
j3.setBounds(340, 335, 150, 40);
j3.setFont(new Font("宋体", Font.PLAIN, 14));
JLabel a1 = new JLabel("姓名");
a1.setFont(new Font("宋体", Font.PLAIN, 20));
a1.setBounds(96, 60, 40, 40);
JLabel a2 = new JLabel("密码");
a2.setFont(new Font("宋体", Font.PLAIN, 20));
a2.setBounds(96, 108, 40, 40);
JLabel a3 = new JLabel("再次输入密码");
a3.setFont(new Font("宋体", Font.PLAIN, 20));
a3.setBounds(10, 130, 150, 100);
JLabel a4 = new JLabel("所属系部");
a4.setFont(new Font("宋体", Font.PLAIN, 20));
a4.setBounds(49, 187, 100, 100);
JLabel a5 = new JLabel("性别");
a5.setFont(new Font("宋体", Font.PLAIN, 20));
a5.setBounds(395, 30, 100, 100);
JLabel a6 = new JLabel("年龄");
a6.setFont(new Font("宋体", Font.PLAIN, 20));
a6.setBounds(550, 30, 100, 100);
JLabel a7 = new JLabel("手机号码");
a7.setFont(new Font("宋体", Font.PLAIN, 20));
a7.setBounds(425, 78, 100, 100);
JTextField a8 = new JTextField();
a8.setBounds(240, 300, 310, 30);
a8.setText(" <服务条款> : 我说啥就是啥,你看着办");
a8.setForeground(Color.RED);
a8.setFont(new Font("宋体", Font.PLAIN, 14));
JLabel a10 = new JLabel("账号");
a10.setFont(new Font("宋体", Font.PLAIN, 20));
a10.setBounds(425, 130, 100, 100);
JLabel a11 = new JLabel("(6-9位)");
a11.setFont(new Font("宋体", Font.PLAIN, 14));
a11.setBounds(330, 114, 60, 24);
JLabel a12 = new JLabel("(6-9位)");
a12.setFont(new Font("宋体", Font.PLAIN, 14));
a12.setBounds(330, 168, 60, 24);
JLabel a13 = new JLabel("注:普通用户请设置10位账号");
a13.setFont(new Font("宋体", Font.PLAIN, 14));
a13.setBounds(425, 220, 300, 24);
a13.setForeground(Color.RED);
JTextField account = new JTextField();
account.setBounds(533, 168, 150, 30);
account.setFont(new Font("宋体", Font.PLAIN, 18));
JLabel a16 = new JLabel("身份");
a16.setFont(new Font("宋体", Font.PLAIN, 20));
a16.setBounds(240, 60, 40, 40);
JTextField a17 = new JTextField();
a17.setBounds(300, 66, 65, 30);
a17.setFont(new Font("宋体", Font.PLAIN, 18));
c.add(a1);
c.add(a2);
c.add(a3);
c.add(a4);
c.add(a5);
c.add(a6);
c.add(a7);
c.add(a8);
c.add(name);
c.add(password1);
c.add(password2);
c.add(sex);
c.add(department);
c.add(age);
c.add(PhoneNumber);
c.add(account);
c.add(j1);
c.add(j2);
c.add(j3);
c.add(a10);
c.add(a11);
c.add(a12);
c.add(a13);
c.add(a16);
c.add(a17);
// 管理员注册Tab
JPanel JP = new JPanel();
JP.setLayout(null);
JLabel a18 = new JLabel("账号");
a18.setFont(new Font("宋体", Font.PLAIN, 20));
a18.setBounds(300, 60, 40, 40);
JLabel a19 = new JLabel("密码");
a19.setFont(new Font("宋体", Font.PLAIN, 20));
a19.setBounds(300, 110, 40, 40);
JLabel a20 = new JLabel("再次输入密码");
a20.setFont(new Font("宋体", Font.PLAIN, 20));
a20.setBounds(220, 160, 150, 40);
JButton a21 = new JButton("注册");
JButton a22 = new JButton("取消");
a21.setBounds(12, 385, 72, 36);
a21.setFont(new Font("宋体", Font.PLAIN, 14));
a22.setBounds(685, 385, 72, 36);
a22.setFont(new Font("宋体", Font.PLAIN, 14));
JRadioButton a23 = new JRadioButton("我已阅读服务条款");
a23.setBounds(340, 335, 150, 40);
a23.setFont(new Font("宋体", Font.PLAIN, 14));
JTextField a24 = new JTextField();
a24.setBounds(240, 300, 310, 30);
a24.setText(" <服务条款> : 我说啥就是啥,你看着办");
a24.setForeground(Color.RED);
a24.setFont(new Font("宋体", Font.PLAIN, 14));
JTextField a25 = new JTextField();
a25.setFont(new Font("宋体", Font.PLAIN, 18));
a25.setBounds(370, 65, 150, 30);
JPasswordField a26 = new JPasswordField();
a26.setBounds(370, 115, 150, 30);
a26.setFont(new Font("宋体", Font.PLAIN, 18));
JPasswordField a27 = new JPasswordField();
a27.setBounds(370, 165, 150, 30);
a27.setFont(new Font("宋体", Font.PLAIN, 18));
JLabel a28 = new JLabel("注:管理员请设置6位账号与6位密码");
a28.setFont(new Font("宋体", Font.PLAIN, 14));
a28.setBounds(300, 220, 250, 24);
a28.setForeground(Color.RED);
JP.add(a18);
JP.add(a19);
JP.add(a20);
JP.add(a21);
JP.add(a22);
JP.add(a23);
JP.add(a24);
JP.add(a25);
JP.add(a26);
JP.add(a27);
JP.add(a28);
// Tab
JTabbedPane tab1 = new JTabbedPane();
tab1.setFont(new Font("宋体", Font.PLAIN, 14));
// 创建第 1 个选项卡
tab1.addTab("普通用户注册", c);
// 创建第 2 个选项卡
tab1.addTab("管理员注册", JP);
this.setContentPane(tab1);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
}
});
this.setResizable(false);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setVisible(true);
j2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
setVisible(false);
}
}
);
a22.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
setVisible(false);
}
}
);
j1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
String d1 = name.getText();
String d2 = password1.getText();
String d3 = department.getText();
String d4 = sex.getText();
String d5 = age.getText();
String d6 = PhoneNumber.getText();
String d7 = account.getText();
String d8 = a17.getText();
User us = new User();
if (d1.length() == 0 || d2.length() < 6 || d2.length() > 9 || d3.length() == 0 || d4.length() == 0
|| d5.length() == 0 || d6.length() == 0 || d7.length() != 10 || d8.length() == 0) {
JOptionPane.showMessageDialog(null, "请输入完整信息.", "提示", JOptionPane.CANCEL_OPTION);
} else {
if (d2.equals(password2.getText())) {
if (j3.isSelected()) {
us.setAccount(d7);
us.setAge(d5);
us.setDepartment(d3);
us.setName(d1);
us.setPassword(d2);
us.setPhone(d6);
us.setSex(d4);
us.setType(d8);
UserRegister use = new UserRegisterImpl();
use.register(us);
JOptionPane.showMessageDialog(null, "注册成功.", "提示", JOptionPane.INFORMATION_MESSAGE);
setVisible(false);
} else {
JOptionPane.showMessageDialog(null, "请同意服务条款.", "提示", JOptionPane.CANCEL_OPTION);
}
} else {
JOptionPane.showMessageDialog(null, "两次密码不一致.", "提示", JOptionPane.CANCEL_OPTION);
}
}
}
}
);
a21.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
String d1 = a25.getText();
String d2 = a26.getText();
Admin ad = new Admin();
if (d1.length() != 6 || d2.length() == 0) {
JOptionPane.showMessageDialog(null, "请输入完整信息.", "提示", JOptionPane.CANCEL_OPTION);
} else {
if (d2.equals(a27.getText())) {
if (a23.isSelected()) {
ad.setAccount(d1);
ad.setPassword(d2);
AdminRegister adm = new AdminRegisterImpl();
adm.register(ad);
JOptionPane.showMessageDialog(null, "注册成功.", "提示", JOptionPane.INFORMATION_MESSAGE);
setVisible(false);
} else {
JOptionPane.showMessageDialog(null, "请同意服务条款.", "提示", JOptionPane.CANCEL_OPTION);
}
} else {
JOptionPane.showMessageDialog(null, "两次密码不一致.", "提示", JOptionPane.CANCEL_OPTION);
}
}
}
}
);
}
public static void main(String[] args) {
Register register = new Register();
register.register();
}
}
Utils包中时间处理的工具类
package com.vector.utils;
import java.time.LocalDate;
public class Days {
/*
* 用LocalDate获取两个日期之间的天数,可正可负
*/
public static int betweenDays(LocalDate start, LocalDate end) {
int sy = start.getYear();
int ey = end.getYear();
int days;
if (sy < ey) {
days = start.lengthOfYear() - start.getDayOfYear();
for (int i = sy + 1; i < ey; i++) {
days += LocalDate.of(i, 12, 31).lengthOfYear();
}
days += end.getDayOfYear();
} else if (sy == ey) {
days = end.getDayOfYear() - start.getDayOfYear();
} else {
days = end.lengthOfYear() - end.getDayOfYear();
for (int i = ey + 1; i < sy; i++) {
days += LocalDate.of(i, 12, 31).lengthOfYear();
}
days += start.getDayOfYear();
days = -days;
}
return days;
}
/*
* 推算多少天以后,可正可负
*/
public static LocalDate reckonDate(LocalDate date, Integer days) {
if (days >= 0)
return date.plusDays(days);
else
return date.minusDays(-days);
}
}
Dao层中实现添加入数据库的代码展示
package com.vector.dao.impl;
import java.sql.Connection;
import org.apache.commons.dbutils.QueryRunner;
import com.vector.bean.Admin;
import com.vector.dao.AdminAddDao;
import com.vector.utils.DataSourceUtils;
public class AdminAddDaoImpl implements AdminAddDao {
public Admin register(Admin ad) {
// TODO Auto-generated method stub
Connection conn = null;
try {
conn = DataSourceUtils.getConnection();
QueryRunner qr = new QueryRunner();
String sql = " insert into admin ( account , password ) values ( ?,?) ";
Object[] obj = { ad.getAccount(), ad.getPassword() };
int in = qr.update(conn, sql, obj);
System.out.println("添加了" + in + "条记录");
} catch (Exception e1) {
// TODO: handle exception
} finally {
DataSourceUtils.closeResource(conn, null, null);
}
return null;
}
}
c3p0配置
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- c3p0默认配置,下面还可以配置多个数据库 -->
<default-config>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/library?characterEncoding=UTF8&useSSL=false
</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">6</property>
<property name="maxPoolSize">10</property>
<property name="maxIdleTime">10000</property>
</default-config>
</c3p0-config>
- 运行截图展示 数据库分表
程序运行截图