目录
我们以图书管理系统为例子,利用DBUtils进行完整的连接数据库开发。
一、准备工作
假设现在有个图书管理系统,可以在上面任意添加图书,包括图书的名字,价格等信息,也可以显示、修改与删除图书的信息,并将这些都在网页上显示出来。
主要涉及到四个功能:
- 书籍的显示功能
- 书籍的添加功能
- 书籍的修改功能
- 书籍的删除功能
首先我们把做好的界面文件(提取码:u11q)导入进来,放至WEB文件夹下,
然后在WEB-INF目录下的lib路径放置我们需要的jar包(提取码:fu23),将之前写过的C3P0Util.java文件放在Util包下,同时写好配置文件c3p0-config.xml(可参考博客地址),
我们还要建立好相关的数据库与数据表,并且修改好配置文件c3p0-config.xml。
二、书籍显示功能
现在我们需要完成点击商品管理中的商品查看可以看到数据库中的书籍的信息,示意图如下:
首先我们实现数据访问层的代码,从数据库拿取所有的书籍(在这之前要实现实体类Book,并且根据数据表中的列名新建Book的属性,完成get和set方法)
package Dao;
import Util.Book;
import Util.C3P0Util;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;
public class BookDaoImpl {
/**
* 查找所有的图书
* @return
* @throws SQLException
*/
public List<Book> findAllBooks() throws SQLException {
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
List<Book> bookList = queryRunner.query("select * from book", new BeanListHandler<Book>(Book.class));
return bookList;
}
}
然后是业务逻辑层,完成主要的业务逻辑,因为这里仅仅是获取数据显示出来,所有直接调用findAllBooks方法即可,
package Service;
import Dao.BookDaoImpl;
import Util.Book;
import java.sql.SQLException;
import java.util.List;
public class BookServiceImpl {
BookDaoImpl bookDao=new BookDaoImpl();
public List<Book> findAllBooks(){
try {
return bookDao.findAllBooks();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
然后是通过servlet来获取数据并且通过request对象将数据分发转向到显示界面list.jsp,
package Web;
import Service.BookServiceImpl;
import Util.Book;
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.List;
@WebServlet(name = "BookListServlet")
public class BookListServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//调用业务逻辑
BookServiceImpl bookService=new BookServiceImpl();
List<Book> bookList = bookService.findAllBooks();//获取所有书籍
//跳转页面
if (bookList!=null){
request.setAttribute("books",bookList);//把所有书籍放入到request对象中
request.getRequestDispatcher("/admin/products/list.jsp").forward(request,response);//跳转到list.jsp中
}
}
}
配置好web.xml的servlet路径:
<welcome-file-list><welcome-file>admin/login/home.jsp</welcome-file></welcome-file-list>
<servlet>
<servlet-name>bookListServlet</servlet-name>
<servlet-class>Web.BookListServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>addBookServlet</servlet-name>
<servlet-class>Web.AddBookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>bookListServlet</servlet-name>
<url-pattern>/servlet/bookListServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>addBookServlet</servlet-name>
<url-pattern>/servlet/addBookServlet</url-pattern>
</servlet-mapping>
最后修改admin/login/left.jsp中点击商品查看时跳转的路径名称即可,这里的路径要和web.xml中的servlet配置路径相同,
然后就可以运行得到本节开始的效果图了。
三、书籍添加功能
书籍列表里面可以点击添加,点击添加之后会弹出添加商品的具体信息,
这里我们先实现数据访问层的添加书籍方法,在数据库根据书本信息中插入数据,
/**
* 添加书籍信息
* @param book
* @throws SQLException
*/
public void addBook(Book book) throws SQLException {
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
queryRunner.update("insert into book values(?,?,?,?,?,?)",book.getId(),book.getName(),book.getPrice(),book.getPnum(),book.getCategory(),book.getDescription());
}
然后是业务逻辑层,直接调用方法:
//添加图书
public void addBook(Book book){
try {
bookDao.addBook(book);
} catch (SQLException e) {
e.printStackTrace();
}
}
然后我们通过servlet将添加页面中的信息封装到Book对象中,并且调用业务层方法将书本添加到数据库中,然后跳转显示的servlet,
package Web;
import Service.BookServiceImpl;
import Util.Book;
import org.apache.commons.beanutils.BeanUtils;
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.lang.reflect.InvocationTargetException;
import java.util.UUID;
@WebServlet(name = "AddBookServlet")
public class AddBookServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//设置编码格式
//获取数据
Book book=new Book();
try {
BeanUtils.populate(book,request.getParameterMap());//从request对象中获取到书籍信息,并封装到book对象中
book.setId(UUID.randomUUID().toString());//给书籍设置随机ID
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//调用业务逻辑
BookServiceImpl bookService=new BookServiceImpl();
bookService.addBook(book);
request.getRequestDispatcher("/servlet/bookListServlet").forward(request,response);//转发到显示的servlet
}
}
然后在web.xml中配置一下添加书籍servlet的映射地址,
<servlet>
<servlet-name>addBookServlet</servlet-name>
<servlet-class>Web.AddBookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>addBookServlet</servlet-name>
<url-pattern>/servlet/addBookServlet</url-pattern>
</servlet-mapping>
输入添加书籍的信息就可以看到显示界面已经有添加的信息了,数据库中也有相关的信息
四、书籍修改功能
当我们在书籍的列表显示界面点击编辑时,我们希望能够获取到书籍的信息,然后根据信息做出相应的修改,比如在三国演义一栏点击修改,就能弹出相应的信息,
这样我们就可以方便的进行修改,首先我们要解决的是根据点击的书本ID来回显数据,然后修改完成之后对书本进行数据库的更新,最后跳转到书本的显示界面。
4.1数据的回显
首先我们解决一下数据的回显问题,我们如果要对某个书籍进行修改,点击对应的编辑按钮,那么就可以根据点击书籍的id来查找到书籍存放在数据库中的信息,然后将这些信息传递到网页端进行显示即可。
数据访问层:
/**
* 根据书籍id获取书籍信息
* @param id
* @return 书籍对象
*/
public Book findBookByIdServlet(String id) throws SQLException {
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
Book book = queryRunner.query("select * from book where id=?", new BeanHandler<Book>(Book.class), id);
return book;
}
业务逻辑层:
//根据书id来查找书
public Book findBookByIdServlet(String id) {
Book book=null;
try {
book=bookDao.findBookByIdServlet(id);
} catch (SQLException e) {
e.printStackTrace();
}
return book;
}
然后我们通过servlet来将从数据库中得到的书籍信息写入request请求对象中,从而传递到网页端。
package Web;
import Service.BookServiceImpl;
import Util.Book;
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 = "FindBookByIdServlet")
public class FindBookByIdServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取数据
String id=request.getParameter("id");//获取request中存储的id信息
//业务处理
BookServiceImpl bookService=new BookServiceImpl();
Book book = bookService.findBookByIdServlet(id);
//分发转向
if (book!=null){
request.setAttribute("book",book);//将书籍信息写到request对象中
request.getRequestDispatcher("/admin/products/edit.jsp").forward(request,response);//将书本信息转发到编辑界面
}
}
}
接着我们在编辑界面获取request对象中的book属性数据,比如
<td align="center" bgColor="#f5fafe" class="ta_01">商品名称:</td>
<td class="ta_01" bgColor="#ffffff"><input type="text" name="name" class="bg" value="${book.name}"/></td>
...
需要注意的是书籍的类别是下拉框,所以要用js代码动态来更新下拉框的值,在框架进行加载的时候就调用方法,
<script type="text/javascript">
//设置类别的默认值
function setProductCategory(t) {
var category = document.getElementById("category");//根据id获取下拉列表元素
var ops = category.options;//获取所有的下拉选项数组
for ( var i = 0; i < ops.length; i++) {//遍历数组,找到书籍所属标签对应的下拉选项
if (ops[i].value == t) {
ops[i].selected = true;//将该选项设置为选中
return;
}
}
};
</script>
<body onload="setProductCategory('${book.category}')">
...
<body>
4.2数据的修改
数据回显之后,首先实现数据访问层
/**
* 更新书籍信息并写入数据库
* @param book
*/
public void updateBook(Book book) throws SQLException {
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
queryRunner.update("update book set name=?,price=?,pnum=?,category=?,description=? where id=?",
book.getName(),book.getPrice(),book.getPnum(),book.getCategory(),book.getDescription(),book.getId());
}
然后是业务逻辑层,
//更新书籍信息
public void updateBook(Book book) {
try {
bookDao.updateBook(book);
} catch (SQLException e) {
e.printStackTrace();
}
}
接着是将需要更新的信息封装成Book对象,这里用servlet从页面中获取更改的数据,
package Web;
import Service.BookServiceImpl;
import Util.Book;
import org.apache.commons.beanutils.BeanUtils;
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.lang.reflect.InvocationTargetException;
@WebServlet(name = "UpdateBookServlet")
public class UpdateBookServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//获取request中的书籍数据
Book book=new Book();
try {
BeanUtils.populate(book,request.getParameterMap());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//业务逻辑
BookServiceImpl bookService=new BookServiceImpl();
bookService.updateBook(book);
//跳转页面
request.getRequestDispatcher("/servlet/bookListServlet").forward(request,response);//跳转到书籍显示servlet
}
}
然后我们在修改界面将原始的信息放到request对象中供servlet取,在点击提交的时候跳转到servlet处理,
<form id="userAction_save_do" name="Form1" action="${pageContext.request.contextPath}/servlet/updateBookServlet" method="post">
接着配置一下servlet的映射地址即可。
<servlet>
<servlet-name>updateBookServlet</servlet-name>
<servlet-class>Web.UpdateBookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>updateBookServlet</servlet-name>
<url-pattern>/servlet/updateBookServlet</url-pattern>
</servlet-mapping>
五、书籍删除功能
删除功能就比较简单,显示数据访问层,
/**
* 根据id删除数据库中的书籍
* @param id
* @throws SQLException
*/
public void deleteBook(String id) throws SQLException{
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
queryRunner.update("delete from book where id=?",id);//通过id删除书籍
}
业务逻辑层
//根据id删除书籍
public void deleteBook(String id){
try {
bookDao.deleteBook(id);
} catch (SQLException e) {
e.printStackTrace();
}
}
然后是从页面获取到删除的id号之后,通过servlet将数据传输给业务逻辑层,并且删除完刷新显示界面,
package Web;
import Service.BookServiceImpl;
import Util.Book;
import org.apache.commons.beanutils.BeanUtils;
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.lang.reflect.InvocationTargetException;
@WebServlet(name = "DeleteBookServlet")
public class DeleteBookServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取数据
String id=request.getParameter("id");//获取要删除书籍的id号
//业务逻辑
BookServiceImpl bookService=new BookServiceImpl();
bookService.deleteBook(id);
//跳转页面
request.getRequestDispatcher("/servlet/bookListServlet").forward(request,response);//跳转到书籍显示servlet
}
}
编辑删除跳转的路径,这里需要注意,我们在删除之前要提示一下用户是否确认,
<td align="center" style="HEIGHT: 22px" width="7%">
<a href="javascript:deleteBook('${book.id}')">
<img src="${pageContext.request.contextPath}/admin/images/i_del.gif" width="16" height="16" border="0" style="CURSOR: hand">
</a>
</td>
然后实现对应的js的函数,实现提示并跳转,
function deleteBook(id){
if (confirm("是否确定删除")){
location.href="${pageContext.request.contextPath}/servlet/deleteBookServlet?id="+id;//跳转执行删除的servlet
}
}
配置好servlet的映射路径就算完成了。
首先随便添加一个书籍,
然后点击删除按钮,会弹出提示框,确认是否删除,
我们确认删除后,发现已经没有该书籍了,
六、全选与反选功能
我们首先要在商品前面加一个复选框按钮,用于表示该商品是否被选中,并且可以全选和反选
<%--添加全选栏--%>
<td align="center" width="10%">
<input type="checkbox" id="selAll" onclick="selectAll()">全选/全不选
</td>
<td align="center" width="24%">商品编号</td>
<td align="center" width="18%">商品名称</td>
<td align="center" width="9%">商品价格</td>
<td align="center" width="9%">商品数量</td>
<td width="8%" align="center">商品类别</td>
<td width="8%" align="center">编辑</td>
<td width="8%" align="center">删除</td>
<%--为每个书籍前面添加复选框,表示是否被选中--%>
<td style="CURSOR: hand; HEIGHT: 22px" align="center" width="23">
<input type="checkbox" name="checkBox">
</td>
<td style="CURSOR: hand; HEIGHT: 22px" align="center" width="23">${book.id}</td>
<td style="CURSOR: hand; HEIGHT: 22px" align="center" width="18%">${book.name}</td>
<td style="CURSOR: hand; HEIGHT: 22px" align="center" width="8%">${book.price}</td>
<td style="CURSOR: hand; HEIGHT: 22px" align="center" width="8%">${book.pnum}</td>
然后通过javascript代码控制点击全选按钮后的操作,
//全选商品或者反选
function selectAll(){
var flag=document.getElementById("selAll").checked;//获取全选框状态
var checkBox=document.getElementsByName("checkBox");//获取所有书籍的复选框元素
for (var i = 0; i < checkBox.length; i++) {
checkBox[i].checked=flag;//对每个复选框进行赋值
}
}
我们首先打开首页查看商品,点击全选按钮发现所有商品均被选中了
七、批量删除
完成了全选之后,我们将选中的书籍进行批量删除,而不是点击每个书籍后面的删除一个个删除。我们用两种不同的方法进行实现。
7.1响应函数删除
首先我们要加一个删除按钮,点击删除时获取所有的复选框的value,而每个复选框存储的值对应的就是每个书籍的id,
//批量删除商品
function deleteProduct(){
var checkBox=document.getElementsByName("checkBox");//获取所有书籍的复选框元素
var idstr="";
for (var i = 0; i < checkBox.length; i++) {
if (checkBox[i].checked==true) {//如果该书籍是被选中状态
idstr+="ids="+checkBox[i].value+"&";//将书籍的id加入到字符串中
}
}
idstr=idstr.substring(0,idstr.length-1);//去掉最后多余的&符号
alert(idstr);
if(idstr!=null){
location.href="${pageContext.request.contextPath}/servlet/delAllBooksServlet?"+idstr;//将所有的要删除字符串id作为参数传入删除的servlet中
}
}
然后我们新建一个servlet用于处理批量删除的书籍,传入的参数即要删除的书籍id,
package Web;
import 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;
@WebServlet(name = "DelAllBooksServlet")
public class DelAllBooksServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到所有要删除书籍的id数组
String[] ids = request.getParameterValues("ids");
//调用删除业务
BookServiceImpl bookService=new BookServiceImpl();
bookService.delAllBooks(ids);
//跳转页面,跳转到显示的servlet
request.getRequestDispatcher("/servlet/bookListServlet").forward(request,response);
}
}
在业务逻辑层调用数据访问层的方法进行和删除,
//根据id数组批量删除书籍
public void delAllBooks(String[] ids) {
try {
bookDao.delAllBooks(ids);
} catch (SQLException e) {
e.printStackTrace();
}
}
然后在数据访问层实现批量删除,
/**
* 根据id数组批量删除书籍
* @param ids
*/
public void delAllBooks(String[] ids) throws SQLException {
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
Object[][] params =new Object[ids.length][];//params为二维数组,高维是batch执行语句的次数,低维是存储每次执行时的参数值
for (int i = 0; i < params.length; i++) {
params[i]=new Object[]{ids[i]};//循环给每个一维数组中的元素赋值,值为书籍的id
}
queryRunner.batch("delete from book where id=?", params);//通过id删除书籍
}
当然还需要在web.xml中配置批量删除书籍servlet的映射路径,
<servlet>
<servlet-name>delAllBooksServlet</servlet-name>
<servlet-class>Web.DelAllBooksServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>delAllBooksServlet</servlet-name>
<url-pattern>/servlet/delAllBooksServlet</url-pattern>
</servlet-mapping>
启动服务器看一下批量删除的效果,首先新添加两本书籍,
然后我们选中这两本书籍进行批量删除,删除结果如下:
7.2提交表单删除
我们还可以在点击删除的时候将复选框的数据作为表单数据进行提交,我们将书籍的显示信息框放置在表单内,注意表单不要和上面的查询表单嵌套,
<form action="${pageContext.request.contextPath}/servlet/delAllBooksServlet" method="post">
...
...
</form>
接着修改批量删除按钮的响应函数,让其能够提交表单数据,
//提交表单信息
function submitForm() {
//var form2=document.getElementById("form2")
var form2=document.forms[1];//获取页面中第二个表单
form2.submit();//将表单提交,相当于点击提交按钮
}
注意表单提交的复选框名字要和后台获取表单数据时处理的名字要一样,复选框name为ids,则后台使用 request.getParameterValues时参数也应该传入ids
八、多条件查询
在进行多条件查询时,用户可能会输出多个不同的条件,这个时候我们就需要灵活的使用sql的查询语句进行查询,首先我们创建form1表单的查询servlet,
package Web;
import Service.BookServiceImpl;
import Util.Book;
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.List;
@WebServlet(name = "SearchBooksServlet")
public class SearchBooksServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//设置编码格式
//获取数据
String id = request.getParameter("id");
String category = request.getParameter("category");
String name = request.getParameter("name");
String minprice = request.getParameter("minprice");
String maxprice = request.getParameter("maxprice");
//调用业务逻辑
BookServiceImpl bookService=new BookServiceImpl();
List<Book> list=bookService.searchBooks(id,category,name,minprice,maxprice);
//跳转页面
request.setAttribute("books",list);//将查询的结果放置在request属性中跳转
request.getRequestDispatcher("/admin/products/list.jsp").forward(request,response);//显示查询的结果页面
}
}
然后在业务逻辑层调用数据访问层的方法进行查询,
//多条件查询书籍
public List<Book> searchBooks(String id, String category, String name, String minprice, String maxprice) {
try {
return bookDao.searchBooks(id,category,name,minprice,maxprice);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
接着在数据访问层实现查询功能,
/**
* 多条件查询书籍
* @param id
* @param category
* @param name
* @param minprice
* @param maxprice
* @return
*/
public List<Book> searchBooks(String id, String category, String name, String minprice, String maxprice) throws SQLException {
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
String sql="select * from book where 1=1";//执行的查询语句
List list =new ArrayList();//存放查询参数的集合
if (!"".equals(id.trim())){
sql+=" and id like ?";
list.add("%"+id.trim()+"%");//注意使用like时要加 %blabla%
}
if (!"".equals(category.trim())){
sql+=" and category=?";
list.add(category.trim());
}
if (!"".equals(name.trim())){
sql+=" and name like ?";
list.add("%"+name.trim()+"%");//注意使用like时要加 %blabla%
}
if (!"".equals(minprice.trim())){
sql+=" and price>?";
list.add(minprice.trim());
}
if (!"".equals(maxprice.trim())){
sql+=" and price<?";
list.add(maxprice.trim());
}
return queryRunner.query(sql,new BeanListHandler<Book>(Book.class),list.toArray());//执行查询语句,并将结果通过BeanListHandler封装到List<Book>的集合中
}
当然还要配置一下web.xml中的查询servlet的映射路径,
<servlet>
<servlet-name>searchBooksServlet</servlet-name>
<servlet-class>Web.SearchBooksServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>searchBooksServlet</servlet-name>
<url-pattern>/servlet/searchBooksServlet</url-pattern>
</servlet-mapping>
然后我们进行查询名称中包含“Java”字样的书籍信息,
九、分页功能
要完成分页功能的话,首先我们在数据库中添加多一点书籍,
然后我们希望可以对这些书籍分页显示,比如每一页显示五本书籍,如果想要看其他的书,可以点击下一页页面跳转,而这些书籍是存储在数据库的,那么我们就可以每次从数据库中取出一定的书籍来显示,
数据库的select相关语句为:
select * from book limit begin_index,num
这里的begin_index指的是从第几本书开始取,num指的是取多少本书,比如(0,3)就代表从第一本书开始取3本书,
如果我们用currentPage表示当前的页数,pageVolume表示一页放几本书,那么取每一页的书籍sql语句可以表示为:
int currentPage; --当前页数
int pageVolume; --每页显示的书籍数
select * from book limit (currentPage-1)*pageVolume,pageVolume
我们还需要计算一下总页数,
int count = select count(*) from book; --总记录数
int totalPage = Math.ceil(count * 1.0 / pageVolume) --总页数
所以我们需要传递当前页面值,总页数以及查询到的当前书籍的集合,这里我们用到了PageBean的方法来传递这些值。
public class PageBean {
private int currentPage;//当前页
private int pageVolume;//每页放几本书
private int count;//数据库内书籍总数
private int totalPage;//总页面数
private List<Book> books;//当前页的书籍集合
...
...//getter和setter方法
}
首先我们先写一下点击上一页下一页的servlet,最后将结果显示在product_list.jsp页面中,
package Web;
import Service.BookServiceImpl;
import Util.PageBean;
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 = "PageChangeServlet")
public class PageChangeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//初始化每页显示的记录数
int pageVolume=4;
int currentPage=1;
String str = request.getParameter("currentPage");
if (str!=null){ //如果第一访问页面则当前页返回值为空,使用初始值1
currentPage=Integer.parseInt(str);
}
//业务逻辑处理
BookServiceImpl bookService=new BookServiceImpl();
PageBean pageBean = bookService.findBooksPage(currentPage,pageVolume);//分页查询并返回当前页的书籍集合
//分发转向
request.setAttribute("pageBean",pageBean);//将pageBean对象存储到request属性中
request.getRequestDispatcher("/product_list.jsp").forward(request,response);
}
}
然后在业务逻辑层调用数据访问层的方法实现,
//分页查询书籍,并返回当前页书籍集合
public PageBean findBooksPage(int currentPage, int pageVolume) {
try {
int count = bookDao.bookCount();//获取数据库的书籍总数
int totalPage = (int)Math.ceil(count*1.0/pageVolume);//求总页面数
List<Book> books =bookDao.findBooksPage(currentPage,pageVolume);//得到当前页面的书籍集合
PageBean pageBean=new PageBean(currentPage,pageVolume,count,totalPage,books);//将结果封装到PageBean对象中传回去
return pageBean;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
接着在数据访问层访问数据库实现分页查询,并返回当前页的书籍集合,
/**
* 获取数据库中的书籍数量
* @return
* @throws SQLException
*/
public int bookCount() throws SQLException {
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
long l = (Long)queryRunner.query("select count(*) from book",new ScalarHandler(1));
return (int)l;
}
/**
* 分页查询书籍并返回当前页的书籍集合
* @param currentPage
* @param pageVolume
* @return
*/
public List<Book> findBooksPage(int currentPage, int pageVolume) throws SQLException {
QueryRunner queryRunner=new QueryRunner(C3P0Util.getDataSource());
return queryRunner.query("select * from book limit ?,?", new BeanListHandler<Book>(Book.class),(currentPage-1)*pageVolume,pageVolume);
}
得到了返回的书籍集合了,现在我们将书籍信息在product_list.jsp中显示出来,通过request中设置的属性pageBean来获取书籍信息,
<table cellspacing="0" class="booklist">
<tr>
<c:forEach items="${pageBean.books }" var="book">
<td>
<div class="divbookpic">
<p>
<a href="#"><img src="" width="115" height="129" border="0" /> </a>
</p>
</div>
<div class="divlisttitle">
<a href="#">书名:${book.name}<br />售价:${book.price}</a>
</div>
</td>
</c:forEach>
</tr>
</table>
<div class="pagination">
<ul>
<li class="disablepage"><a href="${pageContext.request.contextPath}/servlet/pageChangeServlet?currentPage=${pageBean.currentPage==1?1:pageBean.currentPage-1}"><<上一页</li>
<li>第${pageBean.currentPage}页/共${pageBean.totalPage}页</li>
<li class="nextPage"><a href="${pageContext.request.contextPath}/servlet/pageChangeServlet?currentPage=${pageBean.currentPage==pageBean.totalPage?pageBean.totalPage:pageBean.currentPage+1}">下一页>></a></li>
</ul>
</div>
配置好servlet的映射路径就可以进行访问了,
十、显示书籍详细信息
在完成了书籍分页功能后,接着我们希望点击书籍可以查看书籍的详细信息,查询的条件就是点击书籍的id,通过传递id来查找该书籍的详细信息并显示,
首先我们新建一个servlet通过书籍的id获取书籍的信息,在点击的时候就将id传递给该servlet,
package Web;
import Service.BookServiceImpl;
import Util.Book;
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 = "FindBookDetailsServlet")
public class FindBookDetailsServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取数据
String id=request.getParameter("id");//获取request中存储的id信息
//业务处理
BookServiceImpl bookService=new BookServiceImpl();
Book book = bookService.findBookByIdServlet(id);
//跳转页面
request.setAttribute("book",book);//将书籍信息写到request对象中
request.getRequestDispatcher("/product_info.jsp").forward(request,response);//将书本信息转发到编辑界面
}
}
然后我们可以直接调用之前的findBookById的业务逻辑代码,只不过最后不同的是跳转界面不同,那个是跳转到编辑界面,这个是跳转到书籍的详细信息界面,
接着我们在product_info.jsp中修改一下书籍的显示信息,
<td style="padding:20px 5px 5px 5px">
<img src="images/miniicon3.gif" width="16" height="13" /><font class="bookname"> ${book.name}</font>
<hr />售价:<font color="#FF0000">¥:${book.price}元</font>
<hr /> 类别:${book.category}<hr />
<p><b>内容简介:</b></p>${book.description}
</td>
然后配置一下servlet的映射地址,启动服务器,点击书籍即可显示详细信息