图书信息管理系统(MVC设计模式)
一、MVC设计模式简介在MVC的组成之中会包含以下几点:显示层:JSP、HTML、CSS、JavaScript显示出不牵扯到过多的Java程序,最好的显示出是没有任何的Java程序;控制层:Servlet(接收数据、验证数据、调用业务、跳转页面)控制层不负责数据的显示出来,只是负责将数据处理后交给JSP显示;模型层:完成可重用类设计;(1)显示层(View)代表用户交互界面,在Web应用中,可以是
一、MVC设计模式简介
在MVC的组成之中会包含以下几点:
显示层:JSP、HTML、CSS、JavaScript
显示出不牵扯到过多的Java程序,最好的显示出是没有任何的Java程序;
控制层:Servlet(接收数据、验证数据、调用业务、跳转页面)
控制层不负责数据的显示出来,只是负责将数据处理后交给JSP显示;
模型层:完成可重用类设计;
(1)显示层(View)
代表用户交互界面,在Web应用中,可以是JSP、HTML、CSS、JavaScrip程序。使用MVC模式设计的视图层仅仅进行数据的采集和处理,以及用户的请求,而业务流程的控制和处理则是交给控制层(Controller)和模型层(Model)。
(2)模型层(Model)
模型层更多是Java编写的,它接受视图层请求的数据,然后进行相应的业务处理,并返回最终的处理结果。模型层担负的责任最为核心,并使得应用程序得到重用和可扩展。
(3)控制层(Controller)
控制层是从用户端接收请求,将模型和视图匹配在一起,共同完成用户地请求。它的作用就是告诉容器应该选择什么样的视图以及选择什么样的模型。例如,当一个用户点击一个链接时,控制层接受到请求之后,并不直接进行任何的数据操作,而是把用户的请求信息传递给相应的模型层,并告诉模型应该进行什么样的操作,最后根据操作结果选择符合要求的视图返回给请求用户。
控制器在MVC设计模式中就是一个中间枢纽的作用,协调着视图和模型层的操作。
二、图书信息管理系统基本原理(以保存图书信息为例)
1、首先提交用户在JSP文件(前端页面)填写的图书信息(表单数据)给后端(Servlet层),在Servlet层接收到数据后进行数据转换、封装数据。
2、接着将这些数据传给Service层(业务处理层),Service层再将这些数据传给DAO层(操作数据库层),由DAO层将图书信息保存到数据库。
3、图书信息保存到数据库成功后,将成功信息传到Service层,Service层再将成功信息传到Servlet层,Servlet层接收到成功信息后就跳转到图书列表,由此就成功保存了图书信息。
4、其他删除、修改和查询操作都和保存图书信息的原理基本一致。
三、环境配置及运行结果展示
1、环境配置
Operating System:Windows10
IDEA:2020.2.2
Java:jdk1.8
Mysql: 8.0.19
Tomcat:9.0.31
2、运行结果展示
四、源码展示
1、工具类
DateUtil类
package com.sdk.util;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;
//日期转换工具类(将字符串类型的时间数据类型转换为系统时间格式或者数据库时间格式)
public class DateUtil {
public static java.util.Date strToUtilDate(String strDate){
try {
if(strDate!=null){
//正则表达式是否匹配——年份/月份/日期(yyyy/mm/dd)——的形式
if(Pattern.matches("\\d{4}/\\d{2}/\\d{2}", strDate)){
//SimpleDateFormat中的parse方法可以把String型的字符串转换成特定格式的Date类型数据,
//即将字符串形式的时间格式转换为系统格式
return new SimpleDateFormat("yyyy/MM/dd").parse(strDate);
}
//正则表达式是否匹配——年份-月份-日期(yyyy-mm-dd)——的形式
if(Pattern.matches("\\d{4}-\\d{2}-\\d{2}", strDate)){
return new SimpleDateFormat("yyyy-MM-dd").parse(strDate);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//Java中的时间使用标准类库的java.util.Date,其表示特定的瞬间,精确到毫秒。
//是用距离一个固定时间点的毫秒数(可正可负,long类型)表达一个特定的时间点。
public static java.sql.Date utilToSqlDate(java.util.Date date){
if(date!=null){
//使用date.getTime()获取当前系统时间(精确到毫秒数)
//将该对象发送到数据库时,驱动程序将它转换成一个 SQL DATE 类型的值。
return new java.sql.Date(date.getTime());
}
return null;
}
}
JDBCUtil类
package com.sdk.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
//JDBC工具类(连接MySQL数据库的工具类)
public class JDBCUtil {
//数据库查询地址及协议
//jdbc:mysql:// 是指JDBC连接方式;
//localhost: 是指你的本机地址;
//3306:SQL数据库的端口号;
//user:要连接的数据库的地址;
//?serverTimezone = GMT:修改时区
private static final String URL = "jdbc:mysql://localhost:3306/user?serverTimezone = GMT";
//连接mysql数据库账户名
private static final String USER = "root";
//连接mysql数据库密码
private static final String PASSWORD = "root";
//创建连接桥(定义一个静态数据库连接,但该连接还没赋值)
private static Connection conn = null;
//预编译SQL语句
//PrepareStatement创建,用于发送含有一个或多个参数的SQL语句,
//PrepareStatement对象比Statement对象效率更高,并且可以防止SQL植入
static PreparedStatement ps=null;
//得到数据库查询结果集(数据库查询得到数据后使用该对象来得到数据库的值)
static ResultSet rs=null;
//连接数据库方法
public static Connection getConnection(){
try{
//调用Class.forName()方法加载mysql的数据库驱动程序
//将"com.mysql.cj.jdbc.Driver" 当做参数传入,就是告诉JVM,去"com.mysql.jdbc"这个路径下找Driver类,将其加载到内存中。
Class.forName("com.mysql.cj.jdbc.Driver");
//使用适当的驱动程序类建立与数据库的连接,调用DriverManager对象的getConnection方法,
//获得一个Connection对象,它表示一个打开的连接
conn= DriverManager.getConnection(URL,USER,PASSWORD);
System.out.println("++++++++++"+"数据库连接成功"+"++++++++++");
return conn;
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
//关闭所有的jdbc对象,释放资源,关闭结果集,关闭语句对象和连接对象
//只开不关的话可能会把数据库游标耗光
public static void close(Connection conn, PreparedStatement pre,ResultSet rs){
try{
if(rs!=null){
rs.close();
}
if(pre!=null){
pre.close();
}
if(conn!=null){
conn.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
/* public static void main(String[] args) {
System.out.println(getConnection());
}
*/
}
NumberUtil类
package com.sdk.util;
import java.util.regex.Pattern;
//字符串转换工具类(将字符串转换成int类型或者float类型)
public class NumberUtil {
public static int toInt(String strInt){
if(strInt!=null){
//字符串是否可以匹配1个或多个数字
if(Pattern.matches("\\d{1,}", strInt)){
//Integer.parseInt()是把()里的内容转换成整数
int parseInt = Integer.parseInt(strInt);
return parseInt;
}
}
return 0;
}
public static float toFloat(String strFloat){
if(strFloat!=null){
//字符串是否可以匹配1个或多个数字
if(Pattern.matches("\\d{1,}", strFloat)){
//Integer.parseInt()是把()里的内容转换成浮点数
float parseFloat = Float.parseFloat(strFloat);
return parseFloat;
}
}
return 0;
}
}
PageRequestUtil类
package com.sdk.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//分页请求参数(BookDAOImpl类的queryListForPage方法在执行前sql语句前先在这里得到分页的基本信息)
public class PageRequestUtil {
//当前页数(默认pageNum的值为1)
private int pageNum = 1;
//每页显示数目(默认pageSize的值为6)
private int pageSize = 8;
//总书籍数目
private int totalSize;
//封装查询条件
private Map<String, Object> conditions = new HashMap<>();
//总页数(需要计算)
private int totalPages;
//当前页数据(数据库查询)
private List<?> content;
public int getPageNum() {
//如果pageNum小于1,就直接把它设置成1
if (this.pageNum < 1) {
this.pageNum = 1;
}
//如果pageNum大于总页数,就直接把它设置成总页数
else if (this.pageNum >= this.getTotalPages()) {
this.pageNum = this.getTotalPages();
}
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public Map<String, Object> getConditions() {
return conditions;
}
public void setConditions(Map<String, Object> conditions) {
this.conditions = conditions;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getTotalPages() {
//如果总书籍数目除以每页显示条数的模为0,那么总页数就等于总书籍数目除以每页显示条数
if (this.getTotalSize() % this.getPageSize() == 0) {
this.totalPages = this.getTotalSize() / this.getPageSize();
}
//如果总书籍数目除以每页显示条数的模不为0,那么总页数就等于总书籍数目除以每页显示条数+1
else {
this.totalPages = this.getTotalSize() / this.getPageSize() + 1;
}
return totalPages;
}
public List<?> getContent() {
return content;
}
public void setContent(List<?> content) {
this.content = content;
}
public int getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
}
PageResultUtil类
package com.sdk.util;
import java.util.List;
//分页响应工具类
public class PageResultUtil {
//当前页数(默认pageNum的值为1)
private int pageNum=1;
//每页显示数目(默认pageSize的值为6)
private int pageSize=8;
//总条数(数据库查询)
private int totalSize;
//总页数(计算)
private int totalPages;
//当前页数据(查询)
private List<?> content;
//是否首页
private boolean isFirst;
//是否尾页
private boolean isLast;
//是否有下一页
private boolean hasNext;
//是否有上一页
private boolean hasPre;
//下一页页码
private int nextPage;
//上一页页码
private int prePage;
//第一页页码
private int firstPage;
//最后一页页码
private int lastPage;
public int getPageNum() {
//如果pageNum小于1,就直接把它设置成1
if(this.pageNum<1){
this.pageNum=1;
}
//如果pageNum大于总页数,就直接把它设置成总页数
else if(this.pageNum>=this.getTotalPages()){
this.pageNum = this.getTotalPages();
}
return this.pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
public int getTotalPages() {
//如果总书籍数目除以每页显示条数的模为0,那么总页数就等于总书籍数目除以每页显示条数
if(this.getTotalSize()%this.getPageSize()==0){
this.totalPages =this.getTotalSize()/this.getPageSize();
}
//如果总书籍数目除以每页显示条数的模不为0,那么总页数就等于总书籍数目除以每页显示条数+1
else{
this.totalPages =this.getTotalSize()/this.getPageSize()+1;
}
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public List<?> getContent() {
return content;
}
public void setContent(List<?> content) {
this.content = content;
}
public boolean isFirst() {
//如果现在的页数值后的值为1,则返回真
if(this.getPageNum()==1){
return true;
}
return false;
}
public void setFirst(boolean isFirst) {
this.isFirst = isFirst;
}
public boolean isLast() {
//如果现在的页数值与总页数值相等,则返回真
if(this.getPageNum()==this.getTotalPages()){
return true;
}
return false;
}
public void setLast(boolean isLast) {
this.isLast = isLast;
}
public boolean isHasNext() {
//如果现在的页数值比总页数值小,则返回真
if(this.getPageNum()<this.getTotalPages()){
return true;
}
return false;
}
public void setHasNext(boolean hasNext) {
this.hasNext = hasNext;
}
public boolean isHasPre() {
//如果现在的页数值大于1,则返回真
if(this.getPageNum()>1){
return true;
}
return false;
}
public void setHasPre(boolean hasPre) {
this.hasPre = hasPre;
}
public int getNextPage() {
//如果现在的页数值+1大于等于总页数值,就返回总页数值
if(this.getPageNum()+1>=this.getTotalPages()){
return this.getTotalPages();
}
return this.getPageNum()+1;
}
public void setNextPage(int nextPage) {
this.nextPage = nextPage;
}
public int getPrePage() {
return this.getPageNum()-1;
}
public void setPrePage(int prePage) {
this.prePage = prePage;
}
//直接设置为1
public int getFirstPage() {
return 1;
}
public void setFirstPage(int firstPage) {
this.firstPage = firstPage;
}
public int getLastPage() {
return this.getTotalPages();
}
public void setLastPage(int lastPage) {
this.lastPage = lastPage;
}
}
2、Java bean(封装数据)
Book类
package com.sdkc.bean;
import java.util.Date;
//封装Book数据(与数据库数据一致)
public class Book {
private int id;
private String name;
private String author;
private String publish;
private Date publishdate;
private int page;
private float price;
private String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPublish() {
return publish;
}
public void setPublish(String publish) {
this.publish = publish;
}
public Date getPublishdate() {
return publishdate;
}
public void setPublishdate(Date publishdate) {
this.publishdate = publishdate;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
Users类
package com.sdkc.bean;
//封装Users数据(与数据库数据一致)
public class Users {
private int id;
private String name;
private String password;
private int age;
private String sex;
private String nickname;
private int usertype;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getUsertype() {
return usertype;
}
public void setUsertype(int usertype) {
this.usertype = usertype;
}
}
3、DAO层(操作数据库)
BookDAO接口
package com.sdkc.dao;
import com.sdk.util.PageRequestUtil;
import com.sdkc.bean.Book;
import java.util.List;
public interface BookDAO {
//增加(保存)书信息
public int save(Book book);
//删除书信息(根据ID删除)
public int deleteById(int id);
//修改书信息(根据ID修改)
public int updateById(int id,Book book);
//查询书信息(根据ID查询)
public Book queryById(int id);
//查询分页总条数
public int queryCountForPage(PageRequestUtil pageRequestUtil);
//查询分页数据
public List<Book> queryListForPage(PageRequestUtil pageRequestUtil);
}
BookDAOImpl接口实现类
package com.sdkc.dao;
import com.sdk.util.DateUtil;
import com.sdk.util.JDBCUtil;
import com.sdk.util.PageRequestUtil;
import com.sdkc.bean.Book;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class BookDAOImpl implements BookDAO{
//创建连接桥(定义一个静态数据库连接,但该连接还没赋值)
private Connection conn = null;
//预编译SQL语句
//PrepareStatement创建,用于发送含有一个或多个参数的SQL语句,
//PrepareStatement对象比Statement对象效率更高,并且可以防止SQL植入
private PreparedStatement pre = null;
//得到数据库查询结果集(数据库查询得到数据后使用该对象来得到数据库的值)
private ResultSet rs =null;
//增加(保存)书信息
@Override
public int save(Book book) {
try{
//调用JDBCUtil的getConnection()方法,返回获得的一个Connection对象,它表示一个打开的连接
conn=JDBCUtil.getConnection();
// 创建sql语句,里面的参数等可以用问号代替
String sql="insert into book(name,author,publish,publishdate,page,price,content)values(?,?,?,?,?,?,?)";
//使用Connection 接口prepareStatement方法创建一个PreparedStatement语句对象,该对象用于传递带有一个或多个输入参数的sql语句
pre=conn.prepareStatement(sql);
//给第n个问号分别赋值;
pre.setString(1,book.getName());
pre.setString(2,book.getAuthor());
pre.setString(3,book.getPublish());
//将该对象发送到数据库时,驱动程序将它转换成一个 SQL DATE 类型的值。
pre.setDate(4, DateUtil.utilToSqlDate(book.getPublishdate()));
pre.setInt(5,book.getPage());
pre.setFloat(6,book.getPrice());
pre.setString(7,book.getContent());
/*
* executeUpdate方法用于执行SQL DML语句,即INSERT,UPDATE和DELETE语句,
* 此时返回sql语句执行时操作的数据表中受到影响的行数,返回值是一个整数。
* executeUpdate方法还可用于执行sql DDL语句,如CREATE TABLE, DROP TABLE等。此时返回值为0.
*/
int count=pre.executeUpdate();
return count;
} catch (Exception e) {
e.printStackTrace();
}finally {
//每次使用JDBC的结束的时候都要关闭所有的JDBC对象,释放资源,关闭结果集,关闭语句对象和连接对象
JDBCUtil.close(conn,pre,rs);
}
return 0;
}
//删除书信息(根据ID删除)
@Override
public int deleteById(int id) {
try{
conn=JDBCUtil.getConnection();
String sql="delete from book where id=?";
pre=conn.prepareStatement(sql);
pre.setInt(1,id);
return pre.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn,pre,rs);
}
return 0;
}
//修改书信息(根据ID修改)
@Override
public int updateById(int id, Book book) {
try{
conn=JDBCUtil.getConnection();
String sql="update book set name=?,author=?,publish=?,publishdate=?,page=?,price=?,content=? where id=?";
pre=conn.prepareStatement(sql);
pre.setString(1,book.getName());
pre.setString(2,book.getAuthor());
pre.setString(3,book.getPublish());
pre.setDate(4, DateUtil.utilToSqlDate(book.getPublishdate()));
pre.setInt(5,book.getPage());
pre.setFloat(6,book.getPrice());
pre.setString(7,book.getContent());
pre.setInt(8,id);
int count=pre.executeUpdate();
return count;
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn,pre,rs);
}
return 0;
}
//查询书信息(根据ID查询)
@Override
public Book queryById(int id) {
try{
conn=JDBCUtil.getConnection();
String sql="select * from book where id=?";
pre=conn.prepareStatement(sql);
pre.setInt(1,id);
//executeQuery方法用于执行SELECT查询语句,并返回单个结果集,保存在ResultSet对象中
rs=pre.executeQuery();
/*
*ResultSet是一个结果集,即ResultSet存有一个表(通过执行查询数据库的语句生成),
*该表的当前行可以访问(当前行的初始位置是null),可以使用rs.next()方法移动到下一行(即表的第一行),
*如果新的当前行有效(即有值)就返回true,然后就可以使用get方法获取该行各列的值了,如果不存在下一行,则返回 false
*/
if(rs.next()){
Book book=new Book();
book.setId(rs.getInt("id"));
book.setAuthor(rs.getString("author"));
book.setContent(rs.getString("content"));
book.setName(rs.getString("name"));
book.setPage(rs.getInt("page"));
book.setPrice(rs.getFloat("price"));
book.setPublish(rs.getString("publish"));
book.setPublishdate(rs.getDate("publishdate"));
return book;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn,pre,rs);
}
return null;
}
//查询分页总条数
@Override
public int queryCountForPage(PageRequestUtil pageRequestUtil) {
try{
conn=JDBCUtil.getConnection();
String sql="select count(*) from book ";
pre=conn.prepareStatement(sql);
rs=pre.executeQuery();
if(rs.next()){
//rs.getInt(1)表示,从这个结果集的第一行问第一列里拿值,这个值应该答是个数值类型的所以用int来取,就是getInt()方法内。
return rs.getInt(1);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn,pre,rs);
}
return 0;
}
//查询分页数据(每条图书数据)
@Override
public List<Book> queryListForPage(PageRequestUtil pageRequestUtil) {
//创建一个用来装Book类型的数组
List<Book> list =new ArrayList<Book>();
try{
conn=JDBCUtil.getConnection();
//从pageRequestUtil工具类中得到pageNum和pageSize的信息
//这里是有问题的!!!点击下一页的时候pageNum的值变小了
int pageNum=pageRequestUtil.getPageNum();
int pageSize=pageRequestUtil.getPageSize();
int start=(pageNum-1)*pageSize;
//只能在这里改一下正负值,实际上有很大的问题
if(start<0){
start=-start;
}
//将start和pageSize的值插入sql语句
String sql="select * from book limit "+start+","+pageSize;
pre=conn.prepareStatement(sql);
rs=pre.executeQuery();
while(rs.next()){
Book book=new Book();
book.setId(rs.getInt("id"));
book.setAuthor(rs.getString("author"));
book.setContent(rs.getString("content"));
book.setName(rs.getString("name"));
book.setPage(rs.getInt("page"));
book.setPrice(rs.getFloat("price"));
book.setPublish(rs.getString("publish"));
book.setPublishdate(rs.getDate("publishdate"));
//把book类型的数据装入数组
list.add(book);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn,pre,rs);
}
return list;
}
}
UsersDAO接口
package com.sdkc.dao;
public interface UsersDAO {
public int login(String username, String password);
}
UsersDAOImpl接口实现类
package com.sdkc.dao;
import com.sdk.util.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class UsersDAOImpl implements UsersDAO{
private Connection conn = null;
private PreparedStatement pre = null;
private ResultSet rs =null;
@Override
public int login(String username, String password) {
try{
conn= JDBCUtil.getConnection();
String sql="select count(*) from user where name=? and password=?";
pre=conn.prepareStatement(sql);
pre.setString(1,username);
pre.setString(2,password);
//executeQuery方法用于执行SELECT查询语句,并返回单个结果集,保存在ResultSet对象中
rs=pre.executeQuery();
if(rs.next()){
//rs.getInt(1)表示,从这个结果集的第一行问第一列里拿值,这个值应该答是个数值类型的所以用int来取,就是getInt()方法内。
return rs.getInt(1);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn,pre,rs);
}
return 0;
}
}
4、EncodingFilter过滤器
package com.sdkc.filter;
import java.io.IOException;
public class EncodingFilter implements javax.servlet.Filter {
private String encoding =null;
public void destroy() {
}
public void doFilter(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, javax.servlet.FilterChain chain) throws javax.servlet.ServletException, IOException {
//request.setCharacterEncoding()是设置从request中取得的值或从数据库中取出的值。
request.setCharacterEncoding(encoding);
//chain.doFilter将请求转发给过滤器链下一个filter , 如果没有filter那就是请求的资源
chain.doFilter(request, response);
}
public void init(javax.servlet.FilterConfig fConfig) throws javax.servlet.ServletException {
//在ServletConfig有getInitParameter方法, 这方法的都能从web.xml中获取参数
encoding=fConfig.getInitParameter("encoding");
//保证UTF-8的编码方式
if(encoding!=null){
this.encoding=encoding;
}else {
this.encoding="UTF-8";
}
}
}
5、service层(业务逻辑层)
BookService接口
package com.sdkc.service;
import com.sdk.util.PageRequestUtil;
import com.sdk.util.PageResultUtil;
import com.sdkc.bean.Book;
public interface BookService {
public boolean saveBook(Book book);
public PageResultUtil queryForPage(PageRequestUtil pageRequestUtil);
public Book queryById(int id);
public boolean updateById(int id,Book book);
public boolean deleteById(int id);
}
BookServiceImpl接口实现类
package com.sdkc.service;
import com.sdk.util.PageRequestUtil;
import com.sdk.util.PageResultUtil;
import com.sdkc.bean.Book;
import com.sdkc.dao.BookDAO;
import com.sdkc.dao.BookDAOImpl;
import java.util.List;
//图书业务实现类
public class BookServiceImpl implements BookService{
private BookDAO bookDAO;
//用构造函数初始化bookDAOImpl对象
public BookServiceImpl(){
bookDAO=new BookDAOImpl();
}
//增加(保存)书信息
@Override
public boolean saveBook(Book book) {
int count = bookDAO.save(book);
//如果真的有保存的数据,就返回真
if(count>0){
return true;
}
return false;
}
//返回PageResultUtil的结果集对象作为查询翻页数据的结果
@Override
public PageResultUtil queryForPage(PageRequestUtil pageRequestUtil) {
//在DAO层查询总图书条数
int totalCount=bookDAO.queryCountForPage(pageRequestUtil);
//在DAO层查询每条图书的具体内容
List<Book> content = bookDAO.queryListForPage(pageRequestUtil);
//返回PageResultUtil的对象作为分页查询的结果
PageResultUtil pageResultUtil=new PageResultUtil();
//分别设置pageResultUtil的信息
pageResultUtil.setTotalSize(totalCount);
pageResultUtil.setContent(content);
pageResultUtil.setPageSize(pageRequestUtil.getPageSize());
pageResultUtil.setPageNum(pageRequestUtil.getPageNum());
return pageResultUtil;
}
//查询书信息(根据ID查询)
@Override
public Book queryById(int id) {
//返回查询到的id值
return bookDAO.queryById(id);
}
//修改书信息(根据ID修改)
@Override
public boolean updateById(int id, Book book) {
int count = bookDAO.updateById(id,book);
//如果真的有修改的数据,就返回真
if(count>0){
return true;
}
return false;
}
//删除书信息(根据ID删除)
@Override
public boolean deleteById(int id) {
int count = bookDAO.deleteById(id);
//如果真的有要删除的数据,就返回真
if(count>0){
return true;
}
return false;
}
}
UsersService 接口
package com.sdkc.service;
public interface UsersService {
public boolean login(String username,String password);
}
UsersServiceImpl接口实现类
package com.sdkc.service;
import com.sdkc.dao.UsersDAO;
import com.sdkc.dao.UsersDAOImpl;
public class UsersServiceImpl implements UsersService{
private UsersDAO usersDAO;
public UsersServiceImpl(){
usersDAO=new UsersDAOImpl();
}
@Override
public boolean login(String username, String password) {
int count=usersDAO.login(username,password);
//如果用户名和密码一致,则返回真
if(count>0){
return true;
}
return false;
}
}
6、servlet层(与前端页面交互层)
BookServlet类
package com.sdkc.servlet;
import com.sdk.util.DateUtil;
import com.sdk.util.NumberUtil;
import com.sdk.util.PageRequestUtil;
import com.sdk.util.PageResultUtil;
import com.sdkc.bean.Book;
import com.sdkc.service.BookServiceImpl;
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 java.io.IOException;
import java.util.Date;
//图书控制器
@WebServlet(name = "BookServlet")
public class BookServlet extends HttpServlet {
//private static final long serialVersionUID=1L意思是定义程序序列化ID。
private static final long serialVersionUID=1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//调用doGet方法
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//request.getParameter()是一种取参数的方法,把jsp文件中的数据读取到出来,然后就可以封装利用起来。
/*
*request.getParameter()方法:
* 1.获取通过http协议提交过来的数据,通过容器的实现来取得通过get或者post方式提交过来的数据
* 2.request.getParameter()方法传递的数据,会从web客户端传到web服务器端,代表HTTP请求数据,该方法返回String类型的数据
*/
String type = request.getParameter("type");
if("save".equals(type)){//保存
String name=request.getParameter("name");
String author=request.getParameter("author");
String publish=request.getParameter("publish");
String publishdateStr=request.getParameter("publishdate");
String pageStr=request.getParameter("page");
String priceStr=request.getParameter("price");
String content=request.getParameter("content");
//数据转换
Date publishdate= DateUtil.strToUtilDate(publishdateStr);
int page= NumberUtil.toInt(pageStr);
float price=0.0f;
if(priceStr!=null && !"".equals(pageStr)) {
price = Float.parseFloat(priceStr);
}
//封装数据
Book book=new Book();
book.setAuthor(author);
book.setContent(content);
book.setName(name);
book.setPage(page);
book.setPublish(publish);
book.setPublishdate(publishdate);
book.setPrice(price);
//调用service
boolean flag=new BookServiceImpl().saveBook(book);
if(flag){
//添加成功后跳转到列表
request.getRequestDispatcher("/BookServlet?type=list").forward(request,response);
}else {
}
}else if ("list".equals(type)){//分页
String pageNumStr=request.getParameter("pageNum");
String pageSize=request.getParameter("pageSize");
PageRequestUtil pageRequestUtil=new PageRequestUtil();
pageRequestUtil.setPageNum(NumberUtil.toInt(pageNumStr));
if(pageSize != null && !"".equals(pageSize)) {
pageRequestUtil.setPageSize(NumberUtil.toInt(pageSize));
}
//调用service的queryForPage得到图书的结果集
PageResultUtil pageResultUtil=new BookServiceImpl().queryForPage(pageRequestUtil);
//JSP文件里,将result代替pageResultUtil的结果
request.setAttribute("result",pageResultUtil);
request.getRequestDispatcher("/pages/books/list.jsp").forward(request,response);
}else if("getById".equals(type)){//根据id查询去修改页面
String idStr=request.getParameter("id");
Book book=new BookServiceImpl().queryById(NumberUtil.toInt(idStr));
request.setAttribute("book",book);
//将请求转发到/pages/books/save.jsp这个页面
request.getRequestDispatcher("/pages/books/save.jsp").forward(request,response);
}else if("update".equals(type)){//更新book数据
String name=request.getParameter("name");
String author=request.getParameter("author");
String publish=request.getParameter("publish");
String publishdateStr=request.getParameter("publishdate");
String pageStr=request.getParameter("page");
String priceStr=request.getParameter("price");
String content=request.getParameter("content");
String idStr=request.getParameter("id");
//数据转换
Date publishdate= DateUtil.strToUtilDate(publishdateStr);
int page= NumberUtil.toInt(pageStr);
float price=0.0f;
if(priceStr!=null && !"".equals(pageStr)) {
price = Float.parseFloat(priceStr);
}
int id=NumberUtil.toInt(idStr);
//封装数据
Book book=new Book();
book.setAuthor(author);
book.setContent(content);
book.setName(name);
book.setPage(page);
book.setPublish(publish);
book.setPublishdate(publishdate);
book.setPrice(price);
//调用service
boolean flag = new BookServiceImpl().updateById(id,book);
if(flag){//修改成功后跳转到列表
request.getRequestDispatcher("/BookServlet?type=list").forward(request,response);
}else {
System.out.println(22222);
}
}else if("goAdd".equals(type)){
request.getRequestDispatcher("/pages/books/save.jsp").forward(request,response);
}else if("deleteById".equals(type)){
String idStr=request.getParameter("id");
boolean flag=new BookServiceImpl().deleteById(NumberUtil.toInt(idStr));
if(flag){
request.getRequestDispatcher("/BookServlet?type=list").forward(request,response);
}else {
}
}
}
}
UsersLoginServlet类
package com.sdkc.servlet;
import com.sdkc.service.UsersServiceImpl;
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 java.io.IOException;
@WebServlet(name = "UsersLoginServlet")
public class UsersLoginServlet extends HttpServlet {
//private static final long serialVersionUID=1L意思是定义程序序列化ID。
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收数据
String username=request.getParameter("username");
String password=request.getParameter("password");
//调用service
boolean flag=new UsersServiceImpl().login(username,password);
if(flag){
//登录成功
request.getSession().setAttribute("username",username);
response.sendRedirect("/bookSYS_war_exploded/pages/books/list.jsp");
}else {
//登录失败
request.setAttribute("message","用户名或密码错误!");
request.getRequestDispatcher("/pages/users/login.jsp").forward(request,response);
}
}
}
7、JSP页面(前端部分)
list.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- 这是导入jstl(jsp标准标记库)的语句,导入之后,你就可以使用jstl中的标签了 -->
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>图书信息详细列表</title>
<!-- 连接css文件,href为文件路径,{pageContext.request.contextPath}是JSP取得绝对路径的意思 -->
<!-- rel="stylesheet" 描述了当前页面与href所指定文档的关系.即说明的是,href连接的文档是一个新式表 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/book.css">
<!-- 连接JavaScript文件,src为文件路径 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/book.js"></script>
</head>
<body>
<!-- 和css文件链接 -->
<table id="showTab">
<tr>
<!-- colspan属性代表所占列数 -->
<th colspan="8" id="showHeader">图书信息详细列表</th>
</tr>
<tr>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th>出版日期</th>
<th>页数</th>
<th>价格</th>
<th>内容摘要</th>
<th>操作</th>
</tr>
<!-- forEach标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容。 -->
<!-- 变量book为result.content的值,stat.index输出行号,从0开始,varStatus属性可以方便我们实现一些与行数相关的功能-->
<c:forEach items="${result.content}" var="book" varStatus="stat">
<tr ${stat.index%2==0 ? 'class=odd' : ''}>
<th>${book.name}</th>
<th>${book.author}</th>
<th>${book.publish}</th>
<th>${book.publishdate}</th>
<th>${book.page}</th>
<th>${book.price}</th>
<th>${book.content}</th>
<th>
<!-- href 属性的值可以是任何有效文档的相对或绝对 URL,包括片段标识符和 JavaScript 代码段。如果用户选择了 <a> 标签中的内容,
那么浏览器会尝试检索并显示 href 属性指定的 URL 所表示的文档,或者执行 JavaScript 表达式、方法和函数的列表。 -->
<a href="${pageContext.request.contextPath}/BookServlet?type=getById&id=${book.id}">修改</a>
<a href="${pageContext.request.contextPath}/BookServlet?type=deleteById&id=${book.id}">删除</a>
</th>
</tr>
</c:forEach>
<tr>
<td colspan="8" id="tdBut">
<!-- οnclick="javascript:window.location.href 点击后跳转到 -->
<input type="button" value="继续添加" onclick="javascript:window.location.href='${pageContext.request.contextPath}/BookServlet?type=goAdd'">
<a href="${pageContext.request.contextPath}/BookServlet?type=list&pageNum=${result.firstPage}&pageSize=${result.pageSize}">首页</a>
<a href="${pageContext.request.contextPath}/BookServlet?type=list&pageNum=${result.prePage}&pageSize=${result.pageSize}">上一页</a>
<a href="${pageContext.request.contextPath}/BookServlet?type=list&pageNum=${result.nextPage}&pageSize=${result.pageSize}">下一页</a>
<a href="${pageContext.request.contextPath}/BookServlet?type=list&pageNum=${result.lastPage}&pageSize=${result.pageSize}">尾页</a>
总共${result.totalSize}条,共${result.pageNum}/${result.totalPages}页,每页显示<input id="pageSize" onchange="changePageSize(this.value)" type="number" value="${result.pageSize}">条
跳转到<input id="goPageNum" type="number" value="${result.pageNum}" >页<input type="button" value="go" onclick="goPageNum('${result.pageSize}')">
</td>
</td>
</tr>
</table>
</body>
</html>
save.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- 这是导入jstl(jsp标准标记库)的语句,导入之后,你就可以使用jstl中的标签了 -->
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
<!-- 连接css文件,href为文件路径,{pageContext.request.contextPath} JSP取得绝对路径)-->
<!-- rel="stylesheet" 描述了当前页面与href所指定文档的关系.即说明的是,href连接的文档是一个新式表 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/book.css">
</head>
<body>
<!-- action 属性规定当提交表单时,向/BookServlet发送表单数据。使用Post传输的数据,可以通过设置编码的方式正确转化中文-->
<form action="${pageContext.request.contextPath}/BookServlet" method="post">
<c:if test="${book.id !=null}">
<!-- 获取隐形框 这时可以将隐藏框的参数可以传递给后台 -->
<input type="hidden" name="id" value="${book.id}"/>
<input type="hidden" name="type" value="update"/>
</c:if>
<c:if test="${book.id ==null}">
<input type="hidden" name="type" value="save"/>
</c:if>
<table id="addTab">
<tr>
<th colspan="2"> ${book.id ==null? '添加':'修改'}图书 </th>
</tr>
<tr>
<td>书名</td>
<td><input type ="text" name="name" value="${book.name}"></td>
</tr>
<tr>
<td>作者</td>
<td><input type ="text" name="author" value="${book.author}"></td>
</tr>
<tr>
<td>出版社</td>
<td><input type ="text" name="publish" value="${book.publish}"></td>
</tr>
<tr>
<td>出版日期</td>
<td><input type ="date" name="publishdate" value="${book.publishdate}"></td>
</tr>
<tr>
<td>页数</td>
<td><input type ="number" name="page" value="${book.page}"></td>
</tr>
<tr>
<td>价格</td>
<td><input type ="text" name="price" value="${book.price}"></td>
</tr>
<tr>
<td>内容摘要</td>
<td><textarea name="content">${book.content}</textarea></td>
</tr>
<tr>
<!-- <input type="submit"> 定义为一个提交按钮。提交按钮会把表单数据发送到服务器。 -->
<td colspan="2" id="tdBut"><input type="submit" value="${book.id ==null? '添加':'修改'}" >
<!-- 这是表单重置按钮,点击后会将重置按钮所在的表单中填写的内容清空 -->
<input type="reset" value="取消">
</td>
</tr>
</table>
</form>>
</body>
</html>
login.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login</title>
</head>
<body>
<!-- action 属性规定当提交表单时,向/UsersLoginServlet发送表单数据。使用Post传输的数据,可以通过设置编码的方式正确转化中文-->
<form action="${pageContext.request.contextPath}/UsersLoginServlet" method="post">
<table id="login in">
<tr>
<td class="label">登录名:</td>
<td class="inputContent"><input type="text" name="username"></td>
</tr>
<tr>
<td class="label">登录密码:</td>
<td class="inputContent"><input type="password" name="password"></td>
</tr>
<tr id="loginbut">
<td colspan="2">
<!-- <input type="submit"> 定义为一个提交按钮。提交按钮会把表单数据发送到服务器。 -->
<input type="submit" value="登录">
<!-- 这是表单重置按钮,点击后会将重置按钮所在的表单中填写的内容清空 -->
<input type="reset" value="取消">
</td>
</tr>
<tr id="loginbut1">
<td colspan="2">
<!-- <span>标签是行内元素标签,不分行 -->
<span> 
<!-- 还没设置 -->
${message}
</span>
</td>
</tr>
</table>
</body>
</html>
book.css配置文件
#addTab{
border:1px solid #ccc;
width: 500px;
margin: auto;
border-collapse: collapse;
}
td,th{
border:1px solid #ccc;
}
#tdBut{
text-align: center;
}
#showTab{
border:1px solid #ccc;
width: 800px;
margin: auto;
border-collapse: collapse;
}
#pageSize,#goPageNum{
width: 60px;
}
#showHeader{
background-color:#FFFFCC ;
font-size: 60px;
}
tr[class='odd']{
background-color: #DDA0DD;
}
book.js配置文件
function changePageSize(val){
window.location.href="/bookSYS_war_exploded/BookServlet?type=list&pageSize="+val;
}
function goPageNum(val){
//获取id为goPageNum的input里面的数值
var num=document.getElementById("goPageNum").value;
window.location.href="/bookSYS_war_exploded/BookServlet?type=list&pageSize="+val+"&pageNum="+num;
}
web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 字符编码集过滤器 -->
<!-- 在web.xml 文件中使用<filter>和<filter-mapping>元素对编写的filter类进行注册,并设置它所能拦截的资源。 -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.sdkc.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<!-- 初始化encoding的参数,初始化为UTF—8 -->
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<!-- 拦截所有的,比如.jsp、.js、.html、.do等等 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 登录 -->
<servlet>
<display-name>UsersLoginServlet</display-name>
<!--servlet名称,与servlet-mapping中的servlet-name必须一致-->
<servlet-name>UsersLoginServlet</servlet-name>
<!--servlet类所在的包路径,即上面所在包路径-->
<servlet-class>com.sdkc.servlet.UsersLoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UsersLoginServlet</servlet-name>
<!-- servlet过滤的路径,也就是你在jsp中访问servlet时应该在action中填写的东西 -->
<url-pattern>/UsersLoginServlet</url-pattern>
</servlet-mapping>
<!-- 添加图书 -->
<servlet>
<display-name>BookServlet</display-name>
<servlet-name>BookServlet</servlet-name>
<servlet-class>com.sdkc.servlet.BookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BookServlet</servlet-name>
<!-- servlet过滤的路径,也就是你在jsp中访问servlet时应该在action中填写的东西 -->
<url-pattern>/BookServlet</url-pattern>
</servlet-mapping>
</web-app>
五、代码写作感受
这半个月我一直在写这个管理系统,前面也为了写这个图书信息管理系统准备了很久,不过最终还是写出来了,虽然中途遇到了很多问题,但也是一个个解决了。不过这个代码还是有问题,比如翻页、数据库的数据重复等等问题,都还没有解决,希望有大佬可以帮我看看具体应该怎么做,谢谢啦。
更多推荐
所有评论(0)