图书馆管理系统(Maven+Jsp+Servlet+JavaBean+MySql实现)

本项目参考慕课网Jsp课程的拓展项目。项目源代码、数据库文件、拓展项目自带的说明文档都已上传github和码云。
github:图书馆管理系统
码云:图书馆管理系统

一、功能介绍

如图:

系统结构功能图
系统结构功能图

系统流程图

系统流程图

二、界面效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

三、项目分析

3.1开发环境

Eclipse 2018-12
JDK:jdk-8u211-windows-x64
Maven:apache-maven-3.6.1
tomcat:apache-tomcat-8.5.42

3.2总体分析

1.项目采用简单的MVC设计模式,项目结构图如下:
在这里插入图片描述
2.前端页面基本通过post请求提交form表单数据传递给Servlet,Servlet接收数据封装成javaBean对象并调用对应dao层的方法,dao层方法根据传入的javaBean对象值生成对应的SQL语句并执行,再将结果向上返回,Servlet根据返回值跳转到对应界面。
在这里插入图片描述
3.项目涉及12张数据库表,部分表之间存在着外键关联,删除时RESTRICT,更新时CASCADE,在管理员表tb_manager和管理员权限表tb_purview中有两个触发器,用于添加和删除管理员时同时对管理员权限表进行相应操作。
数据库表
在这里插入图片描述
外键
在这里插入图片描述
触发器在这里插入图片描述

3.3主要代码分析

以图书借阅功能为例
在这里插入图片描述

1.工具类:字符串过滤类、时间工具类、数据库连接池

字符串过滤类StrUtil
package com.xxbb.util;
/**  
    * @Title: StrUtil.java
    * @Package com.xxbb.util
    * @Description: TODO(用一句话描述该文件做什么)
    * @author xxbb
    * @version V1.0  
    */

public class StrUtil {
	//处理字符串中得空值
	public static final String nullToString(String v,String toV) {
		if(v==null||"".equals(v)) {
			v=toV;
		}
		return v;
	}
	//过滤危险字符
	public static final String filterStr(String str) {
		str=str.replaceAll(";","");
		str=str.replaceAll("&","&");
		str=str.replaceAll("<","&lt;");
		str=str.replaceAll(">","&gt;");
		str=str.replaceAll("'","");
		str=str.replaceAll("--"," ");
		str=str.replaceAll("/","");
		str=str.replaceAll("%","");
		return str;
	}
	
}

用于对从前前端输入框获取的数据进行处理

时间工具类TimeUtil
package com.xxbb.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @Title: TimeUtil.java
 * @Package com.xxbb.util
 * @Description: TODO(用一句话描述该文件做什么)
 * @author xxbb
 * @version V1.0
 */

public class TimeUtil {
	public static String getDate() {
		Date date = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		return dateFormat.format(date);
	}

	// 获取时间
	public static String getTime() {
		Date date = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
		return dateFormat.format(date);
	}

	// 获取日期时间
	public static String getDateTime() {
		Date date = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return dateFormat.format(date);
	}

	// 日期计算
	public static String getLaterDate(int days) {
		Date date = new Date();
		int leapYear = 366;
		int[] leapMonth = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int commonYear = 365;
		int[] commonMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int daySum = 0;

		// 获取当前年月日
		Calendar calender = Calendar.getInstance();
		calender.setTime(date);
		int year = calender.get(Calendar.YEAR);
		int month = calender.get(Calendar.MONTH) + 1;
		int day = calender.get(Calendar.DATE);

		// 闰年
		if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {

			// 将日期转化为天数进行计算
			for (int i = 0; i < month - 1; i++) {
				daySum += leapMonth[i];
			}
			daySum += day;
			daySum += days;
			// 只考虑加一年的情况
			// 日期增加后没到下一年
			if (daySum <= leapYear) {
				int i = 0;
				for (i = 0;; i++) {
					daySum -= leapMonth[i];
					if (daySum < 1) {
						daySum += leapMonth[i];
						break;
					}
				}
				month = i + 1;
				day = daySum;
			}
			// 日期增加后到了下一年
			else {
				year += 1;
				daySum -= leapYear;
				int i = 0;
				for (i = 0;; i++) {
					daySum -= commonMonth[i];
					if (daySum < 1) {
						daySum += commonMonth[i];
						break;
					}
				}
				month = i + 1;
				day = daySum;

			}

		}
		// 平年
		else {
			// 将日期转化为天数进行计算
			for (int i = 0; i < month - 1; i++) {
				daySum += commonMonth[i];
			}
			daySum += day;
			daySum += days;
			// 只考虑加一年的情况、
			// 日期增加后没到下一年
			if (daySum <= commonYear) {
				int i = 0;
				for (i = 0;; i++) {
					daySum -= commonMonth[i];
					if (daySum < 1) {
						daySum += commonMonth[i];
						break;
					}
				}
				month = i + 1;
				day = daySum;
			}
			// 日期增加后没到下一年
			else {
				year += 1;
				if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
					commonMonth = leapMonth;
				}
				daySum -= commonYear;
				int i = 0;
				for (i = 0;; i++) {
					daySum -= commonMonth[i];
					if (daySum < 1) {
						daySum += commonMonth[i];
						break;
					}
				}
				month = i + 1;
				day = daySum;

			}
		}

		return year + "-" + month + "-" + day;

	}

	// 日期计算
	public static String getLaterDate(String date_str, int days) {
		int leapYear = 366;
		int[] leapMonth = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int commonYear = 365;
		int[] commonMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int daySum = 0;

		// 获取日期
		int year=Integer.parseInt(date_str.substring(0,4));
		int month = Integer.parseInt(date_str.substring(5,7));
		int day = Integer.parseInt(date_str.substring(8,10));

		// 闰年
		if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {

			// 将日期转化为天数进行计算
			for (int i = 0; i < month - 1; i++) {
				daySum += leapMonth[i];
			}
			daySum += day;
			daySum += days;
			// 只考虑加一年的情况
			// 日期增加后没到下一年
			if (daySum <= leapYear) {
				int i = 0;
				for (i = 0;; i++) {
					daySum -= leapMonth[i];
					if (daySum < 1) {
						daySum += leapMonth[i];
						break;
					}
				}
				month = i + 1;
				day = daySum;
			}
			// 日期增加后到了下一年
			else {
				year += 1;
				daySum -= leapYear;
				int i = 0;
				for (i = 0;; i++) {
					daySum -= commonMonth[i];
					if (daySum < 1) {
						daySum += commonMonth[i];
						break;
					}
				}
				month = i + 1;
				day = daySum;

			}

		}
		// 平年
		else {
			// 将日期转化为天数进行计算
			for (int i = 0; i < month - 1; i++) {
				daySum += commonMonth[i];
			}
			daySum += day;
			daySum += days;
			// 只考虑加一年的情况、
			// 日期增加后没到下一年
			if (daySum <= commonYear) {
				int i = 0;
				for (i = 0;; i++) {
					daySum -= commonMonth[i];
					if (daySum < 1) {
						daySum += commonMonth[i];
						break;
					}
				}
				month = i + 1;
				day = daySum;
			}
			// 日期增加后没到下一年
			else {
				year += 1;
				if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
					commonMonth = leapMonth;
				}
				daySum -= commonYear;
				int i = 0;
				for (i = 0;; i++) {
					daySum -= commonMonth[i];
					if (daySum < 1) {
						daySum += commonMonth[i];
						break;
					}
				}
				month = i + 1;
				day = daySum;

			}
		}

		return year + "-" + month + "-" + day;

	}
}

其中getDate()用于获取当前日期:“yyyy-MM-dd”,
getTime()用于获取当前时间:“HH:mm:ss”,
getDateTime()用于获取当前日期时间:“yyyy-MM-dd HH:mm:ss”。
getLaterDate(int days)用于图书借阅时获取当前时间并计算归时间;
getLaterDate(String date_str,int days)用于图书续借时计算续借后的归还日期,date_str用于传入原图书归还时间,days用于传入续借的天数。
由于一般图书馆的一次续借天数不会超过一年,故在日期计算中只考虑了原归还时间到其下一年的日期计算,若days的值使时间跨度超过了一年,则运行时会提示month数组越界。

数据库连接池 ConnectionManager
package com.xxbb.util;
/**  
    * @Title: ConnectionManager.java
    * @Package com.xxbb.test
    * @Description: TODO(用一句话描述该文件做什么)
    * @author xxbb
    * @version V1.0  
    */

import java.sql.Connection;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public final class ConnectionManager {
	//使用单例模式创建数据库连接池
	private static ConnectionManager instance;
	private static ComboPooledDataSource dataSource;
	
	private ConnectionManager() {
		dataSource=new ComboPooledDataSource();
		//防止通过反射进行实例化而破坏单例
		if(instance!=null) {
			throw new RuntimeException("Object has been instanced!!!");
		}
	}
	public static final ConnectionManager getInstance() {
		if(instance==null) {
			try {
				instance=new ConnectionManager();
			}catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
		return instance;
	}
	public synchronized final Connection getConnection() {
		Connection conn=null;
		try {
			conn=dataSource.getConnection();
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return conn;
	}
}

饿汉式构建c3p0数据库连接池。

2.JavaBean对象

BookBorrowForm
package com.xxbb.actionform;

/**
 * @Title: BookBorrowForm.java
 * @Package com.xxbb.actionform
 * @Description: TODO 借阅信息
 * @author xxbb
 * @version V1.0
 */

public class BookBorrowForm {
	// tb_bookborrow
	private Integer id;
	private Integer readerId;
	private Integer bookId;
	private String borrowTime;
	private String returnTime;
	private String operator;
	private Integer ifBack;

	// tb_book
	private String bookType;
	private String bookBarcode;
	private String bookName;
	private String bookcaseName;
	private Double price;
	private String author;
	// tb_reader
	private String readerName;
	private String sex;
	private String readerBarcode;
	private String birthday;
	private String paperType;
	private String paperNo;
	private String telephone;
	private String readerType;
	private Integer degree;

	// tb_publishing
	private String publishName;

	public BookBorrowForm() {
		super();
	}

	@Override
	public String toString() {
		return "BookBorrowForm [id=" + id + ", readerId=" + readerId + ", bookId=" + bookId + ", borrowTime="
				+ borrowTime + ", returnTime=" + returnTime + ", operator=" + operator + ", ifBack=" + ifBack
				+ ", bookType=" + bookType + ", bookBarcode=" + bookBarcode + ", bookName=" + bookName
				+ ", bookcaseName=" + bookcaseName + ", price=" + price + ", author=" + author + ", readerName="
				+ readerName + ", sex=" + sex + ", readerBarcode=" + readerBarcode + ", birthday=" + birthday
				+ ", paperType=" + paperType + ", paperNo=" + paperNo + ", telephone=" + telephone + ", readerType="
				+ readerType + ", degree=" + degree + ", publishName=" + publishName + "]";
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Integer getReaderId() {
		return readerId;
	}

	public void setReaderId(Integer readerId) {
		this.readerId = readerId;
	}

	public Integer getBookId() {
		return bookId;
	}

	public void setBookId(Integer bookId) {
		this.bookId = bookId;
	}

	public String getBorrowTime() {
		return borrowTime;
	}

	public void setBorrowTime(String borrowTime) {
		this.borrowTime = borrowTime;
	}

	public String getReturnTime() {
		return returnTime;
	}

	public void setReturnTime(String returnTime) {
		this.returnTime = returnTime;
	}

	public String getOperator() {
		return operator;
	}

	public void setOperator(String operator) {
		this.operator = operator;
	}

	public Integer getIfBack() {
		return ifBack;
	}

	public void setIfBack(Integer ifBack) {
		this.ifBack = ifBack;
	}

	public String getBookType() {
		return bookType;
	}

	public void setBookType(String bookType) {
		this.bookType = bookType;
	}

	public String getBookBarcode() {
		return bookBarcode;
	}

	public void setBookBarcode(String bookBarcode) {
		this.bookBarcode = bookBarcode;
	}

	public String getBookName() {
		return bookName;
	}

	public void setBookName(String bookName) {
		this.bookName = bookName;
	}

	public String getBookcaseName() {
		return bookcaseName;
	}

	public void setBookcaseName(String bookcaseName) {
		this.bookcaseName = bookcaseName;
	}

	public Double getPrice() {
		return price;
	}

	public void setPrice(Double price) {
		this.price = price;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getReaderName() {
		return readerName;
	}

	public void setReaderName(String readerName) {
		this.readerName = readerName;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public String getReaderBarcode() {
		return readerBarcode;
	}

	public void setReaderBarcode(String readerBarcode) {
		this.readerBarcode = readerBarcode;
	}

	public String getBirthday() {
		return birthday;
	}

	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}

	public String getPaperType() {
		return paperType;
	}

	public void setPaperType(String paperType) {
		this.paperType = paperType;
	}

	public String getPaperNo() {
		return paperNo;
	}

	public void setPaperNo(String paperNo) {
		this.paperNo = paperNo;
	}

	public String getTelephone() {
		return telephone;
	}

	public void setTelephone(String telephone) {
		this.telephone = telephone;
	}

	public String getReaderType() {
		return readerType;
	}

	public void setReaderType(String readerType) {
		this.readerType = readerType;
	}

	public Integer getDegree() {
		return degree;
	}

	public void setDegree(Integer degree) {
		this.degree = degree;
	}

	public String getPublishName() {
		return publishName;
	}

	public void setPublishName(String publishName) {
		this.publishName = publishName;
	}

}

JavaBean对象属性对应的是前端页面需要的属性

3.dao层

BaseDaoImpl
package com.xxbb.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.xxbb.dao.BaseDao;
import com.xxbb.util.ConnectionManager;

/**
 * @Title: BaseDaoImpl.java
 * @Package com.xxbb.dao.impl
 * @Description: TODO(用一句话描述该文件做什么)
 * @author xxbb
 * @version V1.0
 */

public class BaseDaoImpl implements BaseDao {
	protected ConnectionManager cm;
	protected Connection conn;
	protected PreparedStatement ps;
	protected ResultSet rs;
	public BaseDaoImpl() {
		
		// 初始化数据库连接池
		cm = ConnectionManager.getInstance();
		
	}
	/**
	 * 
	    * @Title: close  
		* @Description: TODO(这里用一句话描述这个方法的作用)
	 */
	public void close() {
		// TODO Auto-generated method stub
		try {
			if (rs != null) {
				rs.close();
			}
			if (ps != null) {
				ps.close();
			}
			if (conn != null) {
				conn.close();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace(System.err);
		}
	}
	/**
	 * 
	    * @Title: executeQuery  
		* @Description: TODO(这里用一句话描述这个方法的作用)
		* @param sql
		* @return rs
	 */
	@Override
	public ResultSet executeQuery(String sql) {
		// TODO Auto-generated method stub
		conn=cm.getConnection();
		try {
			ps=conn.prepareStatement(sql);
			rs=ps.executeQuery();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			System.err.println(e.getMessage());
		}
		return rs;
	}
	/**
	 * 
	    * @Title: executeUpdate  
		* @Description: TODO(这里用一句话描述这个方法的作用)
		* @param sql
		* @return result
	 */
	@Override
	public int executeUpdate(String sql) {
		// TODO Auto-generated method stub
		int result=0;
		try {
			conn=cm.getConnection();
			ps=conn.prepareStatement(sql);
			result=ps.executeUpdate();
		} catch (SQLException e) {
			// TODO: handle exception
			System.err.println(e.getMessage());
		}
		return result;
	}

}

通过实现dao接口的形式构建数据库操作类,BaseDaoImpl负责数据库连接池的实例化、执行sql语句和关闭连接。由于该类中的属性会在其子类中使用,故将他们定义为保护类型的成员变量

protected ConnectionManager cm;
protected Connection conn;
protected PreparedStatement ps;
protected ResultSet rs;
BookBorrowDaoImpl
package com.xxbb.dao.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.xxbb.actionform.BookBorrowForm;
import com.xxbb.dao.BookBorrowDao;
import com.xxbb.util.TimeUtil;

/**
 * @Title: BookBorrwoDaoImpl.java
 * @Package com.xxbb.dao.impl
 * @Description: TODO(用一句话描述该文件做什么)
 * @author xxbb
 * @version V1.0
 */

public class BookBorrowDaoImpl extends BaseDaoImpl implements BookBorrowDao {
	
	/**
	 * 
	    * @Title: queryForManager  
		* @Description: TODO(这里用一句话描述这个方法的作用)
		* @param str
		* @return
	 */
	@Override
	public List<BookBorrowForm> queryForManager(String[] str) {
		// TODO Auto-generated method stub
		StringBuffer sb=new StringBuffer();
		BookBorrowForm b=null;
		List<BookBorrowForm> bbfs=new ArrayList<BookBorrowForm>();
		//通过时间查询
		if("startDate".equals(str[0])) {
			sb.append("SELECT b.book_name,bb.borrow_time,bb.return_time,p.publish_name,bc.name,b.price,b.id as book_id,bb.id,r.barcode as reader_barcode,b.barcode as book_barcaode,r.name as reader_name,bb.if_back ");
			sb.append("FROM tb_bookborrow bb ");
			sb.append("left join tb_bookinfo b on bb.book_id=b.id ");
			sb.append("join tb_publishing p on b.ISBN=p.isbn ");
			sb.append("join tb_bookcase bc on b.bookcase=bc.id  ");
			sb.append("join tb_reader r on bb.reader_id=r.id ");
			sb.append("where borrow_time between '");
			sb.append(str[1]);
			sb.append("' and '");
			sb.append(str[2]);
			sb.append("' order by bb.if_back");
			System.out.println("通过时间查询借阅信息:"+sb.toString());
		}
		//通过其他条件查询
		else {
			//通过读者信息
			if("readername".equals(str[0])||"readerbarcode".equals(str[0])) {
				sb.append("SELECT b.book_name,bb.borrow_time,bb.return_time,p.publish_name,bc.name,b.price,b.id as book_id,bb.id,r.barcode as reader_barcode,b.barcode as book_barcaode,r.name as reader_name,bb.if_back ");
				sb.append("FROM tb_reader r ");
				sb.append("left join tb_bookborrow bb on r.id=bb.reader_id ");
				sb.append("join tb_bookinfo b on bb.book_id=b.id join tb_publishing p on b.ISBN=p.isbn join tb_bookcase bc on b.bookcase=bc.id ");
				sb.append("where ");
				if("readername".equals(str[0])) {
					sb.append("r.name='");
				}else if("readerbarcode".equals(str[0])) {
					sb.append("r.barcode='");
				}
				sb.append(str[1]);
				sb.append("' order by bb.if_back");
			}
			//通过图书信息
			else if("barcode".equals(str[0])||"bookname".equals(str[0])||"if_back".equals(str[0])) {
				sb.append("SELECT b.book_name,bb.borrow_time,bb.return_time,p.publish_name,bc.name,b.price,b.id as book_id,bb.id,r.barcode as reader_barcode,b.barcode as book_barcaode,r.name as reader_name,bb.if_back ");
				sb.append("FROM tb_bookinfo b ");
				sb.append("left join tb_bookborrow bb on b.id=bb.book_id ");
				sb.append("join tb_reader r on r.id=bb.reader_id join tb_publishing p on b.ISBN=p.isbn join tb_bookcase bc on b.bookcase=bc.id ");
				sb.append("where ");
				if("barcode".equals(str[0])) {
					sb.append("b.barcode='");
				}else if("bookname".equals(str[0])) {
					sb.append("b.book_name='");
				}else if("if_back".equals(str[0])) {
					sb.append("bb.if_back='");
				}
				
				sb.append(str[1]);
				sb.append("' order by bb.if_back");
			}
			System.out.println("通过条件查询借阅信息:"+sb.toString());
		}
		try {
			rs = executeQuery(sb.toString());
			while (rs.next()) {
				b = new BookBorrowForm();
				b.setBookName(rs.getString(1));
				b.setBorrowTime(rs.getString(2));
				b.setReturnTime(rs.getString(3));
				b.setPublishName(rs.getString(4));
				b.setBookcaseName(rs.getString(5));
				b.setPrice(rs.getDouble(6));
				b.setBookId(rs.getInt(7));
				b.setId(rs.getInt(8));
				b.setReaderBarcode(rs.getString(9));
				b.setBookBarcode(rs.getString(10));
				b.setReaderName(rs.getString(11));
				b.setIfBack(rs.getInt(12));
				bbfs.add(b);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			close();
		}
		return bbfs;
	}
	/**
	 * 
	 * @Title: updateBorrow
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param id
	 * @return
	 */
	@Override
	public int updateBorrow(BookBorrowForm bbf) {
		// TODO Auto-generated method stub
		int result = 0;
		//获取续借后时间
		String bbfDate=bbf.getReturnTime();
		String date=TimeUtil.getLaterDate(bbfDate, 30);
		//构建语句
		StringBuffer sb = new StringBuffer();
		sb.append("update tb_bookborrow set return_time='");
		sb.append(date);
		sb.append("' where id=");
		sb.append(bbf.getId());
		System.out.println("图书续借操作:"+sb);
		try {
			result=executeUpdate(sb.toString());
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			close();
		}
		return result;
	}

	/**
	 * 
	 * @Title: bookBorrowSort
	 * @Description: TODO 图书借阅排行
	 * @return
	 */
	@Override
	public List<BookBorrowForm> bookBorrowSort() {
		// TODO Auto-generated method stub
		// 构建查询语句
		StringBuffer sb = new StringBuffer();
		sb.append("select * from ");
		sb.append("(SELECT book_id,count(book_id) as degree FROM tb_bookborrow group by book_id) as borr ");
		sb.append("join (select b.*,c.name as bookcaseName,p.publish_name,t.type_name from tb_bookinfo b ");
		sb.append(" left join tb_bookcase c ");
		sb.append(" on b.bookcase=c.id ");
		sb.append("join tb_publishing p on b.isbn=p.isbn ");
		sb.append("join tb_booktype t on b.type_id=t.id ");
		sb.append("where b.if_delete=0) as book ");
		sb.append("on borr.book_id=book.id ");
		sb.append("order by borr.degree desc limit 10");
		System.out.println("图书馆借阅排行:" + sb.toString());
		List<BookBorrowForm> bbfs = new ArrayList<BookBorrowForm>();
		BookBorrowForm bbf = null;
		try {
			rs = executeQuery(sb.toString());
			while (rs.next()) {
				bbf = new BookBorrowForm();
				bbf.setId(rs.getInt(1));
				bbf.setDegree(rs.getInt(2));
				bbf.setBookBarcode(rs.getString(3));
				bbf.setBookName(rs.getString(4));
				bbf.setAuthor(rs.getString(6));
				bbf.setPrice(Double.valueOf(rs.getString(9)));
				bbf.setBookcaseName(rs.getString(16));
				bbf.setPublishName(rs.getString(17));
				bbf.setBookType(rs.getString(18));
				bbfs.add(bbf);
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e.getMessage());
		} finally {
			close();
		}

		return bbfs;
	}

	/**
	 * 
	 * @Title: query
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param bbf
	 * @return
	 */
	@Override
	public List<BookBorrowForm> query(BookBorrowForm bbf) {
		// TODO Auto-generated method stub
		StringBuffer sb = new StringBuffer();
		BookBorrowForm b = null;
		List<BookBorrowForm> bbfs = new ArrayList<BookBorrowForm>();
		// 判断传入对象是否为空,若为空则查询全部借阅信息
		if (bbf.getId() == null && bbf.getBookId() == null && bbf.getReaderId() == null) {
			sb.append("SELECT b.book_name,bb.borrow_time,bb.return_time,p.publish_name,bc.name,b.price,b.id as book_id,bb.id,r.barcode as reader_barcode,b.barcode as book_barcaode,r.name as reader_name,bb.if_back ");
			sb.append("FROM tb_bookborrow bb ");
			sb.append("left join tb_bookinfo b on bb.book_id=b.id ");
			sb.append("join tb_publishing p on b.ISBN=p.isbn ");
			sb.append("join tb_bookcase bc on b.bookcase=bc.id  ");
			sb.append("join tb_reader r on bb.reader_id=r.id order by bb.if_back");
			System.out.println("查询全部借阅信息: "+sb);
		} else if (bbf.getReaderId() != null) {
			sb.append(
					"SELECT b.book_name,bb.borrow_time,bb.return_time,p.publish_name,bc.name,b.price,b.id as book_id,bb.id,r.barcode as reader_barcode,b.barcode as book_barcaode,r.name as reader_name,bb.if_back ");
			sb.append("FROM tb_bookborrow bb ");
			sb.append("left join tb_bookinfo b on bb.book_id=b.id ");
			sb.append("join tb_publishing p on b.ISBN=p.isbn ");
			sb.append("join tb_bookcase bc on b.bookcase=bc.id  ");
			sb.append("join tb_reader r on bb.reader_id=r.id ");
			sb.append("where bb.if_back=0 and bb.reader_id=");
			sb.append(bbf.getReaderId());
			System.out.println("查询该读者的图书借阅信息:" + sb);
		}
		try {
			rs = executeQuery(sb.toString());
			while (rs.next()) {
				b = new BookBorrowForm();
				b.setBookName(rs.getString(1));
				b.setBorrowTime(rs.getString(2));
				b.setReturnTime(rs.getString(3));
				b.setPublishName(rs.getString(4));
				b.setBookcaseName(rs.getString(5));
				b.setPrice(rs.getDouble(6));
				b.setBookId(rs.getInt(7));
				b.setId(rs.getInt(8));
				b.setReaderBarcode(rs.getString(9));
				b.setBookBarcode(rs.getString(10));
				b.setReaderName(rs.getString(11));
				b.setIfBack(rs.getInt(12));
				bbfs.add(b);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			close();
		}
		return bbfs;
	}

	/**
	 * 
	 * @Title: insertBorrow
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param readerName
	 * @param BookName
	 * @param operator
	 * @return
	 */
	@Override
	public int insertBorrow(int readerId, int bookId, String operator) {
		// TODO Auto-generated method stub
		StringBuffer sb = new StringBuffer();
		int result = 0;
		int limitedTime = 0;
		// 获取系统日期
		Date d = new Date();
		java.sql.Date borrowDate = new java.sql.Date(d.getTime());
		// 查询可借天数
		sb.append("select bt.limited_time from tb_bookinfo b left join tb_booktype bt on bt.id=b.type_id where b.id=");
		sb.append(bookId);
		try {
			rs = executeQuery(sb.toString());
			if (rs.next()) {
				limitedTime = rs.getInt(1);
			} else {
				return 0;
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			close();
		}
		// 计算归还时间
		String returnDate = TimeUtil.getLaterDate(limitedTime);
		// 构建sql语句
		sb.setLength(0);
		sb.append("insert into tb_bookborrow(reader_id,book_id,borrow_time,return_time,operator) values(");
		sb.append(readerId);
		sb.append(",");
		sb.append(bookId);
		sb.append(",'");
		sb.append(borrowDate);
		sb.append("','");
		sb.append(returnDate);
		sb.append("','");
		sb.append(operator);
		sb.append("')");
		System.out.println("插入借阅信息:" + sb);
		try {
			result = executeUpdate(sb.toString());
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			close();
		}

		return result;
	}

	/**
	 * 
	 * @Title: insertReturn
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param bbf
	 * @return
	 */
	@Override
	public int insertReturn(BookBorrowForm bbf) {
		// TODO Auto-generated method stub
		// 获取当前时间作归还时间
		String date = TimeUtil.getDate();
		int result = 0;

		StringBuffer sb = new StringBuffer();
		sb.append("insert into tb_bookreturn(reader_id,book_id,return_time,operator) values(");
		sb.append(bbf.getReaderId());
		sb.append(",");
		sb.append(bbf.getBookId());
		sb.append(",'");
		sb.append(date);
		sb.append("','");
		sb.append(bbf.getOperator());
		sb.append("')");
		StringBuffer sb2 = new StringBuffer();
		sb2.append("update tb_bookborrow set if_back=1 where id=");
		sb2.append(bbf.getId());
		System.out.println("图书归还操作:" + sb.toString() + "  " + sb2.toString());

		try {
			result = executeUpdate(sb.toString());
			result += executeUpdate(sb2.toString());
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			close();
		}
		return result;
	}
}

继承BookBorrowDao接口和基础的数据库操作类BaoDaoImpl。传入各个方法的值基本是对应的JavaBean对象,通过 if 语句判断对象内属性值是否非空来构建对应的sql语句及其查询条件,一般对象中对应数据库主键的属性值为空对查询数据库对应表的全部内容。 SQL语句通过StringBuffer创建,方便对语句的各种情况和查询条件进行追加。构建好的SQL语句调用父类BaseDaoImpl中的executeQuery或executeUpdate方法执行,并创建对应的JavaBean对象或int对象接收结果作为返回值。

Servlet层

BookBorrowServlet
package com.xxbb.action;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.xxbb.actionform.BookForm;
import com.xxbb.actionform.BookTypeForm;
import com.xxbb.actionform.BookcaseForm;
import com.xxbb.actionform.PublishingForm;
import com.xxbb.dao.BookDao;
import com.xxbb.dao.BookTypeDao;
import com.xxbb.dao.BookcaseDao;
import com.xxbb.dao.PublishingDao;
import com.xxbb.dao.impl.BookDaoImpl;
import com.xxbb.dao.impl.BookTypeDaoImpl;
import com.xxbb.dao.impl.BookcaseDaoImpl;
import com.xxbb.dao.impl.PublishingDaoImpl;
import com.xxbb.util.TimeUtil;

/**
 * Servlet implementation class BookServlet
 */
@WebServlet("/book")
public class BookServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private BookTypeDao btd = null;
	private BookDao bd = null;
	private PublishingDao pd = null;
	private BookcaseDao bcd = null;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public BookServlet() {
		btd = new BookTypeDaoImpl();
		bd = new BookDaoImpl();
		pd = new PublishingDaoImpl();
		bcd = new BookcaseDaoImpl();
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("utf-8");
		resp.setContentType("text/html; charset=utf-8");
		
		String action = req.getParameter("action");
		if ("bookTypeQuery".equals(action)) {
			bookTypeQuery(req, resp);
		} else if ("bookTypeAdd".equals(action)) {
			bookTypeAdd(req, resp);
		} else if ("bookTypeDel".equals(action)) {
			bookTypeDelete(req, resp);
		} else if ("bookTypeModifyQuery".equals(action)) {
			bookTypeModifyQuery(req, resp);
		} else if ("bookTypeModify".equals(action)) {
			bookTypeModify(req, resp);
		} else if ("bookQuery".equals(action)) {
			bookQuery(req, resp);
		} else if ("bookDetail".equals(action)) {
			bookDetail(req, resp);
		} else if ("bookQueryAll".equals(action)) {
			bookQueryAll(req, resp);
		} else if ("bookModifyQuery".equals(action)) {
			bookModifyQuery(req, resp);
		} else if ("bookModify".equals(action)) {
			bookModify(req, resp);
		} else if ("bookAdd".equals(action)) {
			bookAdd(req, resp);
		} else if ("bookInfoQuery".equals(action)) {
			bookInfoQuery(req, resp);
		} else if ("bookDel".equals(action)) {
			bookDel(req, resp);
		} else if ("bookAddQuery".equals(action)) {
			bookAddQuery(req, resp);
		}

	}

	private void bookTypeQuery(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		List<BookTypeForm> btfs = btd.query(new BookTypeForm());
		if (btfs.isEmpty()) {
			req.setAttribute("fflag", "no");
			req.getRequestDispatcher("bookType.jsp").forward(req, resp);
		} else {
			req.setAttribute("fflag", "yes");
			req.setAttribute("btfs", btfs);
			req.getRequestDispatcher("bookType.jsp").forward(req, resp);
		}
	}

	private void bookTypeAdd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		int result = 0;
		BookTypeForm btf = new BookTypeForm();

		btf.setTypeName(req.getParameter("typeName"));
		btf.setLimitedTime(Integer.valueOf(req.getParameter("time")));

		result = btd.insert(btf);
		if (result == 0) {
			req.setAttribute("error", "图书类型信息添加失败!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else if (result == -1) {
			req.setAttribute("error", "该图书类型信息已经添加!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.getRequestDispatcher("bookType_ok.jsp?para=1").forward(req, resp);
		}

	}

	private void bookTypeDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		int result = 0;
		BookTypeForm btf = new BookTypeForm();

		btf.setId(Integer.valueOf(req.getParameter("id")));

		result = btd.delete(btf);
		if (result == 0) {
			req.setAttribute("error", "删除图书类型信息失败!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.getRequestDispatcher("bookType_ok.jsp?para=3").forward(req, resp);
		}
	}

	private void bookTypeModifyQuery(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		req.setAttribute("id", req.getParameter("id"));
		req.setAttribute("name", req.getParameter("name"));
		req.setAttribute("time", req.getParameter("time"));
		req.getRequestDispatcher("bookType_Modify.jsp").forward(req, resp);
	}

	private void bookTypeModify(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		int result = 0;
		BookTypeForm btf = new BookTypeForm();
		btf.setId(Integer.valueOf(req.getParameter("id")));
		btf.setLimitedTime(Integer.valueOf(req.getParameter("time")));

		result = btd.update(btf);
		if (result == 0) {
			req.setAttribute("error", "修改图书类型信息失败!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.getRequestDispatcher("bookType_ok.jsp?para=2").forward(req, resp);
		}
	}

	private void bookQuery(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String[] funcs = new String[2];

		funcs[0] = req.getParameter("f");
		funcs[1] = req.getParameter("key");

		List<BookForm> bfs = bd.query(funcs);
		if (bfs.isEmpty()) {
			req.setAttribute("func", funcs[0]);
			req.setAttribute("value", funcs[1]);
			req.setAttribute("fflag", "no");
			req.getRequestDispatcher("bookQuery.jsp").forward(req, resp);
		} else {
			req.setAttribute("func", funcs[0]);
			req.setAttribute("value", funcs[1]);
			req.setAttribute("bfs", bfs);
			req.getRequestDispatcher("bookQuery.jsp").forward(req, resp);
		}

	}

	private void bookQueryAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		List<BookForm> bfs = bd.query(new BookForm());
		if (bfs.isEmpty()) {
			req.setAttribute("fflag", "no");
			req.getRequestDispatcher("bookQuery.jsp").forward(req, resp);
		} else {
			req.setAttribute("bfs", bfs);
			req.getRequestDispatcher("bookQuery.jsp").forward(req, resp);
		}

	}

	private void bookDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		BookForm bf = new BookForm();
		bf.setId(Integer.valueOf(req.getParameter("id")));
		List<BookForm> bfs = bd.query(bf);
		if (bfs.isEmpty()) {
			req.setAttribute("error", "查看图书具体信息出错,请重试!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.setAttribute("b", bfs.get(0));
			req.getRequestDispatcher("book_detail.jsp").forward(req, resp);
		}
	}

	private void bookModifyQuery(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		List<BookTypeForm> btfs = btd.query(new BookTypeForm());
		List<PublishingForm> pfs = pd.query(new PublishingForm());
		List<BookcaseForm> bcfs = bcd.query(new BookcaseForm());

		BookForm bf = new BookForm();
		bf.setId(Integer.valueOf(req.getParameter("id")));
		List<BookForm> bfs = bd.query(bf);
		if (btfs.isEmpty() || bcfs.isEmpty() || bfs.isEmpty() || pfs.isEmpty()) {
			req.setAttribute("error", "进入图书信息修改页面出错,请重试!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.setAttribute("b", bfs.get(0));
			req.setAttribute("bcfs", bcfs);
			req.setAttribute("btfs", btfs);
			req.setAttribute("pfs", pfs);
			req.getRequestDispatcher("book_Modify.jsp").forward(req, resp);
		}

	}

	private void bookModify(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		int result = 0;
		BookForm bf = new BookForm();
		HttpSession hs = req.getSession();

		bf.setId(Integer.valueOf(req.getParameter("id")));
		bf.setBookBarcode(req.getParameter("barcode"));
		bf.setBookName(req.getParameter("bookName"));
		bf.setBookTypeId(Integer.valueOf(req.getParameter("typeId")));
		bf.setAuthor(req.getParameter("author"));
		bf.setTranslator(req.getParameter("translator"));
		bf.setIsbn((req.getParameter("isbn")));
		bf.setPrice(Double.valueOf(req.getParameter("price")));
		bf.setPage(Integer.valueOf(req.getParameter("page")));
		bf.setBookcaseId(Integer.valueOf(req.getParameter("bookcaseid")));
		bf.setOperator((String) hs.getAttribute("username"));
		result = bd.update(bf);
		if (result == 0) {
			req.setAttribute("error", "修改图书信息失败,请重试!!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else if (result == -1) {
			req.setAttribute("error", "图书条形码已存在,请修改!!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.getRequestDispatcher("book_ok.jsp?para=2").forward(req, resp);
		}
	}

	private void bookDel(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		int result = 0;
		BookForm bf = new BookForm();
		bf.setId(Integer.valueOf(req.getParameter("id")));
		result = bd.delete(bf);
		if (result == 0) {
			req.setAttribute("error", "删除图书信息失败,请重试!!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.getRequestDispatcher("book_ok.jsp?para=3").forward(req, resp);
		}
	}

	private void bookInfoQuery(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		List<BookForm> bfs = bd.query(new BookForm());
		if (bfs.isEmpty()) {
			req.setAttribute("fflag", "no");
			req.getRequestDispatcher("book.jsp").forward(req, resp);
		} else {
			req.setAttribute("bfs", bfs);
			req.getRequestDispatcher("book.jsp").forward(req, resp);
		}
	}

	private void bookAddQuery(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		List<BookTypeForm> btfs = btd.query(new BookTypeForm());
		List<PublishingForm> pfs = pd.query(new PublishingForm());
		List<BookcaseForm> bcfs = bcd.query(new BookcaseForm());
		if (btfs.isEmpty() || bcfs.isEmpty() || pfs.isEmpty()) {
			req.setAttribute("error", "进入图书信息修改页面出错,请重试!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.setAttribute("bcfs", bcfs);
			req.setAttribute("btfs", btfs);
			req.setAttribute("pfs", pfs);
			req.getRequestDispatcher("book_add.jsp").forward(req, resp);
		}

	}

	private void bookAdd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		int result = 0;
		BookForm bf = new BookForm();
		HttpSession hs = req.getSession();
		String date = TimeUtil.getDate();

		bf.setBookBarcode(req.getParameter("barcode"));
		bf.setBookName(req.getParameter("bookName"));
		bf.setBookTypeId(Integer.valueOf(req.getParameter("typeId")));
		bf.setAuthor(req.getParameter("author"));
		bf.setTranslator(req.getParameter("translator"));
		bf.setIsbn((req.getParameter("isbn")));
		bf.setPrice(Double.valueOf(req.getParameter("price")));
		bf.setPage(Integer.valueOf(req.getParameter("page")));
		bf.setBookcaseId(Integer.valueOf(req.getParameter("bookcaseid")));
		bf.setOperator((String) hs.getAttribute("username"));
		bf.setIntime(date);

		result = bd.insert(bf);
		if (result == 0) {
			req.setAttribute("error", "添加图书信息失败,请重试!!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else if (result == -1) {
			req.setAttribute("error", "图书条形码已存在,请修改!!");
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		} else {
			req.getRequestDispatcher("book_ok.jsp?para=1").forward(req, resp);
		}
	}

}

Servlet使用的是3.0版本,使用注解代替Web.xml文件。BookBorrowServlet首先声明在该请求下需要使用到的Dao类,在构造方法中进行实例化。

private static final long serialVersionUID = 1L;
private BookBorrowDao bbd;
private ReaderDao rd;
private BookDao bd;
/**
	 * @see HttpServlet#HttpServlet()
	 */
	public BorrowServlet() {
		bbd = new BookBorrowDaoImpl();
		rd = new ReaderDaoImpl();
		bd = new BookDaoImpl();
	}

其中serialVersionUID据我现在的了解是用于序列化时的版本控制使用,对于我现在这个项目没用用处,但还是把它留着了,其他三个分别是需要用到的数据库操作类,由于只在该Servlet中使用,故定义为私有类型的成员变量。当Servlet被调用时进行实例化。
使用Service方法接收前端请求,获取请求中的action参数,通过 if 判断调用对应的方法,在对应的方法内进一步接收请求数据,调用对应的dao层对象的方法,判断其返回值来跳转到对应界面。
这里我个人是不推荐在dao层方法里构建SQL语句的,可以再建一层service层,在service层的对应类中对获取数据逻辑处理,构建SQL语句,将SQL语句直接传给dao层执行就好了,dao层结果可以先返回service进行逻辑处理,再返回给Serlvet,通过判断跳转至对应的前端界面。
但本项目的业务逻辑较为简单,除了要构建SQL语句之外也没有其他业务逻辑要处理,就和原项目案例一样将SQL语句的构建放在了dao层

前端页面

在这里插入图片描述
banner.jsp用于验证是否登录并显示当前管理员账号,若未读取到管理员账号则跳转至登录界面
navigation.jsp用于根据登录用户的权限并结合menu.js生成导航栏
copyright.jsp用于版权信息的说明
bookBorrow.jsp

<%@page import="com.xxbb.actionform.BookBorrowForm"%>
<%@page import="com.xxbb.actionform.ReaderForm"%>
<%@page contentType="text/html; charset=utf-8" language="java" import="java.sql.*" errorPage=""%>
<%@page import="java.util.*"%>
<html>
<%
	int borrowNumber = 0;
%>
<head>
<title>图书馆管理系统</title>
<link href="CSS/style.css" rel="stylesheet">
<script language="javascript">
	function checkreader(form) {
		if (form.barcode.value == "") {
			alert("请输入读者条形码!");
			form.barcode.focus();
			return;
		}
		form.submit();
	}
	function checkbook(form) {
		if (form.barcode.value == "") {
			alert("请输入读者条形码!");
			form.barcode.focus();
			return;
		}
		if (form.inputkey.value == "") {
			alert("请输入查询关键字!");
			form.inputkey.focus();
			return;
		}
		if (form.number.value - form.borrowNumber.value <= 0) {	
			alert("您不能再借阅其他图书了!");
			return;
		}
		form.submit();
	}
</script>
</head>
<body onLoad="clockon(bgclock)">
	<%@include file="banner.jsp"%>
	<%@include file="navigation.jsp"%>
	<table width="778" border="0" cellspacing="0" cellpadding="0"
		align="center">
		<tr>
			<td valign="top" bgcolor="#FFFFFF"><table width="100%"
					height="509" border="0" align="center" cellpadding="0"
					cellspacing="0" bgcolor="#FFFFFF" class="tableBorder_gray">
					<tr>
						<td height="27" valign="top" style="padding: 5px;"
							class="word_orange">当前位置:图书借还 &gt; 图书借阅 &gt;&gt;&gt;</td>
					</tr>
					<tr>
						<td align="center" valign="top" style="padding: 5px;"><table
								width="100%" border="0" cellspacing="0" cellpadding="0">
								<form name="form1" method="post"
									action="borrow?action=bookborrow">
									<tr>
										<td height="47" background="Images/borrowBackRenew.gif">&nbsp;</td>
									</tr>
									<tr>
										<td height="72" align="center" valign="top"
											background="Images/main_booksort_1.gif" bgcolor="#F8BF73"><table
												width="96%" border="0" cellpadding="1" cellspacing="0"
												bordercolor="#FFFFFF" bgcolor="#F8BF73">
												<tr>
													<td valign="top" bgcolor="#F8BF73">
														<table width="100%" border="0" cellpadding="0"
															cellspacing="0" bgcolor="#FFFFFF">


															<tr>
																<td><table width="90%" height="21" border="0"
																		cellpadding="0" cellspacing="0">
																		<tr>
																			<td width="24%" height="18"
																				style="padding-left: 7px; padding-top: 7px;"><img
																				src="Images/reader_checkbg.jpg" width="142"
																				height="18"></td>
																			<td width="76%" style="padding-top: 7px;">读者条形码:
																				<input name="barcode" type="text" id="barcode"
																				value="${readerinfo.barcode }" size="24"> &nbsp; <input
																				name="Button" type="button" class="btn_grey"
																				value="确定" onClick="checkreader(form1)">
																			</td>
																		</tr>
																	</table></td>
															</tr>
															<tr>
																<td height="13" align="left" style="padding-left: 7px;"><hr
																		width="90%" size="1"></td>
															</tr>
															<tr>
																<td align="center"><table width="96%" border="0"
																		cellpadding="0" cellspacing="0">
																		<tr>
																			<td height="27">&nbsp;&nbsp;&nbsp;&nbsp;名: <input
																				name="readername" type="text" id="readername"
																				value="${readerinfo.name }"></td>
																			<td>&nbsp;&nbsp;&nbsp;&nbsp;别: <input
																				name="sex" type="text" id="sex" value="${readerinfo.sex }"></td>
																			<td>读者类型: <input name="readerType" type="text"
																				id="readerType" value="${readerinfo.typeName }"></td>
																		</tr>
																		<tr>
																			<td height="27">证件类型: <input name="paperType"
																				type="text" id="paperType" value="${readerinfo.paperType }"></td>
																			<td>证件号码: <input name="paperNo" type="text"
																				id="paperNo" value="${readerinfo.paperNO }"></td>
																			<td>可借数量: <input name="number" type="text"
																				id="number" value="${readerinfo.allowBorrowAmount }" size="17">&nbsp;
																			</td>
																		</tr>
																	</table></td>
															</tr>

														</table>
													</td>
												</tr>
												<tr>
													<td height="32" background="Images/borrow_if.gif">&nbsp;添加的依据:
														<input name="f" type="radio" class="noborder"
														value="barcode" checked> 图书条形码 &nbsp;&nbsp; <input
														name="f" type="radio" class="noborder" value="bookname">
														图书名称&nbsp;&nbsp; <input name="inputkey" type="text"
														id="inputkey" size="50"> <input name="Submit2"
														type="submit" class="btn_grey" value="确定"
														onClick="checkbook(form1)"> <input name="operator"
														type="hidden" id="operator" value="${username }">
														<input name="Button" type="button" class="btn_grey"
														value="完成借阅"
														onClick="window.location.href='bookBorrow.jsp'">
													</td>
												</tr>
												<tr>
													<td valign="top" bgcolor="#FCEC9A" style="padding: 5px"><table
															width="99%" border="1" cellpadding="0" cellspacing="0"
															bordercolor="#FFFFFF" bordercolorlight="#FFFFFF"
															bordercolordark="#F6B83B" bgcolor="#FFFFFF">
															<tr align="center" bgcolor="#F9D16B">
																<td width="29%" height="25">图书名称</td>
																<td width="12%">借阅时间</td>
																<td width="14%">应还时间</td>
																<td width="17%">出版社</td>
																<td width="14%">书架</td>
																<td colspan="2">定价(元)</td>
															</tr>
														<c:forEach items="${borrowinfo }" var="b">
															<tr>
																<td height="25" style="padding: 5px;">&nbsp;${b.bookName }</td>
																<td style="padding: 5px;">&nbsp;${b.borrowTime }</td>
																<td style="padding: 5px;">&nbsp;${b.returnTime }</td>
																<td align="center">&nbsp;${b.publishName }</td>
																<td align="center">&nbsp;${b.bookcaseName }</td>
																<td width="14%" align="center">&nbsp;${b.price }</td>
															</tr>
															<input name="addBorrowNumber" type="hidden"
																id="addBorrowNumber" value="<%=++borrowNumber%>">
														</c:forEach>
															
														</table></td>
												</tr>

											</table></td>

									</tr>
									<tr>
										<td height="19" background="Images/main_booksort_2.gif">&nbsp;</td>
									</tr>
									<input name="borrowNumber" type="hidden" id="borrowNumber" value="<%=borrowNumber%>">
								</form>
							</table></td>
					</tr>
				</table> <%@ include file="copyright.jsp"%></td>
		</tr>
	</table>
</body>
</html>

jsp页面内用过form表单或href标签提交请求,使用JSTL标签库的<c:if></c:if>和<c:forEach></c:forEach>对Servlet传来数据进行判断和遍历。

四、项目总结

1.课程提供的项目源代码和数据库文件内各种的命名不够规范,如数据库字段名既有驼峰命名的borrowTime,也有全小写的bookid之类,这里我的数据库字段命名都是采用小写+下划线,如reader_id。JavaBean对象中也存在驼峰命名和全小写命名的现象,这里我都采用驼峰命名法。jsp文件的名也是全小写、驼峰、下划线命名都有,但由于界面之间关联较多,修改麻烦,故对jsp文件命名没有修改,我个人习惯于用小写+下划线的方式给jsp文件命名
2.原jsp页面采用内嵌java代码的方式获取和遍历数据,现在采用EL表达式和JSTL标签获取和遍历数据
在这里插入图片描述
在这里插入图片描述
3.原项目代码使用String类来构建SQL语句,使SQL语句存在不少冗余,且由于String类immutable不可变的性质,在进行字符串拼接时实际上还是创建StringBuffer对象进行拼接,故在此项目都是是使用StringBuffer对字符串进行拼接。
4.使用PreparedStatement预处理SQL语句只能处理一条SQL语句,不能带有分号,之前一直没有注意过。
5.在数据库中仅在管理员表和权限表之间使用了触发器,使得在添加管理员的同时向权限表也插入一条数据。查询触发器有关资料了解到,触发器由于定义在数据库内部,容易被忽视,在性能和维护上会出现问题,要慎用触发器。
参考网页:
https://blog.csdn.net/sinat_41780498/article/details/80651551
https://bbs.csdn.net/topics/390082068
5.在写项目的过程中,为了能同时看项目里的两个文件,通过vscode打开了项目,一边看vscode上的代码内容一边在Eclipse上写代码。一时图方便在vscode上也改了点代码内容并保存后发现项目在Eclipse上运行不了,所有实现dao接口的实现类daoImpl都在@override上报错。查明原因时该项目的配置被改,jdk版本变成了1.5,改回1.8版本后又提示所Maven下在的jar包找不到。没有深究原因,重新建了个Maven项目把文件全部复制进去又能正常使用。
6.导航栏的一些栏目是在menu.js中加载的,但我修改js文件后点击相应的栏目给我的内容仍然是修改之前的内容。查找资料后发现是因为火狐浏览器缓存的原因,只有重启浏览器修改的js文件才会生效,这也是碰巧使用firefox浏览器来查看项目发现的,之前我基本使用chrome浏览器来查看项目网页,并未出现此问题。
7.由此我对ie Edge浏览器也进行测试,发现IE浏览器没有上述问题,但ie Edge在显示由浏览器到Servlet再到浏览器的中文数据会出现乱码问题,如下图
在这里插入图片描述
我将读者类型名称和可借书数量的数据直接从页面表格上读取,显示再修改页面上变成乱码,经测试只有中文会乱码,故尝试再Servlet中添加了如下两行后问题解决。在chrome和firefox浏览器下不设置下图的两行编码格式也不会出现该问题。
在这里插入图片描述
之后我又去测试了下IE浏览其,发现执行上面功能会报如下错误
在这里插入图片描述
查资料了解到RFC3986文档规定,Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符,而我的地址栏后拼接了读者类型名称如管理员这一类的中文字符,所以报错。
参考博客:https://blog.csdn.net/qq_28165595/article/details/79686681
8.写项目的时每天开机首次运行项目出现过几次404情况如下图
在这里插入图片描述
我都是通过先删除tomcat文件夹里的项目再重启tomcat解决的。

  • 7
    点赞
  • 0
    评论
  • 75
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

大家好,我是双鱼林,前段时间学习了struts技术,我从朋友那里得到一个基于struts的图书管理系统,我仔细研究了下,那些功能我都调试通过了,我把这个系统的程序发布给大家,是学习struts的好资料哦! 程序说明: 系统开发环境: Windows xp sp2 + myEclipse5.5 + Tomcat6.0 + MySQL5.0 数据库文件:直接将数据库目录下的db_librarySys文件夹复制到mysql数据库的data目录下即可 mysql数据库登陆信息: 帐号root,密码123(自己可以在com.core.ConnDB类中修改) 管理员测试帐号: admin 密码: admin 系统功能与特色: (1)图书类别信息管理:作为一个学校的图书馆,涉及到的图书是很多的,这就有必要对图书进行分门别类,这样有利于对图书的查询和管理。不同的图书类别可以借阅的天数也是不一样的,管理员登陆系统后可以对图书类别进行添加,更新和删除操作。 (2)图书信息管理:当管理员对图书类别信息添加完成后,就可以开始进行图书信息的录入了,只有将图书馆拥有的图书录入系统中,读者朋友在登陆系统后才可以查询到自己喜欢的该图书。 (3)读者类别管理:为了方便图书馆管理系统对读者的类别进行了分别,不同的读者类别可以借阅图书的数目是不一样的。管理员在登陆系统后可以这个读者类别信息进行管理,包括添加读者类别信息,修改读者类别,删除读者类别,特别是执行删除操作时需要保持数据库表数据之间的一致性。 (4)读者信息管理:当管理员把读者类别信息编辑好完成后,就可以办理读者信息了,管理员可以添加新的读者信息,修改已经存在的读者信息,删除读者信息。 (5)图书借阅管理:读者可以登陆系统查询自己喜欢的图书,然后到图书馆进行图书借书的登记操作,当读者看完了书或需要归还时,需要拿着自己的图书图书馆进行归还,此时有管理员办理图书归还业务。当然,如果读者借阅了图书因某种原因忘记了归还,管理员还可以对这些信息进行统计,同时,管理员还可以对已经出借的图书进行续借的办理。 (6)系统设置: 管理员登陆系统后可以修改图书馆的信息,可以修改管理其他操作员的信息,可以管理书架信息。 (7)口令更改:无论是管理员或读者身份登陆系统后,都可以对自己的登陆密码进行修改操作,这样保证了系统的安全性。 (8)系统特点:采用MVC设计模式,完全采用面向对象的设计思想,使用了开源框架Struts。
©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值