一、项目说明
长期以来,人们使用传统的人工方式管理图书馆的日常业务,其操作流程比较烦琐。在借书时,读者首先将要借的书和借阅证交给工作人员,然后工作人员将每本书的信息卡片和读者的借阅证放在一个小格栏里,最后在借阅证和每本书贴的借阅条上填写借阅信息。在还书时,读者首先将要还的书交给工作人员,工作人员根据图书信息找到相应的书卡和借阅证,并填好相应的还书信息。太过于繁琐了!所以,我们需求设计一个图书管理系统来方便学生的借书和图书馆管理书籍。
二、项目功能流程结构图
三、项目实现用到的软件以及依赖的jar包和设计模式
3.1 项目依赖的jar包
3.2 项目用到的软件
DEA+SQLyog+ Code With Me.
3.3 项目用到的开发模式以及设计模式
三层架构+单例模式+动态代理模式+装饰者模式。
3.3.1 此项目中在service层运用到了dao层的impl中的单例对象,代码如下
public class BookDaoImpl extends BaseDao<Book> implements BookDao {
private static BookDaoImpl bookDaoImpl = null;
/**
* @description: 单例模式来确保BookDaoImpl只生成一个对象
* @param:
* @return: lms.dao.impl.BookDaoImpl
* @author iik
* @date: 9:07 2021/8/10
*/
public static BookDaoImpl getBookDaoImpl() {
if (bookDaoImpl == null) {
bookDaoImpl = new BookDaoImpl();
}
return bookDaoImpl;
}
/**
* @description: 用于生成单列模式的私有构造函数
* @param:
* @return:
* @author df
* @date: 9:02 2021/8/10
*/
private BookDaoImpl() {
}
}
3.4项目分包
采用三层架构思想分为dao(数据访问层)、entity(实体层)、service(服务层)、utils(工具类)、view(视图层)以及我们自行创建的log用于存放操作数据。
3.5数据库表
创建七张表
book表
booktype表
borrowbook表
manager表
operator表
reader表
readertype表
四、团队合作开发Java插件简介
2021.1版本idea 更新了 9 个新特性,我们小团队开发就用到了其中的一个,code with me.第一次使用这个远程协助功能,需要下载 Code With Me 客户端,也就是说,你不需要下载idea客户端就可以和团队一起协作编写代码,而且最牛逼的一点莫过于开发了一个在线实时通信系统,可以在线发信息、语音 & 视频通话。
五、各功能简介
5.1 登录功能
说明:登录功能展示在用户首页,包含管理员登录和操作员登录以及他们各自的忘记密码功能。
5.1.1 首页运行界面如下
5.1.2 登录功能运行界面展示如下
5.1.3 忘记密码运行界面 (以管理员为例)
5.1.4 查看登录日志
代码如下
package lms.view;
import lms.entity.Manager;
import lms.entity.Operator;
import lms.log.LoginLog;
import lms.service.ManagerService;
import lms.service.OperatorService;
import lms.utils.CMUtility;
import lms.utils.EmailUtil;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
/**
* @NAME: LoginView
* @Description: 登录界面
* @Author iik
* @date: 2021年08月09日 10:48
* @Version 1.0
**/
public class LoginView {
private Properties pro = new Properties();
private BufferedWriter out;
private static String operatorName;
/**
* @description:
* @param: null
* @return:
* @author iik
* @date: 11:24 2021/8/9
*/
public LoginView() {
}
public void index() {
boolean flag = true;
while (flag) {
System.out.println("欢迎进入图书馆管理系统");
System.out.println("1.操作员登录");
System.out.println("2.管理员登录");
System.out.println("3.蜜雪冰城图书馆店");
System.out.println("4.管理员忘记密码?");
System.out.println("5.操作员忘记密码?");
System.out.println("6.退出");
char choice;
switch (choice = CMUtility.readMenuSelection()) {
case '1':
checkOperator();
break;
case '2':
checkManager();
break;
case '3':
new DecratorView().index();
break;
case '4':
EmailUtil.emailIndex();
System.out.println("---------------");
System.out.println("请输入你的账号");
String name = CMUtility.readString(30);
System.out.println("请修改你的密码?");
String password = CMUtility.readString(30);
Manager manager = new Manager();
manager.setName(name);
manager.setPassword(password);
int i = new ManagerService().updatePassword(manager);
if (i>0){
System.out.println("密码修改成功!");
}else {
System.out.println("密码修改失败!");
}
break;
case '5':
EmailUtil.emailIndex();
System.out.println("---------------");
System.out.println("请输入你的账号");
String key = CMUtility.readString(30);
System.out.println("请修改你的密码?");
String value = CMUtility.readString(30);
Operator operator=new Operator();
operator.setName(key);
operator.setPassword(value);
int count = new OperatorService().updatePassword(operator);
if (count>0){
System.out.println("密码修改成功!");
}else {
System.out.println("密码修改失败!");
}
break;
case '6':
System.out.println("要退出是吧");
System.out.println("嗨,早该退出了");
//清空日志并关闭流
try {
out = new BufferedWriter(new FileWriter("D:\\ReconstructionLMP\\src\\lms\\log\\loginlog.txt"));
out = new BufferedWriter(new FileWriter("D:\\ReconstructionLMP\\src\\lms\\log\\operatorlog.txt"));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
flag = false;
default:
}
}
}
private void checkManager() {
System.out.println("请输入你的账号");
String user = CMUtility.readString(20);
System.out.println("请输入你的密码");
String word = CMUtility.readString(20);
Manager manager = new Manager();
manager.setName(user);
manager.setPassword(word);
if (new ManagerService().check(manager)) {
//写日志
checklog(user, "管理员");
secondManagerLoginView();
} else {
System.out.println("登录失败");
}
}
private void secondManagerLoginView() {
boolean flag = true;
while (flag) {
System.out.println("1.主菜单");
System.out.println("2.查看登录日志");
System.out.println("3.注册");
System.out.println("4.退出");
char choice;
switch (choice = CMUtility.readMenuSelection()) {
case '1':
new ManagerView().index();
break;
case '2':
new LoginLog();
break;
case '3':
register();
break;
case '4':
flag = false;
break;
default:
}
}
}
public void checkOperator() {
System.out.println("请输入你的账号");
String user = CMUtility.readString(20);
System.out.println("请输入你的密码");
String word = CMUtility.readString(20);
Operator operator = new Operator();
operator.setName(user);
operator.setPassword(word);
if (new OperatorService().check(operator)) {
//写日志
checklog(user, "操作者");
//赋值操作者的名字
operatorName = user;
secondOperatorLoginView();
} else {
System.out.println("登录失败");
}
}
private void secondOperatorLoginView() {
boolean flag = true;
while (flag) {
System.out.println("1.主菜单");
System.out.println("2.查看登录日志");
System.out.println("3.返回");
char choice;
switch (choice = CMUtility.readMenuSelection()) {
case '1':
new OperatorView().index();
break;
case '2':
new LoginLog();
break;
case '3':
flag = false;
break;
case '4':
new DecratorView().index();
break;
default:
}
}
}
private void register() {
System.out.println("请输入账号");
String user = CMUtility.readString(20);
System.out.println("请输入密码");
String word = CMUtility.readString(20);
Manager manager = new Manager();
manager.setName(user);
manager.setPassword(word);
int count;
count = new ManagerService().insertManager(manager);
if (count > 0) {
System.out.println("注册成功");
} else {
System.out.println("注册失败");
}
}
/* public void forgetPassWord() {
System.out.println("请输入你的账号");
String uesr = CMUtility.readString(20);
Manager manager = new Manager();
manager.setName(uesr);
}*/
public static String getOperatorName() {
return operatorName;
}
private void checklog(String name, String str) {
//登陆成功,使用 Properties 集合储存日志信息
try {
//存入集合中
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
pro.setProperty(name + str + "," + sdf.format(new Date()), "--->登录了系统");
//创建缓冲字符流可以追加日志
out = new BufferedWriter(new FileWriter("D:\\ReconstructionLMP\\src\\lms\\log\\loginlog.txt", true));
out.newLine();//换行
out.flush();//刷新
//加载数据进集合
pro.store(out, null);
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果如下
5.2 管理员功能
5.2.1 管理员功能首页
5.2.2 管理操作员(对操作员进行CRUD操作)
5.2.3 操作员日志查询代码如下 (此处使用的动态代理模式编写)
动态代理写日志工具类
package lms.utils;
import lms.view.LoginView;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
/**
* @NAME: ProxyInvo
* @Description:
* @Author df
* @date: 2021年08月12日 10:42
* @Version 1.0
**/
public class ProxyInvo implements InvocationHandler {
//被代理接口
private Object target;
private Properties pro = new Properties();
public void setTarget(Object target) {
this.target = target;
}
//得到代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
//处理代理类,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//添加日志
//筛选check操作
String name = method.getName();
//存入集合中
String str=LoginView.getOperatorName();
if (str!=null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
pro.setProperty(str + "," + sdf.format(new Date()), "执行了" + name + "操作");
//创建缓冲字符流可以追加日志
BufferedWriter out = new BufferedWriter(new FileWriter("D:\\ReconstructionLMP\\src\\lms\\log\\operatorlog.txt", true));
out.newLine();//换行
out.flush();//刷新
//加载数据进集合
pro.store(out, null);
}
Object result = method.invoke(target, args);
return result;
}
}
具体在service中的代码体现(以ManagerService 为例)
public class ManagerService {
private ManagerDao impl ;
{
//需要代理的真实对象
ManagerDaoImpl impl1 = ManagerDaoImpl.getManagerDaoImpl();
//动态代理工具类(自动生成代理类)对象
ProxyInvo proxyInvo=new ProxyInvo();
proxyInvo.setTarget(impl1);
//自动生成动态代理对象
impl = (ManagerDao) proxyInvo.getProxy();
}
...
}
5.2.4 操作员日志查询运行如下
5.3 操作员功能
5.3.1 操作员功能主界面
5.3.2 操作员主要功能(借阅功能)
5.4 新增功能(蜜雪冰城图书馆分店售卖饮料)
5.4.1 代码实现(此处用到了装饰者模式)
class DecratorView{
public void index(){
Drink drink =null;
double cost = 0;
boolean flag = true;
while (flag){
System.out.println("欢迎来到蜜雪冰城图书馆分店");
System.out.println("1.添加饮料(只可添加一种)");
System.out.println("2.添加配料(可添加多种)");
System.out.println("3.查看当前列表");
System.out.println("4.付钱");
System.out.println("5.退出");
char choice;
switch (choice = CMUtility.readMenuSelection()) {
case '1':
if (drink == null){
drink = addDrink();
cost =drink.cost();
}else {
System.out.println("已添加过饮料,不可再次添加");
}
break;
case '2':
if (drink == null){
System.out.println("还未添加饮料,请先添加饮料");
}else {
drink = addDecorator(drink);
cost = drink.cost();
}
break;
case '3':
System.out.println("当前清单");
System.out.println(drink.cost());
break;
case '4':
if (cost ==0){
System.out.println("当前未添加商品,付个锤子钱");
}else {
pay(cost);
drink = null;
}
break;
case '5':
if (cost ==0){
flag = false;
}else {
System.out.println("cnm,钱都没付还想跑?");
}
break;
default:
}
}
}
private Drink addDrink(){
System.out.println("请选择添加饮料");
System.out.println("1.红茶饮料");
System.out.println("2.果汁饮料");
System.out.println("3.牛奶饮料");
System.out.println("4.酸奶饮料");
char choice;
switch (choice = CMUtility.readMenuSelection()) {
case '1':
Drink blackTea = new BlackTea();
return blackTea;
case '2':
Drink juice = new Juice();
return juice;
case '3':
Drink milk = new Milk();
return milk;
case '4':
Drink yogurt = new Yogurt();
return yogurt;
default:
}
return null;
}
private Drink addDecorator(Drink drink){
boolean flag = true;
while (flag) {
System.out.println("请选择添加配料");
System.out.println("1.巧克力");
System.out.println("2.椰果");
System.out.println("3.燕麦");
System.out.println("4.珍珠");
System.out.println("5.布丁");
System.out.println("6.退出");
char choice;
switch (choice = CMUtility.readMenuSelection()) {
case '1':
drink = new Chocolate(drink);
break;
case '2':
drink = new Coco(drink);
break;
case '3':
drink = new Oat(drink);
break;
case '4':
drink = new Pearl(drink);
break;
case '5':
drink = new Pudding(drink);
break;
case '6':
flag = false;
break;
default:
}
}
return drink;
}
private double pay(Double cost){
boolean flag = true;
while (flag){
if (cost >0){
System.out.println("需要付款:"+cost);
Double payment = CMUtility.readDouble();
cost -=payment;
}else if (cost <0){
System.out.println("付款成功,已找零:"+(-cost));
flag = false;
}else {
System.out.println("付款成功,无需找零");
flag = false;
}
}
return cost=0.0;
}
}