改成jsp页面之后,方便回显登录和注册失败之后的错误信息
页面 jsp 动态化
1、在 每个html 页面顶行添加 page 指令。
2、修改文件后缀名为:.jsp
3、地址修改之后无法使用,使用 IDEA 搜索替换.html 为.jsp(快捷键:Ctrl+Shift+R)
新建login_success_menu.jsp文件,抽取公共的部分
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
新建head.jsp,抽取引入的类库等头信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%String basePath = request.getScheme()+ "://"+ request.getServerName()+ ":"+ request.getServerPort()+ request.getContextPath()+ "/";
%>
">
新建footer.jsp抽取页脚
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
尚硅谷书城.Copyright ©2015
新建manager_menu.jsp抽取菜单
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
使用include可以引入抽取的公共部分
<%--静态包含,登录 成功之后的菜单 --%><%@ include file="/pages/common/login_success_menu.jsp"%>
head.jsp文件解决用户每次访问都是localhost地址
方法 | 作用 |
---|---|
request.getScheme() | 协议 |
request.getServerName() | 服务器IP,动态获取每次请求的IP |
request.getServerPort() | 端口号 |
request.getContextPath() | 工程路径 |
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%String basePath = request.getScheme()+ "://"+ request.getServerName()+ ":"+ request.getServerPort()+ request.getContextPath()+ "/";
%>
">
以登录回显为示例:
1、Servlet 程序端需要添加回显信息到 Request 域中,提示的信息msg,回显的信息username
2、设置登录失败跳回的页面
jsp 页面,需要输出回显信息
1、如果等于null,提示请输入用户名密码
2、如果不等于null,提示错误信息
3、在用户名标签的value中判断返回的username
在实际的项目开发中,一个模块,一般只使用一个 Servlet 程序。
将登录和注册Servlet合并成为UserServlet
UserServlet
package com.atguigu.web;import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import com.atguigu.utils.WebUtils;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class UserServlet extends BaseServlet {private UserService userService = new UserServiceImpl();/*** 处理登录的功能** @param req* @param resp* @throws ServletException* @throws IOException*/protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1、获取请求的参数String username = req.getParameter("username");String password = req.getParameter("password");// 调用 userService.login()登录处理业务User loginUser = userService.login(new User(null, username, password, null));// 如果等于null,说明登录 失败!if (loginUser == null) {// 把错误信息,和回显的表单项信息,保存到Request域中req.setAttribute("msg", "用户或密码错误!");req.setAttribute("username", username);// 跳回登录页面req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);} else {// 登录 成功//跳到成功页面login_success.htmlreq.getRequestDispatcher("/pages/user/login_success.jsp").forward(req, resp);}}/*** 处理注册的功能** @param req* @param resp* @throws ServletException* @throws IOException*/protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1、获取请求的参数String username = req.getParameter("username");String password = req.getParameter("password");String email = req.getParameter("email");String code = req.getParameter("code");User user = WebUtils.copyParamToBean(req.getParameterMap(), new User());// 2、检查 验证码是否正确 === 写死,要求验证码为:abcdeif ("abcde".equalsIgnoreCase(code)) {
// 3、检查 用户名是否可用if (userService.existsUsername(username)) {System.out.println("用户名[" + username + "]已存在!");// 把回显信息,保存到Request域中req.setAttribute("msg", "用户名已存在!!");req.setAttribute("username", username);req.setAttribute("email", email);// 跳回注册页面req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);} else {// 可用
// 调用Sservice保存到数据库userService.registUser(new User(null, username, password, email));
//
// 跳到注册成功页面 regist_success.jspreq.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req, resp);}} else {// 把回显信息,保存到Request域中req.setAttribute("msg", "验证码错误!!");req.setAttribute("username", username);req.setAttribute("email", email);System.out.println("验证码[" + code + "]错误");req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);}}
}
还要给 login.jsp 添加隐藏域和修改请求地址
给 tegist.jsp 页面添加隐藏域 action,和修改请求地址
将if else判断改为使用反射调用对应的方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String action = req.getParameter("action");try {// 获取action 业务鉴别字符串,获取相应的业务方法反射对象Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);// System.out.println(method);// 调用目标业务 方法method.invoke(this, req, resp);} catch (Exception e) { e.printStackTrace();
}
其它的Servlet改为继承BaseServlet
package com.atguigu.web;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;public abstract class BaseServlet extends HttpServlet {protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String action = req.getParameter("action");try {// 获取action业务鉴别字符串,获取相应的业务 方法反射对象Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// System.out.println(method);// 调用目标业务 方法method.invoke(this, req, resp);} catch (Exception e) {e.printStackTrace();}}
}
BeanUtils 工具类,它可以一次性的把所有请求的参数注入到 JavaBean 中。经常用于把 Map 中的值注入到 JavaBean 中,或者是对象属性值的拷贝操作。
BeanUtils 它不是 Jdk 的类。而是第三方的工具类。所以需要导包。
1、导 入 需 要 的 jar 包 : commons-beanutils-1.8.0.jar commons-logging-1.1.1.jar
2、编写 WebUtils 工具类使用:
package com.atguigu.utils;import org.apache.commons.beanutils.BeanUtils;
import java.util.Map;public class WebUtils {/*** 把Map中的值注入到对应的JavaBean属性中。* @param value* @param bean*/public static T copyParamToBean( Map value , T bean ){try {System.out.println("注入之前:" + bean);/*** 把所有请求的参数都注入到user对象中*/BeanUtils.populate(bean, value);System.out.println("注入之后:" + bean);} catch (Exception e) {e.printStackTrace();}return bean;}
}
以登录为示例:
231.书城项目-第五阶段,内容介绍
MVC 全称:Model 模型、 View 视图、 Controller 控制器。
MVC 最早出现在 JavaEE 三层中的 Web 层,它可以有效的指导 Web 层的代码如何有效分离,单独工作。
View 视图:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工合作——JSP/HTML。
Controller 控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个“调度者”的角色——Servlet。转到某个页面。或者是重定向到某个页面。
Model 模型:将与业务逻辑相关的数据封装为具体的 JavaBean 类,其中不掺杂任何与数据处理相关的代码——JavaBean/domain/entity/pojo。
MVC 是一种思想
MVC 的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了降低耦合度)。
create table t_book(`id` int primary key auto_increment,`name` varchar(100),`price` decimal(11,2),`author` varchar(100),`sales` int,`stock` int,`img_path` varchar(200)
);## 插入初始化测试数据
insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
values(null , 'java 从入门到放弃' , '国哥' , 80 , 9999 , 9 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) values(null , '数据结构与算法' , '严敏君' , 78.5 , 6 , 13 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) values(null , '怎样拐跑别人的媳妇' , '龙伍' , 68, 99999 , 52 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) values(null , '木虚肉盖饭' , '小胖' , 16, 1000 , 50 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) values(null , 'C++编程思想' , '刚哥' , 45.5 , 14 , 95 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) values(null , '蛋炒饭' , '周星星' , 9.9, 12 , 53 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) values(null , '赌神' , '龙伍' , 66.5, 125 , 535 , 'static/img/default.jpg');## 查看表内容
select id,name,author,price,sales,stock,img_path from t_book;
public class Book { private Integer id; private String name; private String author;private BigDecimal price; private Integer sales; private Integer stock;private String imgPath = "static/img/default.jpg";
JdbcUtils
package com.atguigu.utils;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;public class JdbcUtils {private static DruidDataSource dataSource;static {try {Properties properties = new Properties();// 读取 jdbc.properties属性配置文件InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");// 从流中加载数据properties.load(inputStream);// 创建 数据库连接 池dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}/*** 获取数据库连接池中的连接* @return 如果返回null,说明获取连接失败
有值就是获取连接成功*/public static Connection getConnection(){Connection conn = null;try {conn = dataSource.getConnection();} catch (Exception e) {e.printStackTrace();}return conn;}/*** 关闭连接,放回数据库连接池* @param conn*/public static void close(Connection conn){if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}
}
BaseDao
package com.atguigu.dao.impl;import com.atguigu.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;public abstract class BaseDao {//使用DbUtils操作数据库private QueryRunner queryRunner = new QueryRunner();/*** update() 方法用来执行:Insert\Update\Delete语句** @return 如果返回-1,说明执行失败
返回其他表示影响的行数*/public int update(String sql, Object... args) {Connection connection = JdbcUtils.getConnection();try {return queryRunner.update(connection, sql, args);} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtils.close(connection);}return -1;}/*** 查询返回一个javaBean的sql语句** @param type 返回的对象类型* @param sql 执行的sql语句* @param args sql对应的参数值* @param 返回的类型的泛型* @return*/public T queryForOne(Class type, String sql, Object... args) {Connection con = JdbcUtils.getConnection();try {return queryRunner.query(con, sql, new BeanHandler(type), args);} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtils.close(con);}return null;}/*** 查询返回多个javaBean的sql语句** @param type 返回的对象类型* @param sql 执行的sql语句* @param args sql对应的参数值* @param 返回的类型的泛型* @return*/public List queryForList(Class type, String sql, Object... args) {Connection con = JdbcUtils.getConnection();try {return queryRunner.query(con, sql, new BeanListHandler(type), args);} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtils.close(con);}return null;}/*** 执行返回一行一列的sql语句* @param sql 执行的sql语句* @param args sql对应的参数值* @return*/public Object queryForSingleValue(String sql, Object... args){Connection conn = JdbcUtils.getConnection();try {return queryRunner.query(conn, sql, new ScalarHandler(), args);} catch (Exception e) {e.printStackTrace();} finally {JdbcUtils.close(conn);}return null;}
}
BookDao
package com.atguigu.dao;import com.atguigu.pojo.Book;import java.util.List;public interface BookDao {public int addBook(Book book);public int deleteBookById(Integer id);public int updateBook(Book book);public Book queryBookById(Integer id);public List queryBooks();}
BookDaoImpl
package com.atguigu.dao.impl;import com.atguigu.dao.BookDao;
import com.atguigu.pojo.Book;import java.util.List;public class BookDaoImpl extends BaseDao implements BookDao {@Overridepublic int addBook(Book book) {String sql = "insert into t_book(`name`,`author`,`price`,`sales`,`stock`,`img_path`) values(?,?,?,?,?,?)";return update(sql, book.getName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImgPath());}@Overridepublic int deleteBookById(Integer id) {String sql = "delete from t_book where id = ?";return update(sql, id);}@Overridepublic int updateBook(Book book) {String sql = "update t_book set `name`=?,`author`=?,`price`=?,`sales`=?,`stock`=?,`img_path`=? where id = ?";return update(sql,book.getName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImgPath(),book.getId());}@Overridepublic Book queryBookById(Integer id) {String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imgPath from t_book where id = ?";return queryForOne(Book.class, sql,id);}@Overridepublic List queryBooks() {String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imgPath from t_book";return queryForList(Book.class, sql);}
}
BookDao 的测试
package com.atguigu.test;import com.atguigu.dao.BookDao;
import com.atguigu.dao.impl.BookDaoImpl;
import com.atguigu.pojo.Book;
import org.junit.Test;import java.math.BigDecimal;import static org.junit.Assert.*;public class BookDaoTest {private BookDao bookDao = new BookDaoImpl();@Testpublic void addBook() {bookDao.addBook(new Book(null,"国哥为什么这么帅!", "191125", new BigDecimal(9999),1100000,0,null));}@Testpublic void deleteBookById() {bookDao.deleteBookById(21);}@Testpublic void updateBook() {bookDao.updateBook(new Book(21,"大家都可以这么帅!", "国哥", new BigDecimal(9999),1100000,0,null));}@Testpublic void queryBookById() {System.out.println( bookDao.queryBookById(21) );}@Testpublic void queryBooks() {for (Book queryBook : bookDao.queryBooks()) {System.out.println(queryBook);}}
}
BookService
package com.atguigu.service;import com.atguigu.pojo.Book;
import java.util.List;public interface BookService {public void addBook(Book book);public void deleteBookById(Integer id);public void updateBook(Book book);public Book queryBookById(Integer id);public List queryBooks();
}
BookServiceImpl
package com.atguigu.service.impl;import com.atguigu.dao.BookDao;
import com.atguigu.dao.impl.BookDaoImpl;
import com.atguigu.pojo.Book;
import com.atguigu.service.BookService;import java.util.List;public class BookServiceImpl implements BookService {private BookDao bookDao = new BookDaoImpl();@Overridepublic void addBook(Book book) {bookDao.addBook(book);}@Overridepublic void deleteBookById(Integer id) {bookDao.deleteBookById(id);}@Overridepublic void updateBook(Book book) {bookDao.updateBook(book);}@Overridepublic Book queryBookById(Integer id) {return bookDao.queryBookById(id);}@Overridepublic List queryBooks() {return bookDao.queryBooks();}
}
BookServiceTest
package com.atguigu.test;import com.atguigu.pojo.Book;
import com.atguigu.service.BookService;
import com.atguigu.service.impl.BookServiceImpl;
import org.junit.Test;import java.math.BigDecimal;import static org.junit.Assert.*;public class BookServiceTest {private BookService bookService = new BookServiceImpl();@Testpublic void addBook() {bookService.addBook(new Book(null,"国哥在手,天下我有!", "1125", new BigDecimal(1000000), 100000000, 0, null));}@Testpublic void deleteBookById() {bookService.deleteBookById(22);}@Testpublic void updateBook() {bookService.updateBook(new Book(22,"社会我国哥,人狠话不多!", "1125", new BigDecimal(999999), 10, 111110, null));}@Testpublic void queryBookById() {System.out.println(bookService.queryBookById(22));}@Testpublic void queryBooks() {for (Book queryBook : bookService.queryBooks()) {System.out.println(queryBook);}}
}
BookServlet 程序中添加 list 方法
protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1 通过BookService 查询全部图书List books = bookService.queryBooks();//2 把全部图书保存到Request 域中req.setAttribute("books", books);//3、请求转发到/pages/manager/book_manager.jsp 页面req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req ,resp);
}
修改【图书管理】请求地址
修改 pages/manager/book_manager.jsp 页面的数据遍历输出
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
图书管理 <%-- 静态包含 base标签、css样式、jQuery文件 --%><%@ include file="/pages/common/head.jsp"%>
图书管理系统<%-- 静态包含 manager管理模块的菜单 --%><%@include file="/pages/common/manager_menu.jsp"%><%--静态包含页脚内容--%><%@include file="/pages/common/footer.jsp"%>
问题说明:表单重复提交:
当用户提交完请求,浏览器会记录下最后一次请求的全部信息。当用户按下功能键 F5,就会发起浏览器记录的最后一次请求。
BookServlet 程序中添加 add 方法
解决方法:将req请求转发,改为resp重定向
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1、获取请求的参数==封装成为Book对象Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
// 2、调用BookService.addBook()保存图书bookService.addBook(book);
// 3、跳到图书列表页面
// /manager/bookServlet?action=list
// req.getRequestDispatcher("/manager/bookServlet?action=list").forward(req, resp);resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");}
BookServlet 程序中的 delete 方法
protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求的参数id,图书编程int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 2、调用bookService.deleteBookById();删除图书bookService.deleteBookById(id);
// 3、重定向回图书列表管理页面
// /book/manager/bookServlet?action=listresp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");}
给 WebUtils 工具类添加转换 int 类型的工具方法
/*** 将字符串转换成为int类型的数据* @param strInt* @param defaultValue* @return*/public static int parseInt(String strInt,int defaultValue) {try {return Integer.parseInt(strInt);} catch (Exception e) {e.printStackTrace();}return defaultValue;}
修改删除的连接地址:
给删除添加确认提示操作:
<%-- 静态包含 base标签、css样式、jQuery文件 --%><%@ include file="/pages/common/head.jsp"%>
1、点击修改调用BookServlet.getBook获取图书信息,保存到域中
2、BookServlet.getBook请求转发到bool_edit.jsp页面
3、bool_edit.jsp页面获取域中的信息显示
4、bool_edit.jsp页面修改信息提交给服务器BookServlet.update保存修改
5、BookServlet.update重定向到图书管理页面BookServlet.list
6、页面刷新数据
更新【修改】的请求地址:
BookServlet 程序中添加 getBook 方法
protected void getBook(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1 获取请求的参数图书编号int id = WebUtils.parseInt(req.getParameter("id"), 0);//2 调用bookService.queryBookById查询图书Book book = bookService.queryBookById(id);//3 保存到图书到Request域中req.setAttribute("book", book) ;//4 请求转发到。pages/manager/book_edit.jsp页面req.getRequestDispatcher("/pages/manager/book_edit.jsp").forward(req,resp);}
在 book_edit.jsp 页面中显示修改的数据
在 BookServlet 程序中添加 update 方法:
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求的参数==封装成为Book对象Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
// 2、调用BookService.updateBook( book );修改图书bookService.updateBook(book);
// 3、重定向回图书列表管理页面
// 地址:/工程名/manager/bookServlet?action=listresp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");}
解决 book_edit.jsp 页面,即要实现添加,又要实现修改操作。
book_edit.jsp页面,既要做添加操作,又要做修改操作,而到底是添加还是修改是由一个隐藏域来决定的。如何动态修改隐藏域,让他的值既可以实现添加,又可以实现修改操作。
解决方案一:可以在发请求发起时,附带上当前要操作的值,并注入到隐藏域中
解决方案二:修改有id参数,添加没有id参数。通过判断参数是否有id来确定是添加还是修改操作
解决方案三:可以通过判断Request域中是否包含有修改的图书信息对象,如果没有说明是添加操作,如果有说明是修改操作。
需要的属性 | 属性名 | 如何获取 |
---|---|---|
pageNo | 当前页码 | 客户端进行传递 |
pageTotal | 总页码 | 总记录数/每页数量 |
pageTotalCount | 总记录数 | sql语句count |
pageSize | 每页显示数量 | 客户端进行传递、页面布局决定 |
items | 当前页数据 | sql语句select limit |
package com.atguigu.pojo;import java.util.List;/*** Page是分页的模型对象* @param 是具体的模块的javaBean类*/
public class Page {public static final Integer PAGE_SIZE = 4;// 当前页码private Integer pageNo;// 总页码private Integer pageTotal;// 当前页显示数量private Integer pageSize = PAGE_SIZE;// 总记录数private Integer pageTotalCount;// 当前页数据private List items;// 分页条的请求地址private String url;
}
BookServlet
/*** 处理分页功能* @param req* @param resp* @throws ServletException* @throws IOException*/protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1 获取请求的参数 pageNo 和 pageSizeint pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 1);int pageSize = WebUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);//2 调用BookService.page(pageNo,pageSize):Page对象Page page = bookService.page(pageNo,pageSize);page.setUrl("manager/bookServlet?action=page");//3 保存Page对象到Request域中req.setAttribute("page",page);//4 请求转发到pages/manager/book_manager.jsp页面req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);}
BookServiceImpl
@Overridepublic Page page(int pageNo, int pageSize) {Page page = new Page();// 设置每页显示的数量page.setPageSize(pageSize);// 求总记录数Integer pageTotalCount = bookDao.queryForPageTotalCount();// 设置总记录数page.setPageTotalCount(pageTotalCount);// 求总页码Integer pageTotal = pageTotalCount / pageSize;if (pageTotalCount % pageSize > 0) {pageTotal+=1;}// 设置总页码page.setPageTotal(pageTotal);// 设置当前页码page.setPageNo(pageNo);// 求当前页数据的开始索引int begin = (page.getPageNo() - 1) * pageSize;// 求当前页数据List items = bookDao.queryForPageItems(begin,pageSize);// 设置当前页数据page.setItems(items);return page;}
BookDaoImpl
@Overridepublic Integer queryForPageTotalCount() {String sql = "select count(*) from t_book";Number count = (Number) queryForSingleValue(sql);return count.intValue();}@Overridepublic List queryForPageItems(int begin, int pageSize) {String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imgPath from t_book limit ?,?";return queryForList(Book.class,sql,begin,pageSize);}
manager_menu.jsp 中【图书管理】请求地址的修改:
book_manager.jsp 修改:
到第页
Page 对象中的修改:
public void setPageNo(Integer pageNo) {
/* 数据边界的有效检查 */if (pageNo < 1) { pageNo = 1;}if (pageNo > pageTotal) { pageNo = pageTotal;}this.pageNo = pageNo;
}
BookService 中 page 方法的修改:
@Overridepublic Page page(int pageNo, int pageSize) {Page page = new Page();// 设置每页显示的数量page.setPageSize(pageSize);// 求总记录数Integer pageTotalCount = bookDao.queryForPageTotalCount();// 设置总记录数page.setPageTotalCount(pageTotalCount);// 求总页码Integer pageTotal = pageTotalCount / pageSize;if (pageTotalCount % pageSize > 0) {pageTotal+=1;}// 设置总页码page.setPageTotal(pageTotal);// 设置当前页码page.setPageNo(pageNo);// 求当前页数据的开始索引int begin = (page.getPageNo() - 1) * pageSize;// 求当前页数据List items = bookDao.queryForPageItems(begin,pageSize);// 设置当前页数据page.setItems(items);return page;}
需求:显示 5 个连续的页码,而且当前页码在中间。除了当前页码之外,每个页码都可以点击跳到指定页。
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--分页条的开始--%>
<%--大于首页,才显示--%> 1}">首页上一页 <%--页码输出的开始--%><%--情况1:如果总页码小于等于5的情况,页码的范围是:1-总页码--%> <%--情况2:总页码大于5的情况--%> 5}"><%--小情况1:当前页码为前面3个:1,2,3的情况,页码范围是:1-5.--%> <%--小情况2:当前页码为最后3个,8,9,10,页码范围是:总页码减4 - 总页码--%> requestScope.page.pageTotal-3}"> <%--小情况3:4,5,6,7,页码范围是:当前页码减2 - 当前页码加2--%> 【${i}】 ${i} <%--页码输出的结束--%><%-- 如果已经 是最后一页,则不显示下一页,末页 --%>下一页末页 共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录到第页
以修改图书为示例:
1、在修改的请求地址上追加当前页码参数:
2、在 book_edit.jsp 页面中使用隐藏域记录下 pageNo 参数
3、在服务器重定向的时候,获取当前页码追加上进行跳转,update方法
在 page 对象中添加 url 属性
// 分页条的请求地址
private String url;
Servlet 程序的 page 分页方法中设置 url 的分页请求地址
修改分页条中请求地址为 url 变量输出,并抽取一个单独的 jsp 页面
ClientBookServlet
package com.atguigu.web;import com.atguigu.pojo.Book;
import com.atguigu.pojo.Page;
import com.atguigu.service.BookService;
import com.atguigu.service.impl.BookServiceImpl;
import com.atguigu.utils.WebUtils;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class ClientBookServlet extends BaseServlet {private BookService bookService = new BookServiceImpl();/*** 处理分页功能* @param req* @param resp* @throws ServletException* @throws IOException*/protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1 获取请求的参数 pageNo 和 pageSizeint pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 1);int pageSize = WebUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);//2 调用BookService.page(pageNo,pageSize):Page对象Page page = bookService.page(pageNo,pageSize);page.setUrl("client/bookServlet?action=page");//3 保存Page对象到Request域中req.setAttribute("page",page);//4 请求转发到pages/manager/book_manager.jsp页面req.getRequestDispatcher("/pages/client/index.jsp").forward(req,resp);}/*** 处理分页功能* @param req* @param resp* @throws ServletException* @throws IOException*/protected void pageByPrice(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1 获取请求的参数 pageNo 和 pageSizeint pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 1);int pageSize = WebUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);int min = WebUtils.parseInt(req.getParameter("min"), 0);int max = WebUtils.parseInt(req.getParameter("max"), Integer.MAX_VALUE);//2 调用BookService.page(pageNo,pageSize):Page对象Page page = bookService.pageByPrice(pageNo,pageSize,min,max);StringBuilder sb = new StringBuilder("client/bookServlet?action=pageByPrice");// 如果有最小价格的参数,追加到分页条的地址参数中if (req.getParameter("min") != null) {sb.append("&min=").append(req.getParameter("min"));}// 如果有最大价格的参数,追加到分页条的地址参数中if (req.getParameter("max") != null) {sb.append("&max=").append(req.getParameter("max"));}page.setUrl(sb.toString());//3 保存Page对象到Request域中req.setAttribute("page",page);//4 请求转发到pages/manager/book_manager.jsp页面req.getRequestDispatcher("/pages/client/index.jsp").forward(req,resp);}
}
255.书城项目-搜索价格区间的回显
256.书城项目-解决分页条中不带价格区间的bug