一、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,就直接把它设置成1if (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,那么总页数就等于总书籍数目除以每页显示条数+1else {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,就直接把它设置成1if(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,那么总页数就等于总书籍数目除以每页显示条数+1else{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;}//直接设置为1public 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;//增加(保存)书信息@Overridepublic 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删除)@Overridepublic 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修改)@Overridepublic 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查询)@Overridepublic 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;}//查询分页总条数@Overridepublic 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;}//查询分页数据(每条图书数据)@Overridepublic 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;@Overridepublic 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();}//增加(保存)书信息@Overridepublic boolean saveBook(Book book) {int count = bookDAO.save(book);//如果真的有保存的数据,就返回真if(count>0){return true;}return false;}//返回PageResultUtil的结果集对象作为查询翻页数据的结果@Overridepublic 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查询)@Overridepublic Book queryById(int id) {//返回查询到的id值return bookDAO.queryById(id);}//修改书信息(根据ID修改)@Overridepublic boolean updateById(int id, Book book) {int count = bookDAO.updateById(id,book);//如果真的有修改的数据,就返回真if(count>0){return true;}return false;}//删除书信息(根据ID删除)@Overridepublic 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();}@Overridepublic 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);//调用serviceboolean 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);//调用serviceboolean 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");//调用serviceboolean 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'">&nbsp;&nbsp;&nbsp;<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>&nbsp<!-- 还没设置 -->${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>

五、代码写作感受

这半个月我一直在写这个管理系统,前面也为了写这个图书信息管理系统准备了很久,不过最终还是写出来了,虽然中途遇到了很多问题,但也是一个个解决了。不过这个代码还是有问题,比如翻页、数据库的数据重复等等问题,都还没有解决,希望有大佬可以帮我看看具体应该怎么做,谢谢啦。

图书信息管理系统(MVC设计模式)相关推荐

  1. 基于Spring MVC + Spring + MyBatis的【图书信息管理系统(一)】

    资源下载:https://download.csdn.net/download/weixin_44893902/34867237 练习点设计:模糊查询.删除.新增 一.语言和环境 1.实现语言:JAV ...

  2. 基于Spring MVC + Spring + MyBatis的【图书信息管理系统(二)】

    资源下载:https://download.csdn.net/download/weixin_44893902/35123371 练习点设计:添加.删除.修改 一.语言和环境 实现语言:JAVA语言. ...

  3. [源码和文档分享]基于VC++控制台实现的图书信息管理系统

    1 需求分析 开发一个图书信息管理系统,图书信息包括:图书编号.书名.作者.出版社.类别.出版时间.价格等基本信息(也可以根据自己情况进行扩充,比如是否借出.库存量等).使之能提供以下基本功能: 图书 ...

  4. 实现图书增删的代码_不仅仅是图书信息管理系统

    点击蓝字 关注我们 不仅仅是图书信息管理系统 基于双链表,采用面向对象编程方法制作的图书管理系统 ❞ 效果演示 root用户:账号:0,密码:0 普通用户:账号:1001,密码:666666 图书信息 ...

  5. C语言图书信息管理系统简单,线性表简单实现图书信息管理系统(C语言版)

    #include #include #include #include #define OK 1 #define ERROR 0 #define OVERFLOW -2 #define MAXSIZE ...

  6. 商品品牌信息的增删改查操作步骤_图书信息管理系统

    不仅仅是图书信息管理系统 基于双链表,采用面向对象编程方法制作的图书管理系统 来源微信公众号: 不仅仅是图书信息管理系统​mp.weixin.qq.com 效果演示 框架结构 数据层:双链表管理 核心 ...

  7. 大一c语言图书管理系统查询,大一C语言课程设计图书信息管理系统.doc

    高级语言程序设计 课程设计 评语: 学 院 班 级 姓 名 学 号 成 绩 指导老师 年 月 日 一.目的 1. 进一步掌握和利用C语言进行程设计的能力: 2.? 进一步理解和运用结构化程设计的思想和 ...

  8. 数据库课程设计:图书信息管理系统(Java+MySQL)(附程序)

    期末数据库课程设计做了个图书信息管理系统,由于老师给的选题给得早,所以我在开学后的几周就开学搞了,删删改改整了好多,在此整理分享一下: 项目简介: 随着社会的发展,人们对知识的需求也在不断增长.书籍作 ...

  9. 基于Eclipse+Java+Swing+Mysql图书信息管理系统

    基于Eclipse+Java+Swing+Mysql图书信息管理系统 一.系统介绍 二.功能展示 1.主页 2.新增图书信息 3.删除图书信息 三.数据库 四.其他系统实现 五.获取源码 一.系统介绍 ...

  10. 用c语言实现图书信息管理系统

    图书信息管理系统 本文主要是用C语言有关内容实现图书信息管理系统,主要使用了文件.函数.指针.清屏等有关内容.图书信息则包括书名,ISBN码,出版社,价格,出版年月,图书数量,所属学科以及主编等.围绕 ...

最新文章

  1. 上传文件大小的配置Webcong
  2. Android中文API (109) —— SimpleCursorTreeAdapter
  3. golang os.Rename 移动文件 报错 invalid cross-device link 解决方法
  4. 面试之Java知识整理
  5. 单页面axios_Axios封装之取消重复请求和接口缓存
  6. openjdk platform binary 内存_记一次内存溢出导致的生产事故
  7. http://blog.chinaunix.net/uid-25082381-id-3242162.html
  8. Yii CDBCriteria常用方法
  9. c++清空串口缓冲区
  10. ansible 判断和循环
  11. 提高篇 第三部分 图论 第4章 差分约束系统
  12. 2016级算法第六次上机-D.AlvinZH的学霸养成记V
  13. 高光谱地物识别练习-从ENVI标准波普库中选择端元进行物质识别
  14. html跨页面传数组,如何把一个页面的对象数组传到另外一个页面,没有后台,存js_html/css_WEB-ITnose...
  15. 腾讯云首发智能网关流控,公有云进入网络精细管控时代
  16. Go程序设计语言 第1章 入门
  17. HTML特效文字代码大全
  18. LibreELEC 10.0.2发布
  19. Win10运行PS很卡,分享几种解决Win10用PS卡顿提速设置方法
  20. 苹果新园区最新内部效果图流出

热门文章

  1. mybatis order by concat用法
  2. python3GUI--adb调试测试工具By:PyQt5(附下载地址)
  3. 51单片机学习历程——建立新的工程
  4. Maxwell配置案例
  5. matlab脚本栏中间有条线,word中间有一根线 word中间有一条线如何去掉
  6. c语言5名同学3门课程成绩,输入5名同学3门课程的成绩 求: 1)每门课程的平均成绩。2)找出最高分数所对应的学生和课程。...
  7. 教你寫代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!
  8. 深圳自己做网站 服务器,深圳自己做网站 服务器
  9. 合成文字识别需要的训练竖排文字数据集
  10. 基于云效Codeup一键恢复删库保护数据资源,程序员删库跑路不复存在