- 1、Html转Jsp实现动态化
- 2、抽取页面相同内容(用静态注入)
- 3、登录、注册错误提示,及表单回显
- 4、BaseServlet 的抽取
- 5、数据的封装和抽取 BeanUtils 的使用
- 6、使用 EL 表达式修改表单回显
- 7、MVC概念
- 8、图书模块
- 9、图书分页
- 10、首页 index.jsp 的跳转
- 11、分页条的抽取
- 12、首页价格搜索
1、Html转Jsp实现动态化
在 html 页面顶行添加 page 指令。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
修改文件后缀名为:.jsp
- 使用 IDEA 搜索替换.html 为.jsp(快捷键:Ctrl+Shift+R)

2、抽取页面相同内容(用静态注入)
将页面中相同且需要多次用到的代码块,提取出来,并保存在“pages/common”目录中,使用静态注入的方式嵌入到其他页面中,既节省空间又方便后续修改。
2.1、 head 中 css、jquery、base 标签
head.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%String basePath = request.getScheme()+ "://"+ request.getServerName()+ ":"+ request.getServerPort()+ request.getContextPath()+ "/";pageContext.setAttribute("basePath",basePath);%><!--写base标签,永远固定相对路径跳转的结果--><base href="<%=basePath%>"><link type="text/css" rel="stylesheet" href="static/css/style.css" ><script type="text/javascript" src="static/script/jquery-1.7.2.js"></script>
2.2、每个页面的页脚
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><div id="bottom"><span>尚硅谷书城.Copyright ©2015</span></div>
2.3、 登录成功后的菜单
login_success_menu.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><div><span>欢迎<span class="um_span">您</span>光临尚硅谷书城</span><a href="pages/order/order.jsp">我的订单</a><a href="index.jsp">注销</a> <a href="index.jsp">返回</a></div>
2.4、manager 模块的菜单
<%@ page contentType="text/html;charset=UTF-8" language="java" %><div><a href="manager/bookServlet?action=page">图书管理</a><a href="order_manager.jsp">订单管理</a><a href="index.jsp">返回商城</a></div>
2.5、静态注入jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html><html><head><meta charset="UTF-8"><title>尚硅谷会员注册页面</title><%-- 静态包含 base标签、css样式、jQuery文件 --%><%@ include file="/pages/common/head.jsp"%><style type="text/css">h1 {text-align: center;margin-top: 200px;}h1 a {color:red;}</style></head><body><div id="header"><img class="logo_img" alt="" src="static/img/logo.gif" ><%--静态包含,登录 成功之后的菜单 --%><%@ include file="/pages/common/login_success_menu.jsp"%></div><div id="main"><h1>欢迎回来 <a href="../../index.jsp">转到主页</a></h1></div><%--静态包含页脚内容--%><%@include file="/pages/common/footer.jsp"%></body></html>
2.6、注意“/”
<a href="pages/order/order.jsp">我的订单</a>
<%@include file="/pages/common/footer.jsp"%>
href后面开头不需要紧接“/”,但file后面需要紧接“/”
3、登录、注册错误提示,及表单回显
以登录回显为示例: Servlet 程序端需要添加回显信息到 Request 域中

4、BaseServlet 的抽取
在实际的项目开发中,一个模块,一般只使用一个 Servlet
代码优化一:合并 LoginServlet 和 RegistServlet 程序为 UserServlet 程序

在jsp页面中通过隐藏的选项指定使用的方法
<input type="hidden" name="action" value="login" />
UserServlet 程序:
package com.chang.web;import com.chang.pojo.User;import com.chang.service.UserService;import com.chang.service.impl.UserServiceImpl;import com.chang.utils.WebUtils;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class UserServlet extends HttpServlet {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");// 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);}}protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {String action = req.getParameter("action");if ("login".equals(action)) {login(req, resp);} else if ("regist".equals(action)) {regist(req, resp);}}}
还要给 login.jsp 添加隐藏域和修改请求地址

优化代码二:使用反射优化大量 else if 代码
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();}}
代码优化三:抽取 BaseServlet 程序

BaseServlet 程序代码:
package com.chang.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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8");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();}}}
修改 UserServlet 程序继承 BaseServlet 程序
5、数据的封装和抽取 BeanUtils 的使用
BeanUtils 工具类,它可以一次性的把所有请求的参数注入到 JavaBean 中。
BeanUtils 工具类,经常用于把 Map 中的值注入到 JavaBean 中,或者是对象属性值的拷贝操作。
BeanUtils 它不是 Jdk 的类。而是第三方的工具类。所以需要导包。
- 导入需要的 jar 包:
commons-beanutils-1.8.0.jar
commons-logging-1.1.1.jar - 编写 WebUtils 工具类使用:
WebUtils 工具类
package com.chang.utils;import org.apache.commons.beanutils.BeanUtils;import java.util.Map;public class WebUtils {/*** 把Map中的值注入到对应的JavaBean属性中。* @param value* @param bean*/public static <T> 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;}}
//获取请求参数并封装成为User对象User user = WebUtils.copyParamToBean(req.getParameterMap(), new User());
6、使用 EL 表达式修改表单回显

7、MVC概念
MVC 全称:Model 模型、 View 视图、 Controller 控制器。
MVC 最早出现在 JavaEE 三层中的 Web 层,它可以有效的指导 Web 层的代码如何有效分离,单独工作。
View 视图:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工合作—— JSP/HTML。
Controller 控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个“调度者”的角色——Servlet。 转到某个页面。或者是重定向到某个页面。
Model 模型:将与业务逻辑相关的数据封装为具体的 JavaBean 类,其中不掺杂任何与数据处理相关的代码—— JavaBean/domain/entity/pojo。
MVC 是一种思想。MVC 的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了降低耦合度),方便后期升级和维护。

8、图书模块
8.1、编写图书模块的数据库表
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');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , 'Java 编程思想' , '阳哥' , 99.5 , 47 , 36 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , 'JavaScript 从入门到精通' , '婷姐' , 9.9 , 85 , 95 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , 'cocos2d-x 游戏编程入门' , '国哥' , 49, 52 , 62 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , 'C 语言程序设计' , '谭浩强' , 28 , 52 , 74 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , 'Lua 语言程序设计' , '雷丰阳' , 51.5 , 48 , 82 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , '西游记' , '罗贯中' , 12, 19 , 9999 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , '水浒传' , '华仔' , 33.05 , 22 , 88 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , '操作系统原理' , '刘优' , 133.05 , 122 , 188 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , '数据结构 java 版' , '封大神' , 173.15 , 21 , 81 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , 'UNIX 高级环境编程' , '乐天' , 99.15 , 210 , 810 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , 'javaScript 高级编程' , '国哥' , 69.15 , 210 , 810 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , '大话设计模式' , '国哥' , 89.15 , 20 , 10 , 'static/img/default.jpg');insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)values(null , '人月神话' , '刚哥' , 88.15 , 20 , 80 , 'static/img/default.jpg');## 查看表内容select id,name,author,price,sales,stock,img_path from t_book;
8.2、编写图书模块的JavaBean
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";
8.3、编写图书模块的Dao和测试Dao
BookDao接口类
package com.chang.dao;import com.chang.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<Book> queryBooks();Integer queryForPageTotalCount();List<Book> queryForPageItems(int begin, int pageSize);Integer queryForPageTotalCountByPrice(int min, int max);List<Book> queryForPageItemsByPrice(int begin, int pageSize, int min, int max);}
BookDaoImpl 实现类
package com.chang.dao.impl;import com.chang.dao.BookDao;import com.chang.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<Book> queryBooks() {String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imgPath from t_book";return queryForList(Book.class, sql);}@Overridepublic Integer queryForPageTotalCount() {String sql = "select count(*) from t_book";Number count = (Number)queryForStringValue(sql);return count.intValue();}@Overridepublic List<Book> 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);}@Overridepublic Integer queryForPageTotalCountByPrice(int min, int max) {String sql = "select count(*) from t_book where price between ? and ?";// Number count = (Number) queryForSingleValue(sql,min,max);Number count = (Number)queryForStringValue(sql,min,max);return count.intValue();}@Overridepublic List<Book> queryForPageItemsByPrice(int begin, int pageSize, int min, int max) {String sql = "select `id`,`name`,`author`,`price`,`sales`,`stock`,`img_path` imgPath from t_book where price between ? and ? order by price limit ?,?";return queryForList(Book.class,sql,min,max,begin,pageSize);}}
BookDao测试类
package com.chang.test;import com.chang.dao.BookDao;import com.chang.dao.impl.BookDaoImpl;import com.chang.pojo.Book;import com.chang.pojo.Page;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);}}@Testpublic void queryForPageTotalCount() {System.out.println( bookDao.queryForPageTotalCount() );}@Testpublic void queryForPageTotalCountByPrice() {System.out.println( bookDao.queryForPageTotalCountByPrice(10, 50) );}@Testpublic void queryForPageItems() {for (Book book : bookDao.queryForPageItems(8, Page.PAGE_SIZE)) {System.out.println(book);}}@Testpublic void queryForPageItemsByPrice() {for (Book book : bookDao.queryForPageItemsByPrice(0, Page.PAGE_SIZE,10,50)) {System.out.println(book);}}}
8.4、编写图书模块的Service和测试Service
BookService 接口类
package com.chang.service;import com.chang.pojo.Book;import com.chang.pojo.Page;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<Book> queryBooks();Page<Book> page(int pageNo, int pageSize);Page<Book> pageByPrice(int pageNo, int pageSize, int min, int max);}
BookServiceImpl 实现类
package com.chang.service.impl;import com.chang.dao.BookDao;import com.chang.dao.impl.BookDaoImpl;import com.chang.pojo.Book;import com.chang.pojo.Page;import com.chang.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<Book> queryBooks() {return bookDao.queryBooks();}@Overridepublic Page<Book> page(int pageNo, int pageSize) {Page<Book> page = new Page<Book>();// 设置每页显示的数量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<Book> items = bookDao.queryForPageItems(begin,pageSize);// 设置当前页数据page.setItems(items);return page;}@Overridepublic Page<Book> pageByPrice(int pageNo, int pageSize, int min, int max) {Page<Book> page = new Page<Book>();// 设置每页显示的数量page.setPageSize(pageSize);// 求总记录数Integer pageTotalCount = bookDao.queryForPageTotalCountByPrice(min,max);// 设置总记录数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<Book> items = bookDao.queryForPageItemsByPrice(begin,pageSize,min,max);// 设置当前页数据page.setItems(items);return page;}}
BookService 测试类
package com.chang.test;import com.chang.pojo.Book;import com.chang.pojo.Page;import com.chang.service.BookService;import com.chang.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);}}@Testpublic void page(){System.out.println(bookService.page(1, Page.PAGE_SIZE ));}@Testpublic void pageByPrice(){System.out.println(bookService.pageByPrice(1, Page.PAGE_SIZE,10,50 ));}}
8.5、编写图书模块的Web层和页面联调测试
8.5.1、图书列表功能的实现

BookServlet 程序中添加 list 方法
protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {//1 通过 BookService 查询全部图书List<Book> 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);}
修改【图书管理】请求地址

jsp数据遍历输出
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html><html><head><meta charset="UTF-8"><title>图书管理</title><%-- 静态包含 base 标签、css 样式、jQuery 文件 --%><%@ include file="/pages/common/head.jsp"%></head><body><div id="header"><img class="logo_img" alt="" src="../../static/img/logo.gif" ><span class="wel_word">图书管理系统</span><%-- 静态包含 manager 管理模块的菜单 --%><%@include file="/pages/common/manager_menu.jsp"%></div><div id="main"><table><tr><td>名称</td><td>价格</td><td>作者</td><td>销量</td><td>库存</td><td colspan="2">操作</td></tr><c:forEach items="${requestScope.books}" var="book"><tr><td>${book.name}</td><td>${book.price}</td><td>${book.author}</td><td>${book.sales}</td><td>${book.stock}</td><td><a href="book_edit.jsp">修改</a></td><td><a href="#">删除</a></td></tr></c:forEach><tr><td></td><td></td><td></td><td></td><td></td><td></td><td><a href="book_edit.jsp">添加图书</a></td></tr></table></div><%--静态包含页脚内容--%><%@include file="/pages/common/footer.jsp"%></body></html>
8.5.2、前后台的简单介绍

8.5.3、添加图书功能的实现

问题说明:表单重复提交
当用户提交完请求,浏览器会记录下最后一次请求的全部信息。当用户按下功能键 F5,就会发起浏览器记录的最后一次 请求。
因此不能使用请求转发,而应该使用重定向
BookServlet 程序中添加 add 方法
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");}
修改 book_edit.jsp 页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html><html><head><meta charset="UTF-8"><title>编辑图书</title><%-- 静态包含 base 标签、css 样式、jQuery 文件 --%><%@ include file="/pages/common/head.jsp"%><style type="text/css">h1 {text-align: center;margin-top: 200px;}h1 a {color:red;}input {text-align: center;}</style></head><body><div id="header"><img class="logo_img" alt="" src="../../static/img/logo.gif" ><span class="wel_word">编辑图书</span><%-- 静态包含 manager 管理模块的菜单 --%><%@include file="/pages/common/manager_menu.jsp"%></div><div id="main"><form action="manager/bookServlet" method="get"><input type="hidden" name="action" value="add" /><table><tr><td>名称</td><td>价格</td><td>作者</td><td>销量</td><td>库存</td><td colspan="2">操作</td></tr><tr><td><input name="name" type="text" value="时间简史"/></td><td><input name="price" type="text" value="30.00"/></td><td><input name="author" type="text" value="霍金"/></td><td><input name="sales" type="text" value="200"/></td><td><input name="stock" type="text" value="300"/></td><td><input type="submit" value="提交"/></td></tr></table></form></div><%--静态包含页脚内容--%><%@include file="/pages/common/footer.jsp"%></body></html>
8.5.4、删除图书功能的实现

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;}
修改删除的连接地址

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

更新【修改】的请求地址

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 页面中显示修改的数据
<div id="main"><form action="manager/bookServlet" method="get"><input type="hidden" name="action" value="add" /><table><tr><td>名称</td><td>价格</td><td>作者</td><td>销量</td><td>库存</td><td colspan="2">操作</td></tr><tr><td><input name="name" type="text" value="${requestScope.book.name}"/></td><td><input name="price" type="text" value="${requestScope.book.price}"/></td><td><input name="author" type="text" value="${requestScope.book.author}"/></td><td><input name="sales" type="text" value="${requestScope.book.sales}"/></td><td><input name="stock" type="text" value="${requestScope.book.stock}"/></td><td><input type="submit" value="提交"/></td></tr></table></form></div>
在 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 页面,即要实现添加,又要实现修改操作
修改的URL中是有id的,所以可以进行区分
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html><html><head><meta charset="UTF-8"><title>编辑图书</title><%-- 静态包含 base标签、css样式、jQuery文件 --%><%@ include file="/pages/common/head.jsp"%><style type="text/css">h1 {text-align: center;margin-top: 200px;}h1 a {color:red;}input {text-align: center;}</style></head><body><div id="header"><img class="logo_img" alt="" src="../../static/img/logo.gif" ><span class="wel_word">编辑图书</span><%-- 静态包含 manager管理模块的菜单 --%><%@include file="/pages/common/manager_menu.jsp"%></div><div id="main"><form action="manager/bookServlet" method="post"><input type="hidden" name="action" value="${ empty param.id ? "add" : "update" }"><%-- <input type="hidden" name="id" value="${ requestScope.book.id==null ? "add" : "update" }">--%><input type="hidden" name="id" value="${ requestScope.book.id }"><table><tr><td>名称</td><td>价格</td><td>作者</td><td>销量</td><td>库存</td><td colspan="2">操作</td></tr><tr><td><input name="name" type="text" value="${requestScope.book.name}"/></td><td><input name="price" type="text" value="${requestScope.book.price}"/></td><td><input name="author" type="text" value="${requestScope.book.author}"/></td><td><input name="sales" type="text" value="${requestScope.book.sales}"/></td><td><input name="stock" type="text" value="${requestScope.book.stock}"/></td><td><input type="submit" value="提交"/></td></tr></table></form></div><%--静态包含页脚内容--%><%@include file="/pages/common/footer.jsp"%></body></html>

9、图书分页

9.1、分页模型 Page 的抽取
当前页数,总页数,总记录数, 当前页数据,每页记录数
/*** Page 是分页的模型对象* @param <T> 是具体的模块的 javaBean 类*/public class Page<T> {public static final Integer PAGE_SIZE = 4;// 当前页码private Integer pageNo;// 总页码private Integer pageTotal;// 当前页显示数量private Integer pageSize = PAGE_SIZE;// 总记录数private Integer pageTotalCount;// 当前页数据private List<T> items
9.2、分页的初步实现
BookDao 代码
@Overridepublic Integer queryForPageTotalCount() {String sql = "select count(*) from t_book";Number count = (Number) queryForSingleValue(sql);return count.intValue();}@Overridepublic List<Book> 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);}
BookService 代码
@Overridepublic Page<Book> page(int pageNo, int pageSize) {Page<Book> page = new Page<Book>();// 设置当前页码page.setPageNo(pageNo);// 设置每页显示的数量page.setPageSize(pageSize);// 求总记录数Integer pageTotalCount = bookDao.queryForPageTotalCount();// 设置总记录数page.setPageTotalCount(pageTotalCount);// 求总页码Integer pageTotal = pageTotalCount / pageSize;if (pageTotalCount % pageSize > 0) {pageTotal+=1;}// 设置总页码page.setPageTotal(pageTotal);// 求当前页数据的开始索引int begin = (page.getPageNo() - 1) * pageSize;// 求当前页数据List<Book> items = bookDao.queryForPageItems(begin,pageSize);// 设置当前页数据page.setItems(items);return page;}
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<Book> page = bookService.page(pageNo,pageSize);//3 保存 Page 对象到 Request 域中req.setAttribute("page",page);//4 请求转发到 pages/manager/book_manager.jsp 页面req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);}
manager_menu.jsp 中“图书管理”请求地址的修改
<%@ page contentType="text/html;charset=UTF-8" language="java" %><div><a href="manager/bookServlet?action=page">图书管理</a><a href="order_manager.jsp">订单管理</a><a href="index.jsp">返回商城</a></div>
book_manager.jsp 修改
%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html><html><head><meta charset="UTF-8"><title>图书管理</title><%-- 静态包含 base 标签、css 样式、jQuery 文件 --%><%@ include file="/pages/common/head.jsp"%><script type="text/javascript">$(function () {// 给删除的 a 标签绑定单击事件,用于删除的确认提示操作$("a.deleteClass").click(function () {// 在事件的 function 函数中,有一个 this 对象。这个 this 对象,是当前正在响应事件的 dom 对象。/*** confirm 是确认提示框函数* 参数是它的提示内容* 它有两个按钮,一个确认,一个是取消。* 返回 true 表示点击了,确认,返回 false 表示点击取消。*/return confirm("你确定要删除【" + $(this).parent().parent().find("td:first").text() + "】?");// return false// 阻止元素的默认行为===不提交请求});});</script></head><body><div id="header"><img class="logo_img" alt="" src="../../static/img/logo.gif" ><span class="wel_word">图书管理系统</span><%-- 静态包含 manager 管理模块的菜单 --%><%@include file="/pages/common/manager_menu.jsp"%></div><div id="main"><table><tr><td>名称</td><td>价格</td><td>作者</td><td>销量</td><td>库存</td><td colspan="2">操作</td></tr><c:forEach items="${requestScope.page.items}" var="book"><tr><td>${book.name}</td><td>${book.price}</td><td>${book.author}</td><td>${book.sales}</td><td>${book.stock}</td><td><a href="manager/bookServlet?action=getBook&id=${book.id}">修改</a></td><td><a class="deleteClass" href="manager/bookServlet?action=delete&id=${book.id}">删除</a></td></tr></c:forEach><tr><td></td><td></td><td></td><td></td><td></td><td></td><td><a href="pages/manager/book_edit.jsp">添加图书</a></td></tr></table><div id="page_nav"><a href="#">首页</a><a href="#">上一页</a><a href="#">3</a>【${ requestScope.page.pageNo }】<a href="#">5</a><a href="#">下一页</a><a href="#">末页</a>共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录到第<input value="4" name="pn" id="pn_input"/>页<input type="button" value="确定"></div></div><%--静态包含页脚内容--%><%@include file="/pages/common/footer.jsp"%></body></html>
9.3、首页、上一页、下一页、末页实现
<div id="page_nav"><%--大于首页,才显示--%><c:if test="${requestScope.page.pageNo > 1}"><a href="manager/bookServlet?action=page&pageNo=1">首页</a><a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageNo-1}">上一页</a></c:if><a href="#">3</a>【${ requestScope.page.pageNo }】<a href="#">5</a><%-- 如果已经 是最后一页,则不显示下一页,末页 --%><c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}"><a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageNo+1}">下一页</a><a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageTotal}">末页</a></c:if>共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录到第<input value="4" name="pn" id="pn_input"/>页<input type="button" value="确定"></div>
9.4、分页模块中跳转到指定页数功能实现
<div id="page_nav"><%--大于首页,才显示--%><c:if test="${requestScope.page.pageNo > 1}"><a href="manager/bookServlet?action=page&pageNo=1">首页</a><a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageNo-1}">上一页</a></c:if><a href="#">3</a>【${ requestScope.page.pageNo }】<a href="#">5</a><%-- 如果已经 是最后一页,则不显示下一页,末页 --%><c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}"><a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageNo+1}">下一页</a><a href="manager/bookServlet?action=page&pageNo=${requestScope.page.pageTotal}">末页</a></c:if>共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录到第<input value="${param.pageNo}" name="pn" id="pn_input"/>页<input id="searchPageBtn" type="button" value="确定"><script type="text/javascript">$(function () {// 跳到指定的页码$("#searchPageBtn").click(function () {var pageNo = $("#pn_input").val();<%--var pageTotal = ${requestScope.page.pageTotal};--%><%--alert(pageTotal);--%>// javaScript 语言中提供了一个 location 地址栏对象// 它有一个属性叫 href.它可以获取浏览器地址栏中的地址// href 属性可读,可写location.href = "${pageScope.basePath}manager/bookServlet?action=page&pageNo=" + pageNo;});});</script></div>
9.5、Page 对象中的修改
public void setPageNo(Integer pageNo) {/* 数据边界的有效检查 */if (pageNo < 1) {pageNo = 1;}if (pageNo > pageTotal) {pageNo = pageTotal;}this.pageNo = pageNo;}
9.6、BookService 中 page 方法的修改
@Overridepublic Page<Book> page(int pageNo, int pageSize) {Page<Book> page = new Page<Book>();// 设置每页显示的数量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<Book> items = bookDao.queryForPageItems(begin,pageSize);// 设置当前页数据page.setItems(items);return page;}
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
<%--页码输出的开始--%><c:choose><%--情况 1:如果总页码小于等于 5 的情况,页码的范围是:1-总页码--%><c:when test="${ requestScope.page.pageTotal <= 5 }"><c:set var="begin" value="1"/><c:set var="end" value="${requestScope.page.pageTotal}"/></c:when><%--情况 2:总页码大于 5 的情况--%><c:when test="${requestScope.page.pageTotal > 5}"><c:choose><%--小情况 1:当前页码为前面 3 个:1,2,3 的情况,页码范围是:1-5.--%><c:when test="${requestScope.page.pageNo <= 3}"><c:set var="begin" value="1"/><c:set var="end" value="5"/></c:when><%--小情况 2:当前页码为最后 3 个,8,9,10,页码范围是:总页码减 4 - 总页码--%><c:when test="${requestScope.page.pageNo > requestScope.page.pageTotal-3}"><c:set var="begin" value="${requestScope.page.pageTotal-4}"/><c:set var="end" value="${requestScope.page.pageTotal}"/></c:when><%--小情况 3:4,5,6,7,页码范围是:当前页码减 2 - 当前页码加 2--%><c:otherwise><c:set var="begin" value="${requestScope.page.pageNo-2}"/><c:set var="end" value="${requestScope.page.pageNo+2}"/></c:otherwise></c:choose></c:when></c:choose><c:forEach begin="${begin}" end="${end}" var="i"><c:if test="${i == requestScope.page.pageNo}">【${i}】</c:if><c:if test="${i != requestScope.page.pageNo}"><a href="manager/bookServlet?action=page&pageNo=${i}">${i}</a></c:if></c:forEach><%--页码输出的结束--%>
9.8、修改分页后,增加,删除,修改图书信息的回显页面
以修改图书为示例:
1、在修改的请求地址上追加当前页码参数

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

3、在服务器重定向的时候,获取当前页码追加上进行跳转
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=page&pageNo=" +req.getParameter("pageNo"));}
10、首页 index.jsp 的跳转

index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--只负责请求转发--%><jsp:forward page="/client/bookServlet?action=page"></jsp:forward>
web/pages/client/index.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html><html><head><meta charset="UTF-8"><title>书城首页</title><%-- 静态包含 base标签、css样式、jQuery文件 --%><%@ include file="/pages/common/head.jsp"%></head><body><div id="header"><img class="logo_img" alt="" src="static/img/logo.gif" ><span class="wel_word">网上书城</span><div><a href="pages/user/login.jsp">登录</a> |<a href="pages/user/regist.jsp">注册</a> <a href="pages/cart/cart.jsp">购物车</a><a href="pages/manager/manager.jsp">后台管理</a></div></div><div id="main"><div id="book"><div class="book_cond"><form action="client/bookServlet" method="get"><input type="hidden" name="action" value="pageByPrice">价格:<input id="min" type="text" name="min" value="${param.min}"> 元 -<input id="max" type="text" name="max" value="${param.max}"> 元<input type="submit" value="查询" /></form></div><div style="text-align: center"><span>您的购物车中有3件商品</span><div>您刚刚将<span style="color: red">时间简史</span>加入到了购物车中</div></div><c:forEach items="${requestScope.page.items}" var="book"><div class="b_list"><div class="img_div"><img class="book_img" alt="" src="${book.imgPath}" /></div><div class="book_info"><div class="book_name"><span class="sp1">书名:</span><span class="sp2">${book.name}</span></div><div class="book_author"><span class="sp1">作者:</span><span class="sp2">${book.author}</span></div><div class="book_price"><span class="sp1">价格:</span><span class="sp2">¥${book.price}</span></div><div class="book_sales"><span class="sp1">销量:</span><span class="sp2">${book.sales}</span></div><div class="book_amount"><span class="sp1">库存:</span><span class="sp2">${book.stock}</span></div><div class="book_add"><button>加入购物车</button></div></div></div></c:forEach></div><%--静态包含分页条--%><%@include file="/pages/common/page_nav.jsp"%></div><%--静态包含页脚内容--%><%@include file="/pages/common/footer.jsp"%></body></html>
11、分页条的抽取
11.1、抽取分页条中请求地址为 url 变量
在 page 对象中添加 url 属性
/*** Page 是分页的模型对象* @param <T> 是具体的模块的 javaBean 类*/public class Page<T> {public static final Integer PAGE_SIZE = 4;// 当前页码private Integer pageNo;// 总页码private Integer pageTotal;// 当前页显示数量private Integer pageSize = PAGE_SIZE;// 总记录数private Integer pageTotalCount;// 当前页数据private List<T> items;// 分页条的请求地址private String url
11.2、在 Servlet 程序的 page 分页方法中设置 url 的分页请求地址

11.3、修改分页条中请求地址为 url 变量输出,并抽取一个单独的 jsp 页面
web/common/page_nav.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--分页条的开始--%><div id="page_nav"><%--大于首页,才显示--%><c:if test="${requestScope.page.pageNo > 1}"><a href="${ requestScope.page.url }&pageNo=1">首页</a><a href="${ requestScope.page.url }&pageNo=${requestScope.page.pageNo-1}">上一页</a></c:if><%--页码输出的开始--%><c:choose><%--情况1:如果总页码小于等于5的情况,页码的范围是:1-总页码--%><c:when test="${ requestScope.page.pageTotal <= 5 }"><c:set var="begin" value="1"/><c:set var="end" value="${requestScope.page.pageTotal}"/></c:when><%--情况2:总页码大于5的情况--%><c:when test="${requestScope.page.pageTotal > 5}"><c:choose><%--小情况1:当前页码为前面3个:1,2,3的情况,页码范围是:1-5.--%><c:when test="${requestScope.page.pageNo <= 3}"><c:set var="begin" value="1"/><c:set var="end" value="5"/></c:when><%--小情况2:当前页码为最后3个,8,9,10,页码范围是:总页码减4 - 总页码--%><c:when test="${requestScope.page.pageNo > requestScope.page.pageTotal-3}"><c:set var="begin" value="${requestScope.page.pageTotal-4}"/><c:set var="end" value="${requestScope.page.pageTotal}"/></c:when><%--小情况3:4,5,6,7,页码范围是:当前页码减2 - 当前页码加2--%><c:otherwise><c:set var="begin" value="${requestScope.page.pageNo-2}"/><c:set var="end" value="${requestScope.page.pageNo+2}"/></c:otherwise></c:choose></c:when></c:choose><c:forEach begin="${begin}" end="${end}" var="i"><c:if test="${i == requestScope.page.pageNo}">【${i}】</c:if><c:if test="${i != requestScope.page.pageNo}"><a href="${ requestScope.page.url }&pageNo=${i}">${i}</a></c:if></c:forEach><%--页码输出的结束--%><%-- 如果已经 是最后一页,则不显示下一页,末页 --%><c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}"><a href="${ requestScope.page.url }&pageNo=${requestScope.page.pageNo+1}">下一页</a><a href="${ requestScope.page.url }&pageNo=${requestScope.page.pageTotal}">末页</a></c:if>共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录到第<input value="${param.pageNo}" name="pn" id="pn_input"/>页<input id="searchPageBtn" type="button" value="确定"><script type="text/javascript">$(function () {// 跳到指定的页码$("#searchPageBtn").click(function () {var pageNo = $("#pn_input").val();<%--var pageTotal = ${requestScope.page.pageTotal};--%><%--alert(pageTotal);--%>// javaScript语言中提供了一个location地址栏对象// 它有一个属性叫href.它可以获取浏览器地址栏中的地址// href属性可读,可写location.href = "${pageScope.basePath}${ requestScope.page.url }&pageNo=" + pageNo;});});</script></div><%--分页条的结束--%>
12、首页价格搜索

