Java Web图书管理系统——项目记录

简介

              第一次写博客,图个稀罕。

  • 此项目为B站上面楠哥说java教程里面的web教学实战项目
  • 视频地址:https://www.bilibili.com/video/BV1BJ411L7NR?p=31
  • 笔记、源码链接: https://pan.baidu.com/s/1MDbbNKqC5mgUGg2yUiM9cg 提取码: zmpi
  • 写此文章实属佩服楠哥,顺便记录下看看自己学了多少
  • 仅此
  • 我发现我写作的文笔的真是菜哦,然后写到一半我自己都有点懵了,让我想起了我大学复制粘贴的毕业设计了,打算这个写完,有机会的话写下那个,那是一个黑马旅游网站,锻炼下WEB以及不及小学生的写作的手法
  • 2020年8月5日12:03:55写着写着感觉自己写的好乱啊,我觉得是因为我能力不够,还学人家写博客,不写了,妈的

项目展览

  • 登录页面(因为只注重业务,所以前端页面不怎么展活)

登录页面
      就这吧,不展示了功能太多了,嫌烦了


项目分析

  1. 创建一个Web项目,名字尽量和项目相关比如“TuShuGuanLi_Dog”
  2. 此项目纯属锻炼Java Web所以只写业务,导入前端静态页面即可
  3. 创建数据库,来存放图书信息
  4. 一步一验证,不给自己的弱智大脑找麻烦,运行下项目
  5. 实现读者的登录功能
  6. 实现管理员的登录功能

搭建项目

          我们按照分析一步一步来创建自己项目实现功能
1. 创建一个Web项目
在这里插入图片描述
在这里插入图片描述
2. 导入静态页面至项目的Web文件夹下
            先导入login.jsp、css、images方便后面验证由于不是maven项目,此处WEB-INF下应该创建lib目录导入jar包,后期用到什么jar包,现导什么jar包
在这里插入图片描述

3. 创建数据库
          目资源里有个xxx.sql文件导入即可
4. IDEA连接数据库
在这里插入图片描述
在这里插入图片描述
      选择刚才创建的数据库
在这里插入图片描述
项目验证
在这里插入图片描述
成功!
在这里插入图片描述

三层架构创建

这个“login”跟servlet映射起来,所以要在src下开始创建LoginServlet.java,获取前端传过来的username和password来写登录业务
在这里插入图片描述

@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
    /**
     * 处理登录的业务逻辑
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
    }
}

getParameter与getAttribute两者的区别
request.setAttribute(“xiaoxi”, “欢迎用户”+name);//向request域中放置信息 ( 键值对的形式) 名字为xiaoxi 内容为"欢迎用户"+name
request.getAttribute(“xiaoxi”);//得到request域中放置名字为xiaoxi的信息
request.getParameter(“name”);//得到request域的参数信息(得到jsp页面传过来的参数)
getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型 。
getParameter表示接收参数,参数为页面提交的参数,包括:表单提交的参数、URL重写(就是xxx?id=1中的id)传的参数等,因此这个并没有设置参数的方法(没有setParameter),而且接收参数返回的不是Object,而是String类型

拿到数据以后,去验证,去数据库“reader”表验证
在这里插入图片描述

说到数据库,第一时间想的就是用代码去连接数据库。三层架构的原因,我们要一步一步的来,“LoginServlet.java"代表controller(控制层),那么接下来就是业务层"service”,面向接口编程,所以先写接口,在写实现类,实现登录的业务,用它去调用repository层来查询数据库,在返回给控制层,然后显示到页面
在这里插入图片描述
返回结果为Boolean明显不行,应该返回为读者“reader”的实体类封装对象,所以创建entity(实体类包)下名和数据库对照的实体类“Reader"在这里插入图片描述set,get,toString,有参无参直接怼就完事,然后回到service层下的LoginService接口续写登录方法,返回类型为实体类“Reader"

public interface LoginService {
    public Reader login(String username,String password);
}

接着写实现类,在service下创建impl包,包下创建实体类“LoginServiceImpl"

public class LoginServiceImpl implements com.bin.service.LoginService {
    @Override
    public Reader login(String username, String password) {
        return null;
    }
}

然后写数据库连接层(repository层),老规矩一个接口一个实现类,基本上一个表一个类

public interface ReaderRepository {
    public Reader login(String username,String password);
}

实现类“ReaderRepositoryImpl ”

public class ReaderRepositoryImpl implements ReaderRepository {
    @Override
    public Reader login(String username, String password) {
        return null;
    }
}

至此三层架构基本完工,目录结构
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200802172901925.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTU5MjUwMg==,size_16,color_FFFFFF,t_70在这里插入图片描述
开始调用各个层
在这里插入图片描述

实现业务(注入灵魂)

登录功能

三层架构已有,开始互相调用
如:

@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
    private LoginService loginService = new LoginServiceImpl();//调用service层
    /**
     * 处理登录的业务逻辑
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        Reader reader = loginService.login(username, password);//调用service层的login方法,传入获取的参数,返回一个实体类,判断实体类是否为空
    }
}

然后service调用Repository

public class LoginServiceImpl implements com.bin.service.LoginService {
    private ReaderRepository readerRepository = new ReaderRepositoryImpl();
    @Override
    public Reader login(String username, String password) {
        return readerRepository.login(username, password);
    }
}

Repository是最底层的东西了,它去调用数据库,由于是Web项目没有框架的支持,所以整个数据库工具类在这里插入图片描述说到数据库,那就要开始在web目录下的WEB-INF创建lib目录放jar包(mysql-connector-java-5.1.18.jar和c3p0-0.9.1.2.jar),然后把jar包导入到项目中,把数据库配置文件(c3p0-config.xml)复制到src目录下

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>

	<named-config name="testc3p0">
		
		<!-- 指定连接数据源的基本属性 -->
		<property name="user">root</property>
		<property name="password">123456</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/library?useUnicode=true&amp;characterEncoding=UTF-8</property>
		
		<!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 -->
		<property name="acquireIncrement">5</property>
		<!-- 初始化数据库连接池时连接的数量 -->
		<property name="initialPoolSize">5</property>
		<!-- 数据库连接池中的最小的数据库连接数 -->
		<property name="minPoolSize">5</property>
		<!-- 数据库连接池中的最大的数据库连接数 -->
		<property name="maxPoolSize">10</property>
	
	</named-config>
		
</c3p0-config>

然后写数据库工具类JDBCTools.java

public class JDBCTools {
    private static DataSource dataSource;//DataSource是一个接口,c3p0是对接口的实现

    static {
        dataSource = new ComboPooledDataSource("testc3p0");//加载数据源
    }
    public static Connection getConnection(){
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
    public static void release(Connection connection, Statement statement, ResultSet resultSet){
        try {
            if (connection != null){
                connection.close();
            }
            if (statement != null){
                statement.close();
            }
            if (resultSet != null){
                resultSet.close();
            }
        } catch (SQLException e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        System.out.println(JDBCTools.getConnection());
    }
}

main方法为测试是否成功,如果输出类似“com.mchange.v2.c3p0.impl.NewProxyConnection@2437c6dc”即为成功,可以删除main方法了


工具类没问题,那就开始写ReaderRepositoryImpl.java类

public class ReaderRepositoryImpl implements ReaderRepository {
    @Override
    public Reader login(String username, String password) {
        Connection connection = JDBCTools.getConnection();
        String sql = "select * from reader where username = ? and password = ?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        Reader reader = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1,username);
            statement.setString(2,password);
            resultSet = statement.executeQuery();
            if (resultSet.next()){
                reader = new Reader(resultSet.getInt(1),resultSet.getString(2),
                                    resultSet.getString(3),resultSet.getString(4),
                                    resultSet.getString(5),resultSet.getString(6),
                                    resultSet.getString(7));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,resultSet);
        }
        return reader;
    }
}

然后直接回到servlet层,DeBug下看能不能取到值,这里service层方法调用Repository,所以直接回到了serlet层,调用service层
在这里插入图片描述
进到首页验证
在这里插入图片描述
成功
在这里插入图片描述

登录有两种类型,一种为读者,一种为管理员,现在验证读者

在这里插入图片描述
只需要拿到它的type看它的值为reader(读者)还是admin(管理员)即可,所以说出拿到用户名和密码以外,还要拿到type

@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
    private LoginService loginService = new LoginServiceImpl();
    /**
     * 处理登录的业务逻辑
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //获取登录的类型
        String type = req.getParameter("type");
        Reader reader = loginService.login(username, password);
        if (reader != null){
            HttpSession session = req.getSession();
            session.setAttribute("reader",reader);
            req.getRequestDispatcher("");
        }else {
            resp.sendRedirect("login.jsp");
        }
    }
}

可以用swich来控制程序流程

switch (type){
            case "reader":

                break;
            case "admin":

                break;
        }

所以交给Service做,从接口写到实现类

public interface LoginService {
    public Reader login(String username,String password,String type);
}

实现类,当type是reader(读者)就返回一个reader(读者),是admin(管理员)就返回一个admin(管理员),写到这时,发现没有管理员的实体类,所以在entity下写个管理员实体类

public class LoginServiceImpl implements com.bin.service.LoginService {
    private ReaderRepository readerRepository = new ReaderRepositoryImpl();
    @Override
    public Reader login(String username, String password,String type) {
        switch (type){
            case "reader":
                
                break;
            case "admin":

                break;
        }
        return readerRepository.login(username, password);
    }
}

Admin实体类,按照数据库字段,然后get,set有参无参toString一段狂敲,然后再次回到loginServiceImpl.java
在这里插入图片描述

铛铛铛,多态要出现了,方法返回类型为Reader(读者),所以当type返回一个Admin(管理员)肯定不行,所以返回一个Object类型,这样又能是admin又能是reader
在这里插入图片描述
更改为,然后发现==readerRepository.login(username, password);==调用的是读者的表,所以要在写一个调用管理员的表

public class LoginServiceImpl implements com.bin.service.LoginService {
    private ReaderRepository readerRepository = new ReaderRepositoryImpl();
    @Override
    public Object login(String username, String password,String type) {
        Object object = null;
        switch (type){
            case "reader":
                object = readerRepository.login(username, password);
                break;
            case "admin":
                object = new Admin();
                break;
        }
        return object;
    }
}

写调用的Admin表的代码,在repository包下写接口Admin接口及实现类

public interface AdminRepository {
    public Admin login(String username,String password);
}

AdminRepositoryImpl.java和ReaderRepositoryImpl.java大差不差,改sql语句里面的表名,和传的类型、获取的字段以及返回的类型

public class AdminRepositoryImpl implements AdminRepository {
    @Override
    public Admin login(String username, String password) {
        Connection connection = JDBCTools.getConnection();
        String sql = "select * from bookadmin where username = ? and password = ?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        Admin admin = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1,username);
            statement.setString(2,password);
            resultSet = statement.executeQuery();
            if (resultSet.next()){
                admin = new Admin(resultSet.getInt(1),resultSet.getString(2),
                                  resultSet.getString(3));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,resultSet);

        }
        return admin;
    }
}

然后继续回到LoginServiceImpl.java类,调用AdminRepositoyr

public class LoginServiceImpl implements com.bin.service.LoginService {
    private ReaderRepository readerRepository = new ReaderRepositoryImpl();
    private AdminRepository adminRepository = new AdminRepositoryImpl();
    @Override
    public Object login(String username, String password,String type) {
        Object object = null;
        switch (type){
            case "reader":
                object = readerRepository.login(username, password);
                break;
            case "admin":
                object = adminRepository.login(username,password);
                break;
        }
        return object;
    }
}

区分读者还是管理员的就此完成,然后回到上一层LoginServlet.java,续写代码如下,大概意思为,拿到Controller后只有用户名和密码type,然后把这三个值传给service,service会返回一个对象,这个对象使用多态的特性,既可以返一个reader读者又可以反一个admin管理员,这个就是根据type决定的,到LoginServiceImpl后,分别调用readerRepository.login和adminRepository.login获取到对应的对象,再把对象返回到LoginServlet,再去解析出来,把它从父类转到子类,然后存到session。

public class LoginSrevlet extends HttpServlet {
    private LoginService loginService = new LoginServiceImpl();
    /**
     * 处理登录的业务逻辑
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //获取登录的类型
        String type = req.getParameter("type");
        Object object = loginService.login(username, password,type);
        if (object != null){
            HttpSession session = req.getSession();
            switch (type){
                case "reader":
                    Reader reader = (Reader) object;
                    session.setAttribute("reader",reader);
                    break;
                case "admin":
                    Admin admin = (Admin) object;
                    session.setAttribute("admin",admin);
                    break;
            }
        }else {
            resp.sendRedirect("login.jsp");
        }
    }
}

然后DeBug验证下
在这里插入图片描述
在这里插入图片描述
成功
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

展示数据

成功以后肯定需要跳转到相关的页面,所以引入资源index.jsp文件到web目录下,这涉及到一个知识“分页”,看下index.jsp文件,发现又引入头文件,有头就又脚,所以继续引入
在这里插入图片描述
这里用到了js文件,所以需要导入jar包jstl.jar和standard.jar,打开Index.jsp报错
在这里插入图片描述
然后百度到解决方法:https://blog.csdn.net/qq_41582255/article/details/106470696
在重新打包下项目,成功
在这里插入图片描述

中间展示就是具体的数据,从数据库里读,是展示book里面的数据, 所以现在要做的就是把这些数据查出来在这里插入图片描述
查完之后展示到Index.jsp页面就可以了

当读者登录后肯定要跳转到图书页面,展示图书数据,现在缺的就是一个装满图书对象的list,所以说我们可以继续往下走了,写一个service
在这里插入图片描述
service干的就是把book表里的数据拿出来,给返回,所以就需要把它封装成一个集合对象,所以创建book表的实体类
在这里插入图片描述
黄色代表主键,蓝色是外键,跟其他表进行关联了,通过外键约束,这个外键是关联表的主键,book表是一对多的关系book和bookcase进行关联了,所以说写book实体类怎么去映射这个关系,答案就是再写个bookcase实体类,哈哈哈哈哈哈哈哈哈
发现book表里面有
实体类老规矩一顿快捷键乱造

public class BookCase {
    private Integer id;
    private String name;

    public BookCase(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public BookCase() {
    }

    @Override
    public String toString() {
        return "Bookcaseid{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

继续Book.java

public class Book {
    private Integer id;
    private String name;
    private String author;  //作者
    private String publish; //出版社
    private Integer pages;  //页数
    private Double price;   //价钱
    private BookCase bookCase;  //图书分类

    public Book(Integer id, String name, String author, String publish, Integer pages, Double price, BookCase bookCase) {
        this.id = id;
        this.name = name;
        this.author = author;
        this.publish = publish;
        this.pages = pages;
        this.price = price;
        this.bookCase = bookCase;
    }

    public Book() {
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", publish='" + publish + '\'' +
                ", pages=" + pages +
                ", price=" + price +
                ", bookCase=" + bookCase +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer 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 Integer getPages() {
        return pages;
    }

    public void setPages(Integer pages) {
        this.pages = pages;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
    public BookCase getBookCase() {
        return bookCase;
    }

    public void setBookCase(BookCase bookCase) {
        this.bookCase = bookCase;
    }
}

继续往后走,到service里面
接口

public interface Boo
	//把所有图书查询出来kService {
    public List<Book> findAll();
}

实现类写到一半发现sql语句不能写成“select * from book”
在这里插入图片描述
所以sql语句改成“select * from book,bookcase where book.bookcaseid=bookcase.id”
续写实现类

public class BookRepositoryImpl implements BookRepository {
    @Override
    public List<Book> findAll() {
        Connection connection = JDBCTools.getConnection();
        String sql = "select * from book,bookcase where book.bookcaseid=bookcase.id";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Book> list = new ArrayList<>();
        try {
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                list.add(new Book(resultSet.getInt(1),resultSet.getString(2),
                        resultSet.getString(3), resultSet.getString(4),resultSet.getInt(5),
                        resultSet.getDouble(6),new BookCase(resultSet.getInt(9),resultSet.getString(10))));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCTools.release(connection,statement,resultSet);
        }
        return list;
    }
}

回到上一层,让service调用它,因为业务简单所以直接调用,

public class BookServiceImpl implements BookService {
    
    private BookRepository bookRepository = new BookRepositoryImpl();
    
    @Override
    public List<Book> findAll() {
        return bookRepository.findAll();
    }
}

再上一层servlet,写数据让它返回到前端,当然servlet要调上面写的Book的Service,然后传到
请求作用域里,是这么说的吧,我也记不清楚了,回头补一下

@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
    private LoginService loginService = new LoginServiceImpl();
    private BookService bookService = new BookServiceImpl();
    /**
     * 处理登录的业务逻辑
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //获取登录的类型
        String type = req.getParameter("type");
        Object object = loginService.login(username, password,type);

        if (object != null){
            HttpSession session = req.getSession();
            switch (type){
                case "reader":
                    Reader reader = (Reader) object;
                    session.setAttribute("reader",reader);
                    List<Book> list = bookService.findAll();
                    req.setAttribute("list",list);
                    //跳转到读者页面
                    req.getRequestDispatcher("index.jsp").forward(req,resp);
                    break;
                case "admin":
                    Admin admin = (Admin) object;
                    session.setAttribute("admin",admin);
                    //跳转到管理员页面
                    break;
            }
        }else {
            resp.sendRedirect("login.jsp");
        }
    }
}

紧接着去index.jsp解析list,展示到页面
在这里插入图片描述
运行项目,成功,书架那的应该是我BookCase.java里面toString的问题
在这里插入图片描述
所以我们上面展示书架的代码应该改成${book.bookCase.name},不让他调用toString方法
在这里插入图片描述

当然问题还是很明显,数据超出页面了,所以分页来了

分页

分页怎么处理呢,还是要看数据库,语句查询的时候给她来个甲鱼的臀部-规定下
比如一次取10条,第一次取出前10条
在这里插入图片描述
改SQL语句

select * from book,bookcase where book.bookcaseid=bookcase.id limit 0,10

那取后面的就是

select * from book,bookcase where book.bookcaseid=bookcase.id limit 10,10

一直改数值不是个方法,所以发现个规律

# 每页3条
#1 0,3
#2 3,3
#3 6,3
#....
#n (n-1)*3,3

这是数据库,然后回到index.jsp页面
在这里插入图片描述
这是第一页,当点击第二页的时候应该返回2给我,然后通过2的参数对应第2页的记录,所以我们就要page和n (n-1)*3,3 关联起来,实际上这个n就是page,这就是我们公式,现在来分页实一下
在index.jsp实现下一页
我们单独写一个servlet拿这个数据
在这里插入图片描述
然后发现上面代码要改一下,BookRepositoryImpl.java里面的sql语句一次把数据拿完了,所以要改一下,一次拿10条
sql语句改为

String sql = "select * from book,bookcase where book.bookcaseid=bookcase.id limit ?,?";

BookRepository.java类里面的方法要带过来两个int类型的参数,然后改接口

 public List<Book> findAll(int index,int limit) {
 }

回到刚才单独写的servlet类(BookServlet.java),要查询图书的话,把页码信息给我,所以首先拿到一个page,在转成一个int类型

@WebServlet("/book")
public class BookServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pageStr = req.getParameter("page");
        int page = Integer.parseInt(pageStr);
    }
}

在Bookservice里面把页数给传进去,就是说当前要查询第几页

public interface BookService {
    public List<Book> findAll(int page);
}

传到这以后,需要把page转换成两个参数
在这里插入图片描述
比如把1转换成0,3
2转成 3,3以此类推,要做这么一个处理,因为最后落实到SQL语句是两个参数,但是传的是一个参数,因为要用公式转
在这里插入图片描述
BookService.java这样写,page就是n,3就是LIMIT,然后把计算结果和LIMIT传到下一层

public class BookServiceImpl implements BookService {
    private final int LIMIT = 6;
    private BookRepository bookRepository = new BookRepositoryImpl();

    @Override
    public List<Book> findAll(int page) {
        int index = (page-1)*LIMIT;
        return bookRepository.findAll(index,LIMIT);
    }
}

由于是从下往上写的,所以咱们可以回到BookServlet了,打个断点,Debug登录下,看能取到前6条不能
在这里插入图片描述
发现了前面的遗留的坑,随便传个1吧
在这里插入图片描述
是前6个,成功了,因为传的是1所以把前6条传出来了,接下来点击下一页让数据更新
在这里插入图片描述

显示页数

在这里插入图片描述
所以回到index.jsp
在这里插入图片描述
服务器还要把这个三个参数给带过去,所以Servlet继续获取,当获取到总页数的时候,问题出现了
这个需要 数据总数/每页数据=总页数现在就要写个方法了,调用它了,这就是业务层的东西了,去写接口,实现类,实现类写具体内容发现,需要往下一层在写一个方法(Repository)获取总记录条数

public class BookRepositoryImpl implements BookRepository {
    @Override
    public List<Book> findAll(int index,int limit) {
        Connection connection = JDBCTools.getConnection();
        String sql = "select * from book,bookcase where book.bookcaseid=bookcase.id limit ?,?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Book> list = new ArrayList<>();
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1,index);
            statement.setInt(2,limit);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                list.add(new Book(resultSet.getInt(1),resultSet.getString(2),
                        resultSet.getString(3), resultSet.getString(4),resultSet.getInt(5),
                        resultSet.getDouble(6),new BookCase(resultSet.getInt(9),resultSet.getString(10))));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCTools.release(connection,statement,resultSet);
        }
        return list;
    }

    @Override
    public int count() {
        Connection connection = JDBCTools.getConnection();
        String sql = "select count(*) from book,bookcase where book.bookcaseid=bookcase.id";
        ResultSet resultSet = null;
        PreparedStatement statement = null;
        int count = 0;
        try {
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                count=resultSet.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,resultSet);
        }
        return count;
    }
}

我想着这个换成count++,竟然还不行,那就这样吧,这个方法简单,就不多介绍了,业务层完毕,现在再去上一层,Servlet

while (resultSet.next()){
                count=resultSet.getInt(1);
            }

现在往上一层,回到service

public class BookServiceImpl implements BookService {
    
    private final int LIMIT = 6;
    private BookRepository bookRepository = new BookRepositoryImpl();

    @Override
    public List<Book> findAll(int page) {
        int index = (page-1)*LIMIT;
        return bookRepository.findAll(index,LIMIT);
    }

    @Override
    public int getPages() {
        int count = bookRepository.count();
        int page = 0;
        if (count%LIMIT ==0){
            page = count/LIMIT;
        }else {
            page = count/LIMIT+1;
        }
        return page;
    }
}

这个无需多言了,我不知道该怎么说了,大脑有点混乱了,第一次做项目,我应该要重新捋一遍了

@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
    private LoginService loginService = new LoginServiceImpl();
    private BookService bookService = new BookServiceImpl();
    /**
     * 处理登录的业务逻辑
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //获取登录的类型
        String type = req.getParameter("type");
        Object object = loginService.login(username, password,type);

        if (object != null){
            HttpSession session = req.getSession();
            switch (type){
                case "reader":
                    Reader reader = (Reader) object;
                    session.setAttribute("reader",reader);
                    List<Book> list = bookService.findAll(2);
                    req.setAttribute("list",list);
                    req.setAttribute("dataPrePage",6);//每页展示记录数
                    req.setAttribute("currentPage",1);//当前页数
                    req.setAttribute("pages",bookService.getPages());//总页数,不能写死,需要动态获取
                    //跳转到读者页面
                    req.getRequestDispatcher("index.jsp").forward(req,resp);
                    break;
                case "admin":
                    Admin admin = (Admin) object;
                    session.setAttribute("admin",admin);
                    //跳转到管理员页面
                    break;
            }
        }else {
            resp.sendRedirect("login.jsp");
        }
    }
}

运行项目成功
在这里插入图片描述

开始实现下一页功能,点击下一页,当前页数应该+1,把2传过去,把第2页的信息都拿出来,在返回出来,通过js来实现

下一页及首页尾页

给下一页(nex)写个单击事件,然后在拿到当前页数(currentPage)的内容xxx.html()(就是1)转成int类型再+1,就变成了2

<script type="text/javascript">
		$(function () {
			$("#next").click(function () {
				var page = parseInt($("#currentPage").html())+1;
				location.href = "/book?page="+page;//通过js访问后台的一个方法,访问的是BookServletImpl的doget方法,
													// 传的是当前拿到的2
			})
		})
	</script>

然后回到BookServletImpl.java

@WebServlet("/book")
public class BookServlet extends HttpServlet {

    private BookService bookService = new BookServiceImpl();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pageStr = req.getParameter("page");//拿到了2,3,4...
        int page = Integer.parseInt(pageStr);
        List<Book> list = bookService.findAll(page);
        req.setAttribute("list",list);
        req.setAttribute("dataPrePage",6);//每页展示记录数
        req.setAttribute("currentPage",page);//当前页数
        req.setAttribute("pages",bookService.getPages());
        req.getRequestDispatcher("index.jsp").forward(req,resp);
    }
}

紧接着发现了新的问题,需要设置一个上线,前端就能设置,当前页面肯定不能大于总页面
在这里插入图片描述
成了

<script type="text/javascript">
		$(function () {
			$("#next").click(function () {
				var pages = parseInt($("#pages").html());
				var page = parseInt($("#currentPage").html());
				if (page == pages){//说明是最后一页,直接跳出方法
					return;
				}
				page++;
				location.href = "/book?page="+page;//通过js访问后台的一个方法,访问的是BookServletImpl的doget方法,
				// 传的是当前拿到的2
			})
		})

这样一说上一页岂不是减减就行了吗

$("#previous").click(function () {
				var page = parseInt($("#currentPage").html());
				if (page == 1){//说明是第一页,直接跳出方法
					return;
				}
				page--;
				location.href = "/book?page="+page;
			})

那首页和最后一也起步更简单了

//首页
			$("#first").click(function () {
				location.href = "/book?page=1";//第一页不需要判断,只需要等于1就行了
			})
			//最后一页
			$("#last").click(function () {
				var pages = parseInt($("#pages").html());//总页数
				location.href = "/book?page="+pages;
			})

优化代码

发现这俩个代码有重复的,这就需要优化了,LoginServlet代码里一个逻辑块写了两个业务信息
1.验证用户和密码
2.加载图书信息
这就是高耦合,现在开始解耦
在这里插入图片描述

在这里插入图片描述

LoginServlet修改为,通过代码resp.sendRedirect("/book?page=1"); 直接调到BookServlet还带了一个初始页面

@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
    private LoginService loginService = new LoginServiceImpl();
    private BookService bookService = new BookServiceImpl();
    /**
     * 处理登录的业务逻辑
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //获取登录的类型
        String type = req.getParameter("type");
        Object object = loginService.login(username, password,type);

        if (object != null){
            HttpSession session = req.getSession();
            switch (type){
                case "reader":
                    Reader reader = (Reader) object;
                    session.setAttribute("reader",reader);
                    resp.sendRedirect("/book?page=1");
                    break;
                case "admin":
                    Admin admin = (Admin) object;
                    session.setAttribute("admin",admin);
                    //跳转到管理员页面
                    break;
            }
        }else {
            resp.sendRedirect("login.jsp");
        }
    }
}

借阅

下面开始实现借阅功能,比如借一本书,管理员如果同意,就能把书拿走,反之不能,我们来实现借阅功能,首先要把借阅请求发出去,操作入口就在view这一层就是jsp,点击借阅按钮表示用户做了这么一个操作,然后把这个操作转换成程序,落实到数据库里,我们需要这样一张表,这张表关联了三个表,图书表,读者表,管理员表,因为借书这个事,需要三个参与对象,哪本书被哪个人借走,又被哪个管理员审核
state 0表示未审核,1表是通过,2表示不通过,还回来3
借阅就是向数据库添加一条新记录
在这里插入图片描述
来到入口index.jsp,这个进到BookServlet,所以图书相关的都放这
在这里插入图片描述
这就要逻辑分层了,因为只有一个doGet方法,这个方法里面处理的是加载图书信息的,现在要添加一个借阅审核的逻辑,一个方法怎么用两个逻辑,让他传过来一个method,我就知道它要干啥了,这就能分开了

在这里插入图片描述
根据传来的method来控制程序流程

@WebServlet("/book")
public class BookServlet extends HttpServlet {

    private BookService bookService = new BookServiceImpl();

    /**
     * 加载图书数据
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");//区分逻辑,是否是借阅
        if (method == null){
            method = "findAll";//默认就是图书查询
        }
        //流程控制
        switch (method){
            case "findAll":
                String pageStr = req.getParameter("page");
                int page = Integer.parseInt(pageStr);
                List<Book> list = bookService.findAll(page);
                req.setAttribute("list",list);
                req.setAttribute("dataPrePage",6);//每页展示记录数
                req.setAttribute("currentPage",page);//当前页数
                req.setAttribute("pages",bookService.getPages());
                req.getRequestDispatcher("index.jsp").forward(req,resp);
                break;
            case "addBorrow":
                
                break;
        }
    }
}

接下来考虑传什么参数,就看数据库需要哪些字段,id是自增的,不需要,bookid需要判断是哪本书readerid不需要传,因为reader在session里面存的,直接拿session就行 ,登录的时候回已经把reader存进去了
在这里插入图片描述
总结下来只需要传bookid就好了
在这里插入图片描述
然后写servlet

@WebServlet("/book")
public class BookServlet extends HttpServlet {

    private BookService bookService = new BookServiceImpl();

    /**
     * 加载图书数据
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");//区分逻辑,是否是借阅
        if (method == null){
            method = "findAll";//默认就是图书查询
        }
        //流程控制
        switch (method){
            case "findAll":
                String pageStr = req.getParameter("page");
                int page = Integer.parseInt(pageStr);
                List<Book> list = bookService.findAll(page);
                req.setAttribute("list",list);
                req.setAttribute("dataPrePage",6);//每页展示记录数
                req.setAttribute("currentPage",page);//当前页数
                req.setAttribute("pages",bookService.getPages());
                req.getRequestDispatcher("index.jsp").forward(req,resp);
                break;
            case "addBorrow":
                //拿到jsp页面传来的bookid,再转成int
                String bookidStr = req.getParameter("bookid");
                int bookid = Integer.parseInt(bookidStr);
                //拿到LoginServlet登录成功的reader session
                HttpSession session = req.getSession();
                Reader reader = (Reader) session.getAttribute("reader");
                break;
        }
    }
}

接下来就是业务层的事了,service里写一个方法,传递两个参数,service层拿不到的东西,需要Controller传过来

public interface BookService {
    public List<Book> findAll(int page);
    public int getPages();
    public void addBorrow(Integer bookid,Integer readerid);
}

这层写完,继续下一层

public class BookServiceImpl implements BookService {

    private final int LIMIT = 6;
    private BookRepository bookRepository = new BookRepositoryImpl();

    @Override
    public List<Book> findAll(int page) {
        int index = (page-1)*LIMIT;
        return bookRepository.findAll(index,LIMIT);
    }

    @Override
    public int getPages() {
        int count = bookRepository.count();
        int page = 0;
        if (count%LIMIT ==0){
            page = count/LIMIT;
        }else {
            page = count/LIMIT+1;
        }
        return page;
    }

    @Override
    public void addBorrow(Integer bookid, Integer readerid) {
        //借书时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String borrowTime = simpleDateFormat.format(date);
        //还书时间,借书时间+14天
        Calendar calendar = Calendar.getInstance();
        int dates = calendar.get(Calendar.DAY_OF_YEAR) + 14;
        calendar.set(Calendar.DAY_OF_YEAR, dates);
        Date date2 = calendar.getTime();
        String returnTime = simpleDateFormat.format(date2);
    }
}

下一层,一个表对应一个Repository,创建一个borroRepository接口实现类

public class BorroRepositoryImpl implements BorrowRepository {
    @Override
    public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
        
    }
}

实现类

public class BorroRepositoryImpl implements BorrowRepository {
    @Override
    public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
        Connection connection = JDBCTools.getConnection();
        String sql = "insert into borrow(bookid,readerid,borrowtime,returntime,state) values(?,?,?,?,0)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1,bookid);
            statement.setInt(2,readerid);
            statement.setString(3,borrowtime);
            statement.setString(4,returntime);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,null);
        }
    }
}

上一层(service)让它调用Repsotory

public class BookServiceImpl implements BookService {

    private final int LIMIT = 6;
    private BookRepository bookRepository = new BookRepositoryImpl();
    private BorrowRepository borrowRepository = new BorroRepositoryImpl();

    @Override
    public List<Book> findAll(int page) {
        int index = (page-1)*LIMIT;
        return bookRepository.findAll(index,LIMIT);
    }

    @Override
    public int getPages() {
        int count = bookRepository.count();
        int page = 0;
        if (count%LIMIT ==0){
            page = count/LIMIT;
        }else {
            page = count/LIMIT+1;
        }
        return page;
    }

    @Override
    public void addBorrow(Integer bookid, Integer readerid) {
        //借书时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String borrowTime = simpleDateFormat.format(date);
        //还书时间,借书时间+14天
        Calendar calendar = Calendar.getInstance();
        int dates = calendar.get(Calendar.DAY_OF_YEAR) + 14;
        calendar.set(Calendar.DAY_OF_YEAR, dates);
        Date date2 = calendar.getTime();
        String returnTime = simpleDateFormat.format(date2);
        borrowRepository.insert(bookid,readerid,borrowTime,returnTime,null,0);
    }
}

再往上一层(Bookservlet),调用

@WebServlet("/book")
public class BookServlet extends HttpServlet {

    private BookService bookService = new BookServiceImpl();

    /**
     * 加载图书数据
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");//区分逻辑,是否是借阅
        if (method == null){
            method = "findAll";//默认就是图书查询
        }
        //流程控制
        switch (method){
            case "findAll":
                String pageStr = req.getParameter("page");
                int page = Integer.parseInt(pageStr);
                List<Book> list = bookService.findAll(page);
                req.setAttribute("list",list);
                req.setAttribute("dataPrePage",6);//每页展示记录数
                req.setAttribute("currentPage",page);//当前页数
                req.setAttribute("pages",bookService.getPages());
                req.getRequestDispatcher("index.jsp").forward(req,resp);
                break;
            case "addBorrow":
                //拿到jsp页面传来的bookid,再转成int
                String bookidStr = req.getParameter("bookid");
                int bookid = Integer.parseInt(bookidStr);
                //拿到LoginServlet登录成功的reader session
                HttpSession session = req.getSession();
                Reader reader = (Reader) session.getAttribute("reader");
                bookService.addBorrow(bookid,reader.getId());
                break;
        }
    }
}

大致就是从index.jsp那个借阅一点把method和id传过去
在这里插入图片描述
进到servlet里面,通过method来判断执行借阅的代码操作,把id拿过来,在把reader拿过来,把id和reader的id在传给service
在这里插入图片描述
在service中,把系统时间拿出来,在把还书时间整出来,在把这些参数传给repository
在这里插入图片描述
repository直接往里面就行了,分工相当明确
servlet只需要拿到参数就行了
service只需要进行业务处理,业务处理好交给repository
repository只负责存
好了,运行项目点击借阅,然后一片空白
发现数据库多了条记录,成功了
在这里插入图片描述
然后给响应下,不能一片空白,就是吧这个用户的所有借书信息给响应出来,就是展示数据表(borrow)里面一个读者(readerid)的全部借书信息,从下往上,所有要在BorrowkRepository写一个方法,写到返回类型的时候,发现要有一个实体类,对应borrow表,表关系复杂,所有直接弄其他实体类,然后一套组合拳set,get…等一系列操作

public class Borrow {
    private Integer id;
    private Book book;
    private Reader reader;
    private String borromTime;
    private String returnTime;
}

然后根据自己要返回的的子段,补充下有参,这里我们需要这些信息

select br.id,b.name,b.author,b.publish,br.borrowtime,br.returntime,r.name,r.tel,r.cardid  from borrow br,book b ,reader r where readerid = 3 and b.id = br.bookid and r.id=br.readerid

实体类里在写一些有参
在这里插入图片描述

回到Repository方法就有返回对象了,这里需要个id,根据id才能查出信息,再次回到实现类

public interface BorrowRepository {
    //插入一条借书信息
    public void insert(Integer bookid,Integer readerid,String borrowtime,String returntime,Integer adminid,Integer state);

    public List<Borrow> findAllByReaderId(Integer id);
}

实现类,有点安耐不住了,烦了

public class BorroRepositoryImpl implements BorrowRepository {
    @Override
    public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
        Connection connection = JDBCTools.getConnection();
        String sql = "insert into borrow(bookid,readerid,borrowtime,returntime,state) values(?,?,?,?,0)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1,bookid);
            statement.setInt(2,readerid);
            statement.setString(3,borrowtime);
            statement.setString(4,returntime);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,null);
        }
    }

    @Override
    public List<Borrow> findAllByReaderId(Integer id) {
        Connection connection = JDBCTools.getConnection();
        String sql = "select br.id,b.name,b.author,b.publish,br.borrowtime,br.returntime,r.name,r.tel,r.cardid  from borrow br,book b ,reader r where readerid = ? and b.id = br.bookid and r.id=br.readerid";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Borrow> list = new ArrayList<>();
        try {
            statement=connection.prepareStatement(sql);
            statement.setInt(1,id);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                list.add(new Borrow(resultSet.getInt(1),
                        new Book(resultSet.getString(2),resultSet.getString(3),resultSet.getString(4)),
                        new Reader(resultSet.getString(7),resultSet.getString(8),resultSet.getString(9)),
                        resultSet.getString(5),
                        resultSet.getString(6)));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,resultSet);
        }
        return list;
    }
}

再往上走

public interface BookService {
    public List<Book> findAll(int page);
    public int getPages();
    public void addBorrow(Integer bookid,Integer readerid);
    //返回他所有借书记录
    public List<Borrow> findAllBorrowByReaderId(Integer id);
}

service实现类

public class BookServiceImpl implements BookService {

    private final int LIMIT = 6;
    private BookRepository bookRepository = new BookRepositoryImpl();
    private BorrowRepository borrowRepository = new BorroRepositoryImpl();

    @Override
    public List<Book> findAll(int page) {
        int index = (page-1)*LIMIT;
        return bookRepository.findAll(index,LIMIT);
    }

    @Override
    public int getPages() {
        int count = bookRepository.count();
        int page = 0;
        if (count%LIMIT ==0){
            page = count/LIMIT;
        }else {
            page = count/LIMIT+1;
        }
        return page;
    }

    @Override
    public void addBorrow(Integer bookid, Integer readerid) {
        //借书时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String borrowTime = simpleDateFormat.format(date);
        //还书时间,借书时间+14天
        Calendar calendar = Calendar.getInstance();
        int dates = calendar.get(Calendar.DAY_OF_YEAR) + 14;
        calendar.set(Calendar.DAY_OF_YEAR, dates);
        Date date2 = calendar.getTime();
        String returnTime = simpleDateFormat.format(date2);
        borrowRepository.insert(bookid,readerid,borrowTime,returnTime,null,0);
    }

    @Override
    public List<Borrow> findAllBorrowByReaderId(Integer id) {
        return borrowRepository.findAllByReaderId(id);
    }
}

在往上走回到servlet,打个点断验证下
在这里插入图片描述

点击借阅
在这里插入图片描述
成功
在这里插入图片描述
现在,在Repository的sql语句追加一个审核状态state

public class BorroRepositoryImpl implements BorrowRepository {
    @Override
    public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
        Connection connection = JDBCTools.getConnection();
        String sql = "insert into borrow(bookid,readerid,borrowtime,returntime,state) values(?,?,?,?,0)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1,bookid);
            statement.setInt(2,readerid);
            statement.setString(3,borrowtime);
            statement.setString(4,returntime);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,null);
        }
    }

    @Override
    public List<Borrow> findAllByReaderId(Integer id) {
        Connection connection = JDBCTools.getConnection();
        String sql = "select br.id,b.name,b.author,b.publish,br.borrowtime,br.returntime,r.name,r.tel,r.cardid,br.state  from borrow br,book b ,reader  where readerid = ? and b.id = br.bookid and r.id=br.readerid";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Borrow> list = new ArrayList<>();
        try {
            statement=connection.prepareStatement(sql);
            statement.setInt(1,id);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                list.add(new Borrow(resultSet.getInt(1),
                        new Book(resultSet.getString(2),resultSet.getString(3),resultSet.getString(4)),
                        new Reader(resultSet.getString(7),resultSet.getString(8),resultSet.getString(9)),
                        resultSet.getString(5),
                        resultSet.getString(6),resultSet.getInt(10)));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,resultSet);
        }
        return list;
    }
}

Borrow实体类多个变量

public class Borrow {
    private Integer id;
    private Book book;
    private Reader reader;
    private String borrowTime;
    private String returnTime;
    private Integer state;

    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 Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
    }

    public Integer getId() {
        return id;
    }

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

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }

    public Reader getReader() {
        return reader;
    }

    public void setReader(Reader reader) {
        this.reader = reader;
    }

    public Borrow(Integer id, Book book, Reader reader, String borrowTime, String returnTime, Integer state) {
        this.id = id;
        this.book = book;
        this.reader = reader;
        this.borrowTime = borrowTime;
        this.returnTime = returnTime;
        this.state = state;
    }
}

再回到borrow.jsp

	<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'borrow.jsp' starting page</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
	<link href="css/index.css" type="text/css" rel="stylesheet">
	  <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
	  <script type="text/javascript">
		  $(function(){
			  $("#next").click(function(){
				  var pages = parseInt($("#pages").html());
				  var page = parseInt($("#currentPage").html());
				  if(page == pages){
					  return;
				  }
				  page++;
				  location.href = "/book?method=findAllBorrow&page="+page;
			  })

			  $("#previous").click(function () {
				  var page = parseInt($("#currentPage").html());
				  if(page == 1){
					  return;
				  }
				  page--;
				  location.href = "/book?method=findAllBorrow&page="+page;
			  })

			  $("#first").click(function () {
				  location.href = "/book?method=findAllBorrow&page=1";
			  })

			  $("#last").click(function(){
				  var pages = parseInt($("#pages").html());
				  location.href = "/book?method=findAllBorrow&page="+pages;
			  })
		  })
	  </script>
  </head>
  
  <body>
    <%@ include file="top.jsp" %>
  	
  	
  	<div id="main">
		<div class="navigation">
				当前位置:&nbsp;&nbsp;<a href="/book?page=1">首页</a>
				<div id="readerBlock">欢迎回来&nbsp;:${reader.name }&nbsp;<a href="/logout">注销</a></div>
		</div>
		<div class="img_block">
			<img src="images/main_booksort.gif" class="img" />
		</div>
		
		<table class="table" cellspacing="0">
			<tr>
				<td>编号</td>
				<td>图书名称</td>
				<td>图书作者</td>
				<td>出版社</td>
				<td>读者姓名</td>
				<td>联系电话</td>
				<td>证件编号</td>
				<td>借书时间</td>
				<td>还书时间</td>
				<td>审核状态</td>
			</tr>
			<c:forEach items="${list}" var="borrow">
				<tr>
					<td>${borrow.id}</td>
					<td>${borrow.book.name}</td>
					<td>${borrow.book.author}</td>
					<td>${borrow.book.publish}</td>
					<td>${borrow.reader.name}</td>
					<td>${borrow.reader.tel}</td>
					<td>${borrow.reader.carid}</td>
					<td>${borrow.borrowTime}</td>
					<td>${borrow.returnTime}</td>
					<td>${borrow.state}</td>
				</tr>
			</c:forEach>
			
		</table>
		<hr class="hr"/>
		<div id="pageControl">
			<div class="pageControl_item">每页<font id="dataPrePage">${dataPrePage }</font>条数据</div>
			<div class="pageControl_item" id="last">最后一页</div>
			<div class="pageControl_item" id="next">下一页</div>
			<div class="pageControl_item"><font id="currentPage">${currentPage }</font>/<font id="pages">${pages }</font></div>
			<div class="pageControl_item" id="previous">上一页</div>
			<div class="pageControl_item" id="first">首页</div>
		</div>
	</div>

  	
   <%@ include file="footer.jsp" %>
  </body>
</html>

运行项目,成功,现在开始分页,还有审核状态不能给显示数字,展示的时候把数字给翻译下
在这里插入图片描述
这样就翻译过来了
在这里插入图片描述
再次运行项目,成功
在这里插入图片描述
先写个过滤器,要不要页面刷新后点击借阅返回空指针异常

@WebServlet("/book")
public class ReaderFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //判断是否有读者登录
        HttpSession session =((HttpServletRequest)servletRequest).getSession();
        Reader reader = (Reader) session.getAttribute("reader");
        if (reader == null){
            ((HttpServletResponse)servletResponse).sendRedirect("login.jsp");
        }else {
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
}

现在开始分页,根据上面分页的经验

借阅分页

接口

public interface BorrowRepository {
    //插入一条借书信息
    public void insert(Integer bookid,Integer readerid,String borrowtime,String returntime,Integer adminid,Integer state);

    public List<Borrow> findAllByReaderId(Integer id,Integer index,Integer limit);
}

实现类,只需要更改sql语句,然后替换sql语句的值,具体的交给service业务层

public class BorroRepositoryImpl implements BorrowRepository {
    @Override
    public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
        Connection connection = JDBCTools.getConnection();
        String sql = "insert into borrow(bookid,readerid,borrowtime,returntime,state) values(?,?,?,?,0)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setInt(1,bookid);
            statement.setInt(2,readerid);
            statement.setString(3,borrowtime);
            statement.setString(4,returntime);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,null);
        }
    }

    @Override
    public List<Borrow> findAllByReaderId(Integer id,Integer index,Integer limit) {
        Connection connection = JDBCTools.getConnection();
        String sql = "select br.id,b.name,b.author,b.publish,br.borrowtime,br.returntime,r.name,r.tel,r.cardid,br.state from borrow br,book b ,reader r where readerid = ? and b.id = br.bookid and r.id = br.readerid limit ?,?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Borrow> list = new ArrayList<>();
        try {
            statement=connection.prepareStatement(sql);
            statement.setInt(1,id);
            statement.setInt(2,index);
            statement.setInt(3,limit);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                list.add(new Borrow(resultSet.getInt(1),
                        new Book(resultSet.getString(2),resultSet.getString(3),resultSet.getString(4)),
                        new Reader(resultSet.getString(7),resultSet.getString(8),resultSet.getString(9)),
                        resultSet.getString(5),
                        resultSet.getString(6),resultSet.getInt(10)));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCTools.release(connection,statement,resultSet);
        }
        return list;
    }
}

回到servlet,获取页数,紧着发现这个addBorrow方法执行了两个业务
在这里插入图片描述

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Alt

带尺寸的图片: Alt

居中的图片: Alt

居中并且带尺寸的图片: Alt

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目Value
电脑$1600
手机$12
导管$1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列第二列第三列
第一列文本居中第二列文本居右第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPEASCIIHTML
Single backticks'Isn't this fun?'‘Isn’t this fun?’
Quotes"Isn't this fun?"“Isn’t this fun?”
Dashes-- is en-dash, --- is em-dash– is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。1

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通过欧拉积分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

你可以找到更多关于的信息 LaTeX 数学表达式[here][1].

新的甘特图功能,丰富你的文章

Mon 06 Mon 13 Mon 20 已完成 进行中 计划一 计划二 现有任务 Adding GANTT diagram functionality to mermaid
  • 关于 甘特图 语法,参考 [这儿][2],

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 [这儿][3],

FLowchart流程图

我们依旧会支持flowchart的流程图:

Created with Raphaël 2.2.0 开始 我的操作 确认? 结束 yes no
  • 关于 Flowchart流程图 语法,参考 [这儿][4].

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. 注脚的解释 ↩︎

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值