1、Html转Jsp实现动态化

  1. 在 html 页面顶行添加 page 指令。

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. 修改文件后缀名为:.jsp

  3. 使用 IDEA 搜索替换.html 为.jsp(快捷键:Ctrl+Shift+R)

10、Web项目延伸完善 - 图1

2、抽取页面相同内容(用静态注入)

将页面中相同且需要多次用到的代码块,提取出来,并保存在“pages/common”目录中,使用静态注入的方式嵌入到其他页面中,既节省空间又方便后续修改

2.1、 head 中 css、jquery、base 标签

head.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%
  3. String basePath = request.getScheme()
  4. + "://"
  5. + request.getServerName()
  6. + ":"
  7. + request.getServerPort()
  8. + request.getContextPath()
  9. + "/";
  10. pageContext.setAttribute("basePath",basePath);
  11. %>
  12. <!--写base标签,永远固定相对路径跳转的结果-->
  13. <base href="<%=basePath%>">
  14. <link type="text/css" rel="stylesheet" href="static/css/style.css" >
  15. <script type="text/javascript" src="static/script/jquery-1.7.2.js"></script>

2.2、每个页面的页脚

footer.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <div id="bottom">
  3. <span>
  4. 尚硅谷书城.Copyright &copy;2015
  5. </span>
  6. </div>

2.3、 登录成功后的菜单

login_success_menu.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <div>
  3. <span>欢迎<span class="um_span"></span>光临尚硅谷书城</span>
  4. <a href="pages/order/order.jsp">我的订单</a>
  5. <a href="index.jsp">注销</a>&nbsp;&nbsp;
  6. <a href="index.jsp">返回</a>
  7. </div>

2.4、manager 模块的菜单

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <div>
  3. <a href="manager/bookServlet?action=page">图书管理</a>
  4. <a href="order_manager.jsp">订单管理</a>
  5. <a href="index.jsp">返回商城</a>
  6. </div>

2.5、静态注入jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>尚硅谷会员注册页面</title>
  7. <%-- 静态包含 base标签、css样式、jQuery文件 --%>
  8. <%@ include file="/pages/common/head.jsp"%>
  9. <style type="text/css">
  10. h1 {
  11. text-align: center;
  12. margin-top: 200px;
  13. }
  14. h1 a {
  15. color:red;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <div id="header">
  21. <img class="logo_img" alt="" src="static/img/logo.gif" >
  22. <%--静态包含,登录 成功之后的菜单 --%>
  23. <%@ include file="/pages/common/login_success_menu.jsp"%>
  24. </div>
  25. <div id="main">
  26. <h1>欢迎回来 <a href="../../index.jsp">转到主页</a></h1>
  27. </div>
  28. <%--静态包含页脚内容--%>
  29. <%@include file="/pages/common/footer.jsp"%>
  30. </body>
  31. </html>

2.6、注意“/”

  1. <a href="pages/order/order.jsp">我的订单</a>
  1. <%@include file="/pages/common/footer.jsp"%>

href后面开头不需要紧接“/”,但file后面需要紧接“/”

3、登录、注册错误提示,及表单回显

以登录回显为示例: Servlet 程序端需要添加回显信息到 Request 域中

10、Web项目延伸完善 - 图2

4、BaseServlet 的抽取

在实际的项目开发中,一个模块,一般只使用一个 Servlet

代码优化一:合并 LoginServlet 和 RegistServlet 程序为 UserServlet 程序

10、Web项目延伸完善 - 图3

在jsp页面中通过隐藏的选项指定使用的方法

  1. <input type="hidden" name="action" value="login" />

UserServlet 程序:

  1. package com.chang.web;
  2. import com.chang.pojo.User;
  3. import com.chang.service.UserService;
  4. import com.chang.service.impl.UserServiceImpl;
  5. import com.chang.utils.WebUtils;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.io.IOException;
  10. public class UserServlet extends HttpServlet {
  11. private UserService userService = new UserServiceImpl();
  12. /**
  13. * 处理登录的功能
  14. * @param req
  15. * @param resp
  16. * @throws ServletException
  17. * @throws IOException
  18. */
  19. protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  20. // 1、获取请求的参数
  21. String username = req.getParameter("username");
  22. String password = req.getParameter("password");
  23. // 调用 userService.login()登录处理业务
  24. User loginUser = userService.login(new User(null, username, password, null));
  25. // 如果等于 null,说明登录 失败!
  26. if (loginUser == null) {
  27. // 把错误信息,和回显的表单项信息,保存到 Request 域中
  28. req.setAttribute("msg","用户或密码错误!");
  29. req.setAttribute("username", username);
  30. // 跳回登录页面
  31. req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);
  32. } else {
  33. // 登录 成功
  34. //跳到成功页面 login_success.html
  35. req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req, resp);
  36. }
  37. }
  38. /**
  39. * 处理注册的功能
  40. * @param req
  41. * @param resp
  42. * @throws ServletException
  43. * @throws IOException
  44. */
  45. protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  46. // 1、获取请求的参数
  47. String username = req.getParameter("username");
  48. String password = req.getParameter("password");
  49. String email = req.getParameter("email");
  50. String code = req.getParameter("code");
  51. // 2、检查 验证码是否正确 === 写死,要求验证码为:abcde
  52. if ("abcde".equalsIgnoreCase(code)) {
  53. // 3、检查 用户名是否可用
  54. if (userService.existsUsername(username)) {
  55. System.out.println("用户名[" + username + "]已存在!");
  56. // 把回显信息,保存到 Request 域中
  57. req.setAttribute("msg", "用户名已存在!!");
  58. req.setAttribute("username", username);
  59. req.setAttribute("email", email);
  60. // 跳回注册页面
  61. req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
  62. } else {
  63. // 可用
  64. // 调用 Sservice 保存到数据库
  65. userService.registUser(new User(null, username, password, email));
  66. //
  67. // 跳到注册成功页面 regist_success.jsp
  68. req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req, resp);
  69. }
  70. } else {
  71. // 把回显信息,保存到 Request 域中
  72. req.setAttribute("msg", "验证码错误!!");
  73. req.setAttribute("username", username);
  74. req.setAttribute("email", email);
  75. System.out.println("验证码[" + code + "]错误");
  76. req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
  77. }
  78. }
  79. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  80. String action = req.getParameter("action");
  81. if ("login".equals(action)) {
  82. login(req, resp);
  83. } else if ("regist".equals(action)) {
  84. regist(req, resp);
  85. }
  86. }
  87. }

还要给 login.jsp 添加隐藏域和修改请求地址

10、Web项目延伸完善 - 图4

优化代码二:使用反射优化大量 else if 代码

  1. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  2. String action = req.getParameter("action");
  3. try {
  4. // 获取 action 业务鉴别字符串,获取相应的业务 方法反射对象
  5. Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class,
  6. HttpServletResponse.class);
  7. // System.out.println(method);
  8. // 调用目标业务 方法
  9. method.invoke(this, req, resp);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }

代码优化三:抽取 BaseServlet 程序

10、Web项目延伸完善 - 图5

BaseServlet 程序代码:

  1. package com.chang.web;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.http.HttpServlet;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.IOException;
  7. import java.lang.reflect.Method;
  8. public abstract class BaseServlet extends HttpServlet {
  9. @Override
  10. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  11. doPost(req, resp);
  12. }
  13. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  14. req.setCharacterEncoding("UTF-8");
  15. String action = req.getParameter("action");
  16. try {
  17. // 获取action业务鉴别字符串,获取相应的业务 方法反射对象
  18. Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
  19. // System.out.println(method);
  20. // 调用目标业务 方法
  21. method.invoke(this, req, resp);
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

修改 UserServlet 程序继承 BaseServlet 程序

5、数据的封装和抽取 BeanUtils 的使用

BeanUtils 工具类,它可以一次性的把所有请求的参数注入到 JavaBean 中。

BeanUtils 工具类,经常用于把 Map 中的值注入到 JavaBean 中,或者是对象属性值的拷贝操作。

BeanUtils 它不是 Jdk 的类。而是第三方的工具类。所以需要导包。

  1. 导入需要的 jar 包:
    commons-beanutils-1.8.0.jar
    commons-logging-1.1.1.jar
  2. 编写 WebUtils 工具类使用:
    WebUtils 工具类
  1. package com.chang.utils;
  2. import org.apache.commons.beanutils.BeanUtils;
  3. import java.util.Map;
  4. public class WebUtils {
  5. /**
  6. * 把Map中的值注入到对应的JavaBean属性中。
  7. * @param value
  8. * @param bean
  9. */
  10. public static <T> T copyParamToBean( Map value , T bean ){
  11. try {
  12. System.out.println("注入之前:" + bean);
  13. /**
  14. * 把所有请求的参数都注入到user对象中
  15. */
  16. BeanUtils.populate(bean, value);
  17. System.out.println("注入之后:" + bean);
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. return bean;
  22. }
  23. }
  1. //获取请求参数并封装成为User对象
  2. User user = WebUtils.copyParamToBean(req.getParameterMap(), new User());

6、使用 EL 表达式修改表单回显

10、Web项目延伸完善 - 图6

7、MVC概念

MVC 全称:Model 模型、 View 视图、 Controller 控制器。

MVC 最早出现在 JavaEE 三层中的 Web 层,它可以有效的指导 Web 层的代码如何有效分离,单独工作。

View 视图:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工合作—— JSP/HTML。

Controller 控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个“调度者”的角色——Servlet。 转到某个页面。或者是重定向到某个页面。

Model 模型:将与业务逻辑相关的数据封装为具体的 JavaBean 类,其中不掺杂任何与数据处理相关的代码—— JavaBean/domain/entity/pojo。

MVC 是一种思想。MVC 的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了降低耦合度),方便后期升级和维护。

10、Web项目延伸完善 - 图7

8、图书模块

8.1、编写图书模块的数据库表

  1. create table t_book(
  2. `id` int primary key auto_increment,
  3. `name` varchar(100),
  4. `price` decimal(11,2),
  5. `author` varchar(100),
  6. `sales` int,
  7. `stock` int,
  8. `img_path` varchar(200)
  9. );
  10. ## 插入初始化测试数据
  11. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  12. values(null , 'java 从入门到放弃' , '国哥' , 80 , 9999 , 9 , 'static/img/default.jpg');
  13. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  14. values(null , '数据结构与算法' , '严敏君' , 78.5 , 6 , 13 , 'static/img/default.jpg');
  15. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  16. values(null , '怎样成功' , '龙伍' , 68, 99999 , 52 , 'static/img/default.jpg');
  17. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  18. values(null , '木虚肉盖饭' , '小胖' , 16, 1000 , 50 , 'static/img/default.jpg');
  19. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  20. values(null , 'C++编程思想' , '刚哥' , 45.5 , 14 , 95 , 'static/img/default.jpg');
  21. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  22. values(null , '蛋炒饭' , '周星星' , 9.9, 12 , 53 , 'static/img/default.jpg');
  23. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  24. values(null , '赌神' , '龙伍' , 66.5, 125 , 535 , 'static/img/default.jpg');
  25. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  26. values(null , 'Java 编程思想' , '阳哥' , 99.5 , 47 , 36 , 'static/img/default.jpg');
  27. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  28. values(null , 'JavaScript 从入门到精通' , '婷姐' , 9.9 , 85 , 95 , 'static/img/default.jpg');
  29. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  30. values(null , 'cocos2d-x 游戏编程入门' , '国哥' , 49, 52 , 62 , 'static/img/default.jpg');
  31. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  32. values(null , 'C 语言程序设计' , '谭浩强' , 28 , 52 , 74 , 'static/img/default.jpg');
  33. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  34. values(null , 'Lua 语言程序设计' , '雷丰阳' , 51.5 , 48 , 82 , 'static/img/default.jpg');
  35. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  36. values(null , '西游记' , '罗贯中' , 12, 19 , 9999 , 'static/img/default.jpg');
  37. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  38. values(null , '水浒传' , '华仔' , 33.05 , 22 , 88 , 'static/img/default.jpg');
  39. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  40. values(null , '操作系统原理' , '刘优' , 133.05 , 122 , 188 , 'static/img/default.jpg');
  41. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  42. values(null , '数据结构 java 版' , '封大神' , 173.15 , 21 , 81 , 'static/img/default.jpg');
  43. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  44. values(null , 'UNIX 高级环境编程' , '乐天' , 99.15 , 210 , 810 , 'static/img/default.jpg');
  45. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  46. values(null , 'javaScript 高级编程' , '国哥' , 69.15 , 210 , 810 , 'static/img/default.jpg');
  47. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  48. values(null , '大话设计模式' , '国哥' , 89.15 , 20 , 10 , 'static/img/default.jpg');
  49. insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
  50. values(null , '人月神话' , '刚哥' , 88.15 , 20 , 80 , 'static/img/default.jpg');
  51. ## 查看表内容
  52. select id,name,author,price,sales,stock,img_path from t_book;

8.2、编写图书模块的JavaBean

  1. public class Book {
  2. private Integer id;
  3. private String name;
  4. private String author;
  5. private BigDecimal price;
  6. private Integer sales;
  7. private Integer stock;
  8. private String imgPath = "static/img/default.jpg";

8.3、编写图书模块的Dao和测试Dao

BookDao接口类

  1. package com.chang.dao;
  2. import com.chang.pojo.Book;
  3. import java.util.List;
  4. public interface BookDao {
  5. public int addBook(Book book);
  6. public int deleteBookById(Integer id);
  7. public int updateBook(Book book);
  8. public Book queryBookById(Integer id);
  9. public List<Book> queryBooks();
  10. Integer queryForPageTotalCount();
  11. List<Book> queryForPageItems(int begin, int pageSize);
  12. Integer queryForPageTotalCountByPrice(int min, int max);
  13. List<Book> queryForPageItemsByPrice(int begin, int pageSize, int min, int max);
  14. }

BookDaoImpl 实现类

  1. package com.chang.dao.impl;
  2. import com.chang.dao.BookDao;
  3. import com.chang.pojo.Book;
  4. import java.util.List;
  5. public class BookDaoImpl extends BaseDao implements BookDao {
  6. @Override
  7. public int addBook(Book book) {
  8. String sql = "insert into t_book(`name`,`author`,`price`,`sales`,`stock`,`img_path`) values(?,?,?,?,?,?)";
  9. return update(sql, book.getName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImgPath());
  10. }
  11. @Override
  12. public int deleteBookById(Integer id) {
  13. String sql = "delete from t_book where id = ?";
  14. return update(sql, id);
  15. }
  16. @Override
  17. public int updateBook(Book book) {
  18. String sql = "update t_book set `name`=?,`author`=?,`price`=?,`sales`=?,`stock`=?,`img_path`=? where id = ?";
  19. return update(sql,book.getName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImgPath(),book.getId());
  20. }
  21. @Override
  22. public Book queryBookById(Integer id) {
  23. String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imgPath from t_book where id = ?";
  24. return queryForOne(Book.class, sql,id);
  25. }
  26. @Override
  27. public List<Book> queryBooks() {
  28. String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imgPath from t_book";
  29. return queryForList(Book.class, sql);
  30. }
  31. @Override
  32. public Integer queryForPageTotalCount() {
  33. String sql = "select count(*) from t_book";
  34. Number count = (Number)queryForStringValue(sql);
  35. return count.intValue();
  36. }
  37. @Override
  38. public List<Book> queryForPageItems(int begin, int pageSize) {
  39. String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imgPath from t_book limit ?,?";
  40. return queryForList(Book.class,sql,begin,pageSize);
  41. }
  42. @Override
  43. public Integer queryForPageTotalCountByPrice(int min, int max) {
  44. String sql = "select count(*) from t_book where price between ? and ?";
  45. // Number count = (Number) queryForSingleValue(sql,min,max);
  46. Number count = (Number)queryForStringValue(sql,min,max);
  47. return count.intValue();
  48. }
  49. @Override
  50. public List<Book> queryForPageItemsByPrice(int begin, int pageSize, int min, int max) {
  51. String sql = "select `id`,`name`,`author`,`price`,`sales`,`stock`,`img_path` imgPath from t_book where price between ? and ? order by price limit ?,?";
  52. return queryForList(Book.class,sql,min,max,begin,pageSize);
  53. }
  54. }

BookDao测试类

  1. package com.chang.test;
  2. import com.chang.dao.BookDao;
  3. import com.chang.dao.impl.BookDaoImpl;
  4. import com.chang.pojo.Book;
  5. import com.chang.pojo.Page;
  6. import org.junit.Test;
  7. import java.math.BigDecimal;
  8. import static org.junit.Assert.*;
  9. public class BookDaoTest {
  10. private BookDao bookDao=new BookDaoImpl();
  11. @Test
  12. public void addBook() {
  13. bookDao.addBook(new Book(null,"天气很好!", "191125", new BigDecimal(9999),1100000,0,null));
  14. }
  15. @Test
  16. public void deleteBookById() {
  17. bookDao.deleteBookById(21);
  18. }
  19. @Test
  20. public void updateBook() {
  21. bookDao.updateBook(new Book(21,"大家都可以这么帅!", "国哥", new BigDecimal(9999),1100000,0,null));
  22. }
  23. @Test
  24. public void queryBookById() {
  25. System.out.println( bookDao.queryBookById(21) );
  26. }
  27. @Test
  28. public void queryBooks() {
  29. for (Book queryBook : bookDao.queryBooks()) {
  30. System.out.println(queryBook);
  31. }
  32. }
  33. @Test
  34. public void queryForPageTotalCount() {
  35. System.out.println( bookDao.queryForPageTotalCount() );
  36. }
  37. @Test
  38. public void queryForPageTotalCountByPrice() {
  39. System.out.println( bookDao.queryForPageTotalCountByPrice(10, 50) );
  40. }
  41. @Test
  42. public void queryForPageItems() {
  43. for (Book book : bookDao.queryForPageItems(8, Page.PAGE_SIZE)) {
  44. System.out.println(book);
  45. }
  46. }
  47. @Test
  48. public void queryForPageItemsByPrice() {
  49. for (Book book : bookDao.queryForPageItemsByPrice(0, Page.PAGE_SIZE,10,50)) {
  50. System.out.println(book);
  51. }
  52. }
  53. }

8.4、编写图书模块的Service和测试Service

BookService 接口类

  1. package com.chang.service;
  2. import com.chang.pojo.Book;
  3. import com.chang.pojo.Page;
  4. import java.util.List;
  5. public interface BookService {
  6. public void addBook(Book book);
  7. public void deleteBookById(Integer id);
  8. public void updateBook(Book book);
  9. public Book queryBookById(Integer id);
  10. public List<Book> queryBooks();
  11. Page<Book> page(int pageNo, int pageSize);
  12. Page<Book> pageByPrice(int pageNo, int pageSize, int min, int max);
  13. }

BookServiceImpl 实现类

  1. package com.chang.service.impl;
  2. import com.chang.dao.BookDao;
  3. import com.chang.dao.impl.BookDaoImpl;
  4. import com.chang.pojo.Book;
  5. import com.chang.pojo.Page;
  6. import com.chang.service.BookService;
  7. import java.util.List;
  8. public class BookServiceImpl implements BookService {
  9. private BookDao bookDao = new BookDaoImpl();
  10. @Override
  11. public void addBook(Book book) {
  12. bookDao.addBook(book);
  13. }
  14. @Override
  15. public void deleteBookById(Integer id) {
  16. bookDao.deleteBookById(id);
  17. }
  18. @Override
  19. public void updateBook(Book book) {
  20. bookDao.updateBook(book);
  21. }
  22. @Override
  23. public Book queryBookById(Integer id) {
  24. return bookDao.queryBookById(id);
  25. }
  26. @Override
  27. public List<Book> queryBooks() {
  28. return bookDao.queryBooks();
  29. }
  30. @Override
  31. public Page<Book> page(int pageNo, int pageSize) {
  32. Page<Book> page = new Page<Book>();
  33. // 设置每页显示的数量
  34. page.setPageSize(pageSize);
  35. // 求总记录数
  36. Integer pageTotalCount = bookDao.queryForPageTotalCount();
  37. // 设置总记录数
  38. page.setPageTotalCount(pageTotalCount);
  39. // 求总页码
  40. Integer pageTotal = pageTotalCount / pageSize;
  41. if (pageTotalCount % pageSize > 0) {
  42. pageTotal+=1;
  43. }
  44. // 设置总页码
  45. page.setPageTotal(pageTotal);
  46. // 设置当前页码
  47. page.setPageNo(pageNo);
  48. // 求当前页数据的开始索引
  49. int begin = (page.getPageNo() - 1) * pageSize;
  50. // 求当前页数据
  51. List<Book> items = bookDao.queryForPageItems(begin,pageSize);
  52. // 设置当前页数据
  53. page.setItems(items);
  54. return page;
  55. }
  56. @Override
  57. public Page<Book> pageByPrice(int pageNo, int pageSize, int min, int max) {
  58. Page<Book> page = new Page<Book>();
  59. // 设置每页显示的数量
  60. page.setPageSize(pageSize);
  61. // 求总记录数
  62. Integer pageTotalCount = bookDao.queryForPageTotalCountByPrice(min,max);
  63. // 设置总记录数
  64. page.setPageTotalCount(pageTotalCount);
  65. // 求总页码
  66. Integer pageTotal = pageTotalCount / pageSize;
  67. if (pageTotalCount % pageSize > 0) {
  68. pageTotal+=1;
  69. }
  70. // 设置总页码
  71. page.setPageTotal(pageTotal);
  72. // 设置当前页码
  73. page.setPageNo(pageNo);
  74. // 求当前页数据的开始索引
  75. int begin = (page.getPageNo() - 1) * pageSize;
  76. // 求当前页数据
  77. List<Book> items = bookDao.queryForPageItemsByPrice(begin,pageSize,min,max);
  78. // 设置当前页数据
  79. page.setItems(items);
  80. return page;
  81. }
  82. }

BookService 测试类

  1. package com.chang.test;
  2. import com.chang.pojo.Book;
  3. import com.chang.pojo.Page;
  4. import com.chang.service.BookService;
  5. import com.chang.service.impl.BookServiceImpl;
  6. import org.junit.Test;
  7. import java.math.BigDecimal;
  8. import static org.junit.Assert.*;
  9. public class BookServiceTest {
  10. private BookService bookService = new BookServiceImpl();
  11. @Test
  12. public void addBook() {
  13. bookService.addBook(new Book(null,"技术在手,天下我有!", "1125", new BigDecimal(1000000), 100000000, 0, null));
  14. }
  15. @Test
  16. public void deleteBookById() {
  17. bookService.deleteBookById(22);
  18. }
  19. @Test
  20. public void updateBook() {
  21. bookService.updateBook(new Book(22,"你好我好大家好", "1125", new BigDecimal(999999), 10, 111110, null));
  22. }
  23. @Test
  24. public void queryBookById() {
  25. System.out.println(bookService.queryBookById(22));
  26. }
  27. @Test
  28. public void queryBooks() {
  29. for (Book queryBook : bookService.queryBooks()) {
  30. System.out.println(queryBook);
  31. }
  32. }
  33. @Test
  34. public void page(){
  35. System.out.println(bookService.page(1, Page.PAGE_SIZE ));
  36. }
  37. @Test
  38. public void pageByPrice(){
  39. System.out.println(bookService.pageByPrice(1, Page.PAGE_SIZE,10,50 ));
  40. }
  41. }

8.5、编写图书模块的Web层和页面联调测试

8.5.1、图书列表功能的实现

10、Web项目延伸完善 - 图8

BookServlet 程序中添加 list 方法
  1. protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
  2. IOException {
  3. //1 通过 BookService 查询全部图书
  4. List<Book> books = bookService.queryBooks();
  5. //2 把全部图书保存到 Request 域中
  6. req.setAttribute("books", books);
  7. //3、请求转发到/pages/manager/book_manager.jsp 页面
  8. req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);
  9. }

修改【图书管理】请求地址

10、Web项目延伸完善 - 图9

jsp数据遍历输出
  1. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  2. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  3. <!DOCTYPE html>
  4. <html>
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>图书管理</title>
  8. <%-- 静态包含 base 标签、css 样式、jQuery 文件 --%>
  9. <%@ include file="/pages/common/head.jsp"%>
  10. </head>
  11. <body>
  12. <div id="header">
  13. <img class="logo_img" alt="" src="../../static/img/logo.gif" >
  14. <span class="wel_word">图书管理系统</span>
  15. <%-- 静态包含 manager 管理模块的菜单 --%>
  16. <%@include file="/pages/common/manager_menu.jsp"%>
  17. </div>
  18. <div id="main">
  19. <table>
  20. <tr>
  21. <td>名称</td>
  22. <td>价格</td>
  23. <td>作者</td>
  24. <td>销量</td>
  25. <td>库存</td>
  26. <td colspan="2">操作</td>
  27. </tr>
  28. <c:forEach items="${requestScope.books}" var="book">
  29. <tr>
  30. <td>${book.name}</td>
  31. <td>${book.price}</td>
  32. <td>${book.author}</td>
  33. <td>${book.sales}</td>
  34. <td>${book.stock}</td>
  35. <td><a href="book_edit.jsp">修改</a></td>
  36. <td><a href="#">删除</a></td>
  37. </tr>
  38. </c:forEach>
  39. <tr>
  40. <td></td>
  41. <td></td>
  42. <td></td>
  43. <td></td>
  44. <td></td>
  45. <td></td>
  46. <td><a href="book_edit.jsp">添加图书</a></td>
  47. </tr>
  48. </table>
  49. </div>
  50. <%--静态包含页脚内容--%>
  51. <%@include file="/pages/common/footer.jsp"%>
  52. </body>
  53. </html>

8.5.2、前后台的简单介绍

10、Web项目延伸完善 - 图10

8.5.3、添加图书功能的实现

10、Web项目延伸完善 - 图11

问题说明:表单重复提交

当用户提交完请求,浏览器会记录下最后一次请求的全部信息。当用户按下功能键 F5,就会发起浏览器记录的最后一次 请求。

因此不能使用请求转发,而应该使用重定向

BookServlet 程序中添加 add 方法
  1. protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
  2. IOException {
  3. // 1、获取请求的参数==封装成为 Book 对象
  4. Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
  5. // 2、调用 BookService.addBook()保存图书
  6. bookService.addBook(book);
  7. // 3、跳到图书列表页面
  8. // /manager/bookServlet?action=list
  9. // req.getRequestDispatcher("/manager/bookServlet?action=list").forward(req, resp);
  10. resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");
  11. }

修改 book_edit.jsp 页面
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>编辑图书</title>
  7. <%-- 静态包含 base 标签、css 样式、jQuery 文件 --%>
  8. <%@ include file="/pages/common/head.jsp"%>
  9. <style type="text/css">
  10. h1 {
  11. text-align: center;
  12. margin-top: 200px;
  13. }
  14. h1 a {
  15. color:red;
  16. }
  17. input {
  18. text-align: center;
  19. }
  20. </style>
  21. </head>
  22. <body>
  23. <div id="header">
  24. <img class="logo_img" alt="" src="../../static/img/logo.gif" >
  25. <span class="wel_word">编辑图书</span>
  26. <%-- 静态包含 manager 管理模块的菜单 --%>
  27. <%@include file="/pages/common/manager_menu.jsp"%>
  28. </div>
  29. <div id="main">
  30. <form action="manager/bookServlet" method="get">
  31. <input type="hidden" name="action" value="add" />
  32. <table>
  33. <tr>
  34. <td>名称</td>
  35. <td>价格</td>
  36. <td>作者</td>
  37. <td>销量</td>
  38. <td>库存</td>
  39. <td colspan="2">操作</td>
  40. </tr>
  41. <tr>
  42. <td><input name="name" type="text" value="时间简史"/></td>
  43. <td><input name="price" type="text" value="30.00"/></td>
  44. <td><input name="author" type="text" value="霍金"/></td>
  45. <td><input name="sales" type="text" value="200"/></td>
  46. <td><input name="stock" type="text" value="300"/></td>
  47. <td><input type="submit" value="提交"/></td>
  48. </tr>
  49. </table>
  50. </form>
  51. </div>
  52. <%--静态包含页脚内容--%>
  53. <%@include file="/pages/common/footer.jsp"%>
  54. </body>
  55. </html>

8.5.4、删除图书功能的实现

10、Web项目延伸完善 - 图12

BookServlet 程序中的 delete 方法
  1. protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  2. // 1、获取请求的参数 id,图书编程
  3. int id = WebUtils.parseInt(req.getParameter("id"), 0);
  4. // 2、调用 bookService.deleteBookById();删除图书
  5. bookService.deleteBookById(id);
  6. // 3、重定向回图书列表管理页面
  7. // /book/manager/bookServlet?action=list
  8. resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");
  9. }

给 WebUtils 工具类添加转换 int 类型的工具
  1. /**
  2. * 将字符串转换成为 int 类型的数据
  3. * @param strInt
  4. * @param defaultValue
  5. * @return
  6. */
  7. public static int parseInt(String strInt,int defaultValue) {
  8. try {
  9. return Integer.parseInt(strInt);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. return defaultValue;
  14. }

修改删除的连接地址

10、Web项目延伸完善 - 图13

给删除添加确认提示操作
  1. <script type="text/javascript">
  2. $(function () {
  3. // 给删除的 a 标签绑定单击事件,用于删除的确认提示操作
  4. $("a.deleteClass").click(function () {
  5. // 在事件的 function 函数中,有一个 this 对象。这个 this 对象,是当前正在响应事件的 dom 对象。
  6. /**
  7. * confirm 是确认提示框函数
  8. * 参数是它的提示内容
  9. * 它有两个按钮,一个确认,一个是取消。
  10. * 返回 true 表示点击了,确认,返回 false 表示点击取消。
  11. */
  12. return confirm("你确定要删除【" + $(this).parent().parent().find("td:first").text() + "】?");
  13. // return false// 阻止元素的默认行为===不提交请求
  14. });
  15. });
  16. </script>

8.5.5、修改图书功能的实现

10、Web项目延伸完善 - 图14

更新【修改】的请求地址

10、Web项目延伸完善 - 图15

BookServlet 程序中添加 getBook 方法
  1. protected void getBook(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  2. //1 获取请求的参数图书编号
  3. int id = WebUtils.parseInt(req.getParameter("id"), 0);
  4. //2 调用 bookService.queryBookById 查询图书
  5. Book book = bookService.queryBookById(id);
  6. //3 保存到图书到 Request 域中
  7. req.setAttribute("book", book) ;
  8. //4 请求转发到。pages/manager/book_edit.jsp 页面
  9. req.getRequestDispatcher("/pages/manager/book_edit.jsp").forward(req,resp);
  10. }

在 book_edit.jsp 页面中显示修改的数据
  1. <div id="main">
  2. <form action="manager/bookServlet" method="get">
  3. <input type="hidden" name="action" value="add" />
  4. <table>
  5. <tr>
  6. <td>名称</td>
  7. <td>价格</td>
  8. <td>作者</td>
  9. <td>销量</td>
  10. <td>库存</td>
  11. <td colspan="2">操作</td>
  12. </tr>
  13. <tr>
  14. <td><input name="name" type="text" value="${requestScope.book.name}"/></td>
  15. <td><input name="price" type="text" value="${requestScope.book.price}"/></td>
  16. <td><input name="author" type="text" value="${requestScope.book.author}"/></td>
  17. <td><input name="sales" type="text" value="${requestScope.book.sales}"/></td>
  18. <td><input name="stock" type="text" value="${requestScope.book.stock}"/></td>
  19. <td><input type="submit" value="提交"/></td>
  20. </tr>
  21. </table>
  22. </form>
  23. </div>

在 BookServlet 程序中添加 update 方法
  1. protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  2. // 1、获取请求的参数==封装成为 Book 对象
  3. Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
  4. // 2、调用 BookService.updateBook( book );修改图书
  5. bookService.updateBook(book);
  6. // 3、重定向回图书列表管理页面
  7. // 地址:/工程名/manager/bookServlet?action=list
  8. resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");
  9. }

解决 book_edit.jsp 页面,即要实现添加,又要实现修改操作

修改的URL中是有id的,所以可以进行区分

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>编辑图书</title>
  7. <%-- 静态包含 base标签、css样式、jQuery文件 --%>
  8. <%@ include file="/pages/common/head.jsp"%>
  9. <style type="text/css">
  10. h1 {
  11. text-align: center;
  12. margin-top: 200px;
  13. }
  14. h1 a {
  15. color:red;
  16. }
  17. input {
  18. text-align: center;
  19. }
  20. </style>
  21. </head>
  22. <body>
  23. <div id="header">
  24. <img class="logo_img" alt="" src="../../static/img/logo.gif" >
  25. <span class="wel_word">编辑图书</span>
  26. <%-- 静态包含 manager管理模块的菜单 --%>
  27. <%@include file="/pages/common/manager_menu.jsp"%>
  28. </div>
  29. <div id="main">
  30. <form action="manager/bookServlet" method="post">
  31. <input type="hidden" name="action" value="${ empty param.id ? "add" : "update" }">
  32. <%-- <input type="hidden" name="id" value="${ requestScope.book.id==null ? "add" : "update" }">--%>
  33. <input type="hidden" name="id" value="${ requestScope.book.id }">
  34. <table>
  35. <tr>
  36. <td>名称</td>
  37. <td>价格</td>
  38. <td>作者</td>
  39. <td>销量</td>
  40. <td>库存</td>
  41. <td colspan="2">操作</td>
  42. </tr>
  43. <tr>
  44. <td><input name="name" type="text" value="${requestScope.book.name}"/></td>
  45. <td><input name="price" type="text" value="${requestScope.book.price}"/></td>
  46. <td><input name="author" type="text" value="${requestScope.book.author}"/></td>
  47. <td><input name="sales" type="text" value="${requestScope.book.sales}"/></td>
  48. <td><input name="stock" type="text" value="${requestScope.book.stock}"/></td>
  49. <td><input type="submit" value="提交"/></td>
  50. </tr>
  51. </table>
  52. </form>
  53. </div>
  54. <%--静态包含页脚内容--%>
  55. <%@include file="/pages/common/footer.jsp"%>
  56. </body>
  57. </html>

10、Web项目延伸完善 - 图16

9、图书分页

10、Web项目延伸完善 - 图17

9.1、分页模型 Page 的抽取

当前页数,总页数,总记录数, 当前页数据,每页记录数

  1. /**
  2. * Page 是分页的模型对象
  3. * @param <T> 是具体的模块的 javaBean 类
  4. */
  5. public class Page<T> {
  6. public static final Integer PAGE_SIZE = 4;
  7. // 当前页码
  8. private Integer pageNo;
  9. // 总页码
  10. private Integer pageTotal;
  11. // 当前页显示数量
  12. private Integer pageSize = PAGE_SIZE;
  13. // 总记录数
  14. private Integer pageTotalCount;
  15. // 当前页数据
  16. private List<T> items

9.2、分页的初步实现

BookDao 代码

  1. @Override
  2. public Integer queryForPageTotalCount() {
  3. String sql = "select count(*) from t_book";
  4. Number count = (Number) queryForSingleValue(sql);
  5. return count.intValue();
  6. }
  7. @Override
  8. public List<Book> queryForPageItems(int begin, int pageSize) {
  9. String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imgPath from t_book limit ?,?";
  10. return queryForList(Book.class,sql,begin,pageSize);
  11. }

BookService 代码

  1. @Override
  2. public Page<Book> page(int pageNo, int pageSize) {
  3. Page<Book> page = new Page<Book>();
  4. // 设置当前页码
  5. page.setPageNo(pageNo);
  6. // 设置每页显示的数量
  7. page.setPageSize(pageSize);
  8. // 求总记录数
  9. Integer pageTotalCount = bookDao.queryForPageTotalCount();
  10. // 设置总记录数
  11. page.setPageTotalCount(pageTotalCount);
  12. // 求总页码
  13. Integer pageTotal = pageTotalCount / pageSize;
  14. if (pageTotalCount % pageSize > 0) {
  15. pageTotal+=1;
  16. }
  17. // 设置总页码
  18. page.setPageTotal(pageTotal);
  19. // 求当前页数据的开始索引
  20. int begin = (page.getPageNo() - 1) * pageSize;
  21. // 求当前页数据
  22. List<Book> items = bookDao.queryForPageItems(begin,pageSize);
  23. // 设置当前页数据
  24. page.setItems(items);
  25. return page;
  26. }

BookServlet 代码

  1. /**
  2. * 处理分页功能
  3. * @param req
  4. * @param resp
  5. * @throws ServletException
  6. * @throws IOException
  7. */
  8. protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
  9. IOException {
  10. //1 获取请求的参数 pageNo 和 pageSize
  11. int pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 1);
  12. int pageSize = WebUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);
  13. //2 调用 BookService.page(pageNo,pageSize):Page 对象
  14. Page<Book> page = bookService.page(pageNo,pageSize);
  15. //3 保存 Page 对象到 Request 域中
  16. req.setAttribute("page",page);
  17. //4 请求转发到 pages/manager/book_manager.jsp 页面
  18. req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);
  19. }

manager_menu.jsp 中“图书管理”请求地址的修改

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <div>
  3. <a href="manager/bookServlet?action=page">图书管理</a>
  4. <a href="order_manager.jsp">订单管理</a>
  5. <a href="index.jsp">返回商城</a>
  6. </div>

book_manager.jsp 修改

  1. %@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  2. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  3. <!DOCTYPE html>
  4. <html>
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>图书管理</title>
  8. <%-- 静态包含 base 标签、css 样式、jQuery 文件 --%>
  9. <%@ include file="/pages/common/head.jsp"%>
  10. <script type="text/javascript">
  11. $(function () {
  12. // 给删除的 a 标签绑定单击事件,用于删除的确认提示操作
  13. $("a.deleteClass").click(function () {
  14. // 在事件的 function 函数中,有一个 this 对象。这个 this 对象,是当前正在响应事件的 dom 对象。
  15. /**
  16. * confirm 是确认提示框函数
  17. * 参数是它的提示内容
  18. * 它有两个按钮,一个确认,一个是取消。
  19. * 返回 true 表示点击了,确认,返回 false 表示点击取消。
  20. */
  21. return confirm("你确定要删除【" + $(this).parent().parent().find("td:first").text() + "】?");
  22. // return false// 阻止元素的默认行为===不提交请求
  23. });
  24. });
  25. </script>
  26. </head>
  27. <body>
  28. <div id="header">
  29. <img class="logo_img" alt="" src="../../static/img/logo.gif" >
  30. <span class="wel_word">图书管理系统</span>
  31. <%-- 静态包含 manager 管理模块的菜单 --%>
  32. <%@include file="/pages/common/manager_menu.jsp"%>
  33. </div>
  34. <div id="main">
  35. <table>
  36. <tr>
  37. <td>名称</td>
  38. <td>价格</td>
  39. <td>作者</td>
  40. <td>销量</td>
  41. <td>库存</td>
  42. <td colspan="2">操作</td>
  43. </tr>
  44. <c:forEach items="${requestScope.page.items}" var="book">
  45. <tr>
  46. <td>${book.name}</td>
  47. <td>${book.price}</td>
  48. <td>${book.author}</td>
  49. <td>${book.sales}</td>
  50. <td>${book.stock}</td>
  51. <td><a href="manager/bookServlet?action=getBook&id=${book.id}">修改</a></td>
  52. <td><a class="deleteClass" href="manager/bookServlet?action=delete&id=${book.id}">删
  53. 除</a></td>
  54. </tr>
  55. </c:forEach>
  56. <tr>
  57. <td></td>
  58. <td></td>
  59. <td></td>
  60. <td></td>
  61. <td></td>
  62. <td></td>
  63. <td><a href="pages/manager/book_edit.jsp">添加图书</a></td>
  64. </tr>
  65. </table>
  66. <div id="page_nav">
  67. <a href="#">首页</a>
  68. <a href="#">上一页</a>
  69. <a href="#">3</a>
  70. ${ requestScope.page.pageNo }】
  71. <a href="#">5</a>
  72. <a href="#">下一页</a>
  73. <a href="#">末页</a>
  74. ${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录
  75. 到第<input value="4" name="pn" id="pn_input"/>页
  76. <input type="button" value="确定">
  77. </div>
  78. </div>
  79. <%--静态包含页脚内容--%>
  80. <%@include file="/pages/common/footer.jsp"%>
  81. </body>
  82. </html>

9.3、首页、上一页、下一页、末页实现

  1. <div id="page_nav">
  2. <%--大于首页,才显示--%>
  3. <c:if test="${requestScope.page.pageNo > 1}">
  4. <a href="manager/bookServlet?action=page&pageNo=1">首页</a>
  5. <a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageNo-1}">上一页</a>
  6. </c:if>
  7. <a href="#">3</a>
  8. 【${ requestScope.page.pageNo }】
  9. <a href="#">5</a>
  10. <%-- 如果已经 是最后一页,则不显示下一页,末页 --%>
  11. <c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}">
  12. <a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageNo+1}">下一页</a>
  13. <a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageTotal}">末页</a>
  14. </c:if>
  15. 共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录
  16. 到第<input value="4" name="pn" id="pn_input"/>
  17. <input type="button" value="确定">
  18. </div>

9.4、分页模块中跳转到指定页数功能实现

  1. <div id="page_nav">
  2. <%--大于首页,才显示--%>
  3. <c:if test="${requestScope.page.pageNo > 1}">
  4. <a href="manager/bookServlet?action=page&pageNo=1">首页</a>
  5. <a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageNo-1}">上一页</a>
  6. </c:if>
  7. <a href="#">3</a>
  8. 【${ requestScope.page.pageNo }】
  9. <a href="#">5</a>
  10. <%-- 如果已经 是最后一页,则不显示下一页,末页 --%>
  11. <c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}">
  12. <a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageNo+1}">下一页</a>
  13. <a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageTotal}">末页</a>
  14. </c:if>
  15. 共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录
  16. 到第<input value="${param.pageNo}" name="pn" id="pn_input"/>
  17. <input id="searchPageBtn" type="button" value="确定">
  18. <script type="text/javascript">
  19. $(function () {
  20. // 跳到指定的页码
  21. $("#searchPageBtn").click(function () {
  22. var pageNo = $("#pn_input").val();
  23. <%--var pageTotal = ${requestScope.page.pageTotal};--%>
  24. <%--alert(pageTotal);--%>
  25. // javaScript 语言中提供了一个 location 地址栏对象
  26. // 它有一个属性叫 href.它可以获取浏览器地址栏中的地址
  27. // href 属性可读,可写
  28. location.href = "${pageScope.basePath}manager/bookServlet?action=page&pageNo=" + pageNo;
  29. });
  30. });
  31. </script>
  32. </div>

9.5、Page 对象中的修改

  1. public void setPageNo(Integer pageNo) {
  2. /* 数据边界的有效检查 */
  3. if (pageNo < 1) {
  4. pageNo = 1;
  5. }
  6. if (pageNo > pageTotal) {
  7. pageNo = pageTotal;
  8. }
  9. this.pageNo = pageNo;
  10. }

9.6、BookService 中 page 方法的修改

  1. @Override
  2. public Page<Book> page(int pageNo, int pageSize) {
  3. Page<Book> page = new Page<Book>();
  4. // 设置每页显示的数量
  5. page.setPageSize(pageSize);
  6. // 求总记录数
  7. Integer pageTotalCount = bookDao.queryForPageTotalCount();
  8. // 设置总记录数
  9. page.setPageTotalCount(pageTotalCount);
  10. // 求总页码
  11. Integer pageTotal = pageTotalCount / pageSize;
  12. if (pageTotalCount % pageSize > 0) {
  13. pageTotal+=1;
  14. }
  15. // 设置总页码
  16. page.setPageTotal(pageTotal);
  17. // 设置当前页码
  18. page.setPageNo(pageNo);
  19. // 求当前页数据的开始索引
  20. int begin = (page.getPageNo() - 1) * pageSize;
  21. // 求当前页数据
  22. List<Book> items = bookDao.queryForPageItems(begin,pageSize);
  23. // 设置当前页数据
  24. page.setItems(items);
  25. return page;
  26. }

9.7、页码跳转

分页模块中,页码 1,2,【3】,4,5 的显示,要显示 5 个页 码,并且页码可以点击跳转。

需求:显示 5 个连续的页码,而且当前页码在中间。除了当前页码之外,每个页码都可以点击跳到指定页

情况 1:如果总页码小于等于 5 的情况,页码的范围是:1-总页码

1 页 1

2 页 1,2

3 页 1,2,3

4 页 1,2,3,4

5 页 1,2,3,4,5

情况 2:总页码大于 5 的情况。假设一共 10 页

小情况 1:当前页码为前面 3 个:1,2,3 的情况,页码范围是:1-5.

【1】2,3,4,5

1,【2】3,4,5

1,2,【3】4,5

小情况 2:当前页码为最后 3 个,8,9,10,页码范围是:总页码减 4 - 总页码

6,7【8】9,10

6,7,8【9】10

6,7,8,9【10】

小情况 3:4,5,6,7,页码范围是:当前页码减 2 - 当前页码加 2

2,3,4,5,6

3,4,5,6,7

4,5,6,7,8

5,6,7,8,9

  1. <%--页码输出的开始--%>
  2. <c:choose>
  3. <%--情况 1:如果总页码小于等于 5 的情况,页码的范围是:1-总页码--%>
  4. <c:when test="${ requestScope.page.pageTotal <= 5 }">
  5. <c:set var="begin" value="1"/>
  6. <c:set var="end" value="${requestScope.page.pageTotal}"/>
  7. </c:when>
  8. <%--情况 2:总页码大于 5 的情况--%>
  9. <c:when test="${requestScope.page.pageTotal > 5}">
  10. <c:choose>
  11. <%--小情况 1:当前页码为前面 3 个:123 的情况,页码范围是:1-5.--%>
  12. <c:when test="${requestScope.page.pageNo <= 3}">
  13. <c:set var="begin" value="1"/>
  14. <c:set var="end" value="5"/>
  15. </c:when>
  16. <%--小情况 2:当前页码为最后 3 个,8910,页码范围是:总页码减 4 - 总页码--%>
  17. <c:when test="${requestScope.page.pageNo > requestScope.page.pageTotal-3}">
  18. <c:set var="begin" value="${requestScope.page.pageTotal-4}"/>
  19. <c:set var="end" value="${requestScope.page.pageTotal}"/>
  20. </c:when>
  21. <%--小情况 34567,页码范围是:当前页码减 2 - 当前页码加 2--%>
  22. <c:otherwise>
  23. <c:set var="begin" value="${requestScope.page.pageNo-2}"/>
  24. <c:set var="end" value="${requestScope.page.pageNo+2}"/>
  25. </c:otherwise>
  26. </c:choose>
  27. </c:when>
  28. </c:choose>
  29. <c:forEach begin="${begin}" end="${end}" var="i">
  30. <c:if test="${i == requestScope.page.pageNo}">
  31. 【${i}】
  32. </c:if>
  33. <c:if test="${i != requestScope.page.pageNo}">
  34. <a href="manager/bookServlet?action=page&pageNo=${i}">${i}</a>
  35. </c:if>
  36. </c:forEach>
  37. <%--页码输出的结束--%>

9.8、修改分页后,增加,删除,修改图书信息的回显页面

以修改图书为示例:

1、在修改的请求地址上追加当前页码参数

10、Web项目延伸完善 - 图18

2、在 book_edit.jsp 页面中使用隐藏域记录下 pageNo 参数

10、Web项目延伸完善 - 图19

3、在服务器重定向的时候,获取当前页码追加上进行跳转

  1. protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  2. // 1、获取请求的参数==封装成为 Book 对象
  3. Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
  4. // 2、调用 BookService.updateBook( book );修改图书
  5. bookService.updateBook(book);
  6. // 3、重定向回图书列表管理页面
  7. // 地址:/工程名/manager/bookServlet?action=list
  8. resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo=" +
  9. req.getParameter("pageNo"));
  10. }

10、首页 index.jsp 的跳转

10、Web项目延伸完善 - 图20

index.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%--只负责请求转发--%>
  3. <jsp:forward page="/client/bookServlet?action=page"></jsp:forward>

web/pages/client/index.jsp

  1. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  2. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  3. <!DOCTYPE html>
  4. <html>
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>书城首页</title>
  8. <%-- 静态包含 base标签、css样式、jQuery文件 --%>
  9. <%@ include file="/pages/common/head.jsp"%>
  10. </head>
  11. <body>
  12. <div id="header">
  13. <img class="logo_img" alt="" src="static/img/logo.gif" >
  14. <span class="wel_word">网上书城</span>
  15. <div>
  16. <a href="pages/user/login.jsp">登录</a> |
  17. <a href="pages/user/regist.jsp">注册</a> &nbsp;&nbsp;
  18. <a href="pages/cart/cart.jsp">购物车</a>
  19. <a href="pages/manager/manager.jsp">后台管理</a>
  20. </div>
  21. </div>
  22. <div id="main">
  23. <div id="book">
  24. <div class="book_cond">
  25. <form action="client/bookServlet" method="get">
  26. <input type="hidden" name="action" value="pageByPrice">
  27. 价格:<input id="min" type="text" name="min" value="${param.min}"> -
  28. <input id="max" type="text" name="max" value="${param.max}">
  29. <input type="submit" value="查询" />
  30. </form>
  31. </div>
  32. <div style="text-align: center">
  33. <span>您的购物车中有3件商品</span>
  34. <div>
  35. 您刚刚将<span style="color: red">时间简史</span>加入到了购物车中
  36. </div>
  37. </div>
  38. <c:forEach items="${requestScope.page.items}" var="book">
  39. <div class="b_list">
  40. <div class="img_div">
  41. <img class="book_img" alt="" src="${book.imgPath}" />
  42. </div>
  43. <div class="book_info">
  44. <div class="book_name">
  45. <span class="sp1">书名:</span>
  46. <span class="sp2">${book.name}</span>
  47. </div>
  48. <div class="book_author">
  49. <span class="sp1">作者:</span>
  50. <span class="sp2">${book.author}</span>
  51. </div>
  52. <div class="book_price">
  53. <span class="sp1">价格:</span>
  54. <span class="sp2">¥${book.price}</span>
  55. </div>
  56. <div class="book_sales">
  57. <span class="sp1">销量:</span>
  58. <span class="sp2">${book.sales}</span>
  59. </div>
  60. <div class="book_amount">
  61. <span class="sp1">库存:</span>
  62. <span class="sp2">${book.stock}</span>
  63. </div>
  64. <div class="book_add">
  65. <button>加入购物车</button>
  66. </div>
  67. </div>
  68. </div>
  69. </c:forEach>
  70. </div>
  71. <%--静态包含分页条--%>
  72. <%@include file="/pages/common/page_nav.jsp"%>
  73. </div>
  74. <%--静态包含页脚内容--%>
  75. <%@include file="/pages/common/footer.jsp"%>
  76. </body>
  77. </html>

11、分页条的抽取

11.1、抽取分页条中请求地址为 url 变量

在 page 对象中添加 url 属性

  1. /**
  2. * Page 是分页的模型对象
  3. * @param <T> 是具体的模块的 javaBean 类
  4. */
  5. public class Page<T> {
  6. public static final Integer PAGE_SIZE = 4;
  7. // 当前页码
  8. private Integer pageNo;
  9. // 总页码
  10. private Integer pageTotal;
  11. // 当前页显示数量
  12. private Integer pageSize = PAGE_SIZE;
  13. // 总记录数
  14. private Integer pageTotalCount;
  15. // 当前页数据
  16. private List<T> items;
  17. // 分页条的请求地址
  18. private String url

11.2、在 Servlet 程序的 page 分页方法中设置 url 的分页请求地址

10、Web项目延伸完善 - 图21

11.3、修改分页条中请求地址为 url 变量输出,并抽取一个单独的 jsp 页面

web/common/page_nav.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%--分页条的开始--%>
  3. <div id="page_nav">
  4. <%--大于首页,才显示--%>
  5. <c:if test="${requestScope.page.pageNo > 1}">
  6. <a href="${ requestScope.page.url }&pageNo=1">首页</a>
  7. <a href="${ requestScope.page.url }&pageNo=${requestScope.page.pageNo-1}">上一页</a>
  8. </c:if>
  9. <%--页码输出的开始--%>
  10. <c:choose>
  11. <%--情况1:如果总页码小于等于5的情况,页码的范围是:1-总页码--%>
  12. <c:when test="${ requestScope.page.pageTotal <= 5 }">
  13. <c:set var="begin" value="1"/>
  14. <c:set var="end" value="${requestScope.page.pageTotal}"/>
  15. </c:when>
  16. <%--情况2:总页码大于5的情况--%>
  17. <c:when test="${requestScope.page.pageTotal > 5}">
  18. <c:choose>
  19. <%--小情况1:当前页码为前面3个:123的情况,页码范围是:1-5.--%>
  20. <c:when test="${requestScope.page.pageNo <= 3}">
  21. <c:set var="begin" value="1"/>
  22. <c:set var="end" value="5"/>
  23. </c:when>
  24. <%--小情况2:当前页码为最后3个,8910,页码范围是:总页码减4 - 总页码--%>
  25. <c:when test="${requestScope.page.pageNo > requestScope.page.pageTotal-3}">
  26. <c:set var="begin" value="${requestScope.page.pageTotal-4}"/>
  27. <c:set var="end" value="${requestScope.page.pageTotal}"/>
  28. </c:when>
  29. <%--小情况34567,页码范围是:当前页码减2 - 当前页码加2--%>
  30. <c:otherwise>
  31. <c:set var="begin" value="${requestScope.page.pageNo-2}"/>
  32. <c:set var="end" value="${requestScope.page.pageNo+2}"/>
  33. </c:otherwise>
  34. </c:choose>
  35. </c:when>
  36. </c:choose>
  37. <c:forEach begin="${begin}" end="${end}" var="i">
  38. <c:if test="${i == requestScope.page.pageNo}">
  39. 【${i}】
  40. </c:if>
  41. <c:if test="${i != requestScope.page.pageNo}">
  42. <a href="${ requestScope.page.url }&pageNo=${i}">${i}</a>
  43. </c:if>
  44. </c:forEach>
  45. <%--页码输出的结束--%>
  46. <%-- 如果已经 是最后一页,则不显示下一页,末页 --%>
  47. <c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}">
  48. <a href="${ requestScope.page.url }&pageNo=${requestScope.page.pageNo+1}">下一页</a>
  49. <a href="${ requestScope.page.url }&pageNo=${requestScope.page.pageTotal}">末页</a>
  50. </c:if>
  51. 共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录
  52. 到第<input value="${param.pageNo}" name="pn" id="pn_input"/>
  53. <input id="searchPageBtn" type="button" value="确定">
  54. <script type="text/javascript">
  55. $(function () {
  56. // 跳到指定的页码
  57. $("#searchPageBtn").click(function () {
  58. var pageNo = $("#pn_input").val();
  59. <%--var pageTotal = ${requestScope.page.pageTotal};--%>
  60. <%--alert(pageTotal);--%>
  61. // javaScript语言中提供了一个location地址栏对象
  62. // 它有一个属性叫href.它可以获取浏览器地址栏中的地址
  63. // href属性可读,可写
  64. location.href = "${pageScope.basePath}${ requestScope.page.url }&pageNo=" + pageNo;
  65. });
  66. });
  67. </script>
  68. </div>
  69. <%--分页条的结束--%>

12、首页价格搜索

10、Web项目延伸完善 - 图22