jsp/html---view Book类/JavaBean类 --- Model Servlet程序类-----Controller
再逐一测试
执行删除后,要想让id自增接着按照前面的序号,需要执行sql ALTER TABLE t_book AUTO_INCREMENT = 1
指定访问的servlet程序及post参数(action判断)
manager.jsp页面跳转
方便权限管理
***** 共性Servlet类中放入post请求(判断action--调用指定方法) *****
无论那个子类继承BaseSerlvet,this就代表该子类---即获取该子类中指定action值的方法
BookServlet程序list()
manager.jsp
列表功能的实现
取出域中的books,遍历,遍历项设为book
前台后台
--- 需要参数注入 webutils中的参数为copyParamToBean()
表单提交----book_manager.jsp
地址为后台Servlet程序,提交方式get/post一样(get中调用了psot),隐藏域action=add(设置隐藏域action对应方法名)
需要提交的表单项的name需要对应指定的Book类属性名 ------ 不然参数注入出错
编写add方法
请求转发会出错,导致F5后多次提交-----------使用重定向
请求转发为一次请求,重定向为第二次请求,request域中的数据存在一次请求中
请求转发存在的问题,因为请求转发是一次访问多个页面,浏览器会缓存最后访问的信请求息,当按下功能键F5,请求会再次提交,将上次提交的信息全部再提交一次,导致表单重复提交,清理缓存也不行
解决办法:add方法中的请求转发改为重定向,将以此访问变为两次访问,当再次F5,只会进行重定向操作到list查询,不会进行添加
注意: 请求转发的 / 表示工程名
重定向的 / 表示端口号,所以利用重定向代替请求转发,需要添加工程名 req.getContextPath()
也可以直接写完整的访问路径
删除图书功能实现 只需要一个id---webutils的字符转Int
提交表单到后台---action=delete,id=图书编号
1. BookServlet中获取请求参数id
2. 调用bookServlet.deleteBookById(),删除图书
3. 重定向跳到图书列表页面
可以直接重定向
获取的参数为字符串,删除方法需要的是integer类型,需要转型
优化:在WebUtils中编写String---Integer方法
添加删除提示功能-----给删除添加点击事件
删除的a标签设置class,通过class来设置点击事件
confirm() 是一个提示框,两个选项,返回true是点了确认,false是点了取消
直接返回confirm的值,true就提交表单,页面跳转,false阻止元素默认行为(阻止表单提交)
提示信息中,穿插获取要删除的行的书名name------this(当前正在执行的dom对象)、parent(父标签)、find("td:first")(标签内查找)
修改图书功能实现
-------------------------------------------------------------------------------------------------------------
第一步:回显需要修改的信息给book_edit.jsp
通过jsp页面----> 跳转到jsp页面,无法操作数据库,可以先访问Servlet程序,在请求转发到指定jsp页面
book_manager.jsp中跳转Servlet请求,传入参数(指定方法getBook和需修改的id)
Web层 getBook方法,通过id(forEach获取的遍历项book)获取参数(指定book),再回写到域中,请求转发到编辑页面
---------------------------------------------------------------------------------------------
第二步:提交修改的信息,保存到服务器
存在待解决的问题:
添加、修改都需要使用book_edit.jsp的隐藏域,来判断调用对应方法
book_edit.jsp 的隐藏域已经用来标示add添加操作,还要标示update更新操作
--------------每个请求都自带一个method="xxx"参数,给隐藏域获取
在添加图书的a标签中添加参数add,在修改的a标签中添加参数update
在book_edit.jsp隐藏域中${param.method}获取指定的操作参数值add/update,动态获取隐藏域
--------------隐藏域判断请求的参数是否存在“id“,来判断add/update
添加操作请求重定向到book_edit.jsp的url 有 id参数
更新修改请求重定向到book_edit.jsp的url 没有id参数
EL表达式param获取请求参数----------通过判断请求参数中是否有id,来判断使用
-------------隐藏域判断request域中是否存在book(getBook获取并放进域中的book),来判断add/update
注意:回显时,获取id用的book是list遍历的循环项,没有在域中
编写更新Servlet方法:update()
通过解决book_edit.jsp冲突后,请求到update方法------将参数封装到book,更新book,重定向回列表
存在问题:
获取的参数中不包含 书籍 id ,数据库查询通过id查找不到
book_edti.jsp页面没有获取id,没有传递id参数给Servlet update
解决办法:
表单提交时,增加隐藏域id (或者在修改页面增加id项,参数传递时,全部传入map)
---------------------------------------------------------------------------------------------------
首先创建一个Page<T>类,带泛型,因为不止Book一个模块使用
同理:当前页数据等,都需要使用泛型的集合存放数据
一、分页初步实现
1. Servlet程序----page()方法
获取请求参数 pageNo pageSize
用service的page()方法,用pageNo、pageSize参数获取一个封装好的page对象(包含需要的值)
将获取的page对象放入域中
请求转发
第一次访问page, pageNo、pageSize为空,使用默认值
2. service层的------page(pageNo,pageSize)方法
创建page对象
设置当前页、设置每页显示数量、设置总记录数、设置总页码、设置当前页数据
查询总记录数 -----Dao层queryForPageTotalCount()方法查询
计算总页码 ------总记录数 / 每页显示数量
获取当前页数据 ------索引开始位置(begin =(当前页-1)* 每页显示数量),再用Dao层queryForPageItems()方法查询
3. Dao层-----求总记录数 + 求当前页数据方法
select count(*) from t_book
select * from t_book limit begin,pagesize
4. 分别测试Dao层 、
Service层
5. 实现界面显示分页界面
修改公共的图书管理跳转地址------action=page-----请求访问Servlet的page方法跳转 --- book_manager.jsp
遍历源修改为 域中的page对象的items属性
添加分页导航栏
----给分页条的确定按钮添加点击事件(location.href)
location.href获取地址栏中的地址
赋值location.href,进行跳转
location必须小写
可以调用base标签的地址,通过写入page域中,再在地址跳转处获取 ---------动态获取请求根地址
检验搜索页数超出范围
方法一: 在分页条提交按钮处,事件中判断
在按钮处JavaScript中判断pageNo的值超出范围的操作 --不推荐
方法二:在Page类的设置当前页方法中判断-----即要跳转的页面-----超过就设为末页,小于就设为首页
数据边界有效检查
将有效检查设置在page的setpageNo()方法里,所有模块调用分页时,都能使用----提高通用性
<%--<c:choose>
<c:when test="${requestScope.page.pageTotal<=5}">
<c:forEach begin="1" end="${requestScope.page.pageTotal}" 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:when>
<c:when test="${requestScope.page.pageTotal>5}">
<c:choose>
<c:when test="${requestScope.page.pageNo<3}">
<c:forEach begin="1" end="5" 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:when>
<c:when test="${requestScope.page.pageNo>requestScope.page.pageTotal-3}">
<c:forEach begin="${requestScope.page.pageTotal-4}" end="${requestScope.page.pageTotal}" 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:when>
<c:otherwise>
<c:forEach begin="${requestScope.page.pageNo-2}" end="${requestScope.page.pageNo+2}" 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:otherwise>
</c:choose>
</c:when>
</c:choose>--%>
简化:
由于每次只执行一次请求,一次forEach,将forEach独立出来,每个需要调用到forEach的地方,只需设置begin,end的值
注意:
分页后,需要将原来跳转到 list 的操作add、delete、update等,重定向为page
分页对增删改操作的影响
add需要传递末页参数 pageTotal
删除、修改需要传递当前页参数 pageNo
添加
1. 添加图书跳转处,传递分页-总页数参数pageTotal
2. 获取传递的pageTotal参数---放入隐藏域pageTotal
3. 添加方法add中,获取总页数pageTotal,再加一,保证跳转后肯定是最后一页(传递的12页,新加后变13,冲突)
4. 添加完,重定向地址中,总页数值 pageTotal 传递给 当前页 pageNo------跳转到添加的最后一页处
删除
1. 删除图书跳转处,传递分页-当前页参数pageNo -------- page对象在跳转page方法时,就存入域中了
2. 重定向地址中,当前页值传递给 pageNo -----删除后跳转到被删除的当前页
修改
1. book_manager.jsp修改图书跳转处,传递分页-当前页参数pageNo
2. 在book_edit.jsp中,获取传递的pageNo参数---放入隐藏域pageNo
也可将1的参数名改为pageTotal,利用原有的隐藏域pageTotal传递,update方法中的重定向参数就将pageTotal-->pageNo
3. 重定向地址中,当前页值传递给 pageNo, 再将pageNo返回到显示页面
创建client下的index.jsp,将web下的index.jsp内容复制----(真正的首页)
一、前台页面跳转
web下的index.jsp-----作为跳转到clientBookServlet的中介-----再跳转到真正的client下的index.jsp
注意:跳转时,访问page
web下的index.jsp
通过page请求转发到client下的index.jsp
二、前台分页遍历显示
将图书块进行forEach遍历,遍历源为域中page.items,输出项book,显示每个book的属性
/*单独的一项书籍信息:*/
三、分页条抽取
复制 book_manager.jsp <div id="page_nav">的内容------分页条,将所有跳转地址改为client/bookServlet,进行跳转
优化:
前台的分页条中的页面跳转,的访问Servlet程序及参数
替换为page的属性url获取
-----在page中加入url属性,在page方法中设置url属性
后台的分页条中的页面跳转,的访问Servlet程序及参数
替换为page的属性url获取
-----在page中加入url属性,在page方法中设置url属性
优点:当需要改页面的跳转地址时,只需修改page.setUrl的url变量值
前台后台不同处为跳转的url不同,将不同的部分设为page对象的url属性,放入域中调用,此时就可以抽取出来该分页条块
跳转部分使用与的page的url代替
二次优化:
当前台和后台的url都替换成后,分页条部分代码完全一样,就可以将分页条的部分抽取到common中,通过静态包含调用
静态包含调用
表单
web_index->clientservlet->client_index.jsp请求跳转到前台pageByPrice 传递min、 max参数(在clientBookServlet中设置了)
Servlet程序-----pageByPrice
获取请求参数pageNo、pageSize、min、max
url设置---参数action跳转到pageByPrice---供下一次价格区间查询---传回分页条中需要用到url的地方
实现输入价格区间查询后,再次下一页。。。还是在查询的结果中跳转
但还需要传递min、max参数-------------min、max添加到url后(判断是否存在才添加)
page对象放入域中
重定向到前台
Service层
求总记录、总页码、当前页数据
参考page的方法,传入min、max参数
调用Dao的两个方法
Dao层
参照 方法
传入min、max,在sql中通过price在区间查询
在 中传入min、max
测试Dao、Service、Servlet程序
参数pageByPrice供---在区间查询结果下,再点击下一页等,访问价格区间查询
当输出价格区间的书籍后,点击下一页,出错-----价格参数min、max------------没有给请求传递min、max参数
---服务器创建Cookie,保存在客户端的
---服务器通知客户端保存键值对的一种技术
--------new Cookie(key,value)
注意:resp.addCookie(cookie)必须有,否则客户端不会受到Cookie的创建
-------getCookies()
获取所有Cookie -------req.getCookies()
查找单个Cookie --------将所有Cookies遍历,取出单个特定key 的 Cookie
创建查找工具类 ---- 遍历Cookies,找到指定key的Cookie
一:要改谁,就创建同名的Cookie,构造时传递值,再传回客户端
二:要改谁,就获取该Cookie,通过setValue()改值,再传回客户端
F12 --- Aplication --- Cookies
F12--- 存储
setMaxAge()
正数 ------- 指定秒后删除
负数 ------- 浏览器关闭后 删除
0 ------- 马上关
过期时间设为一小时后
设置cookie的过期时间为过期,浏览器就会马上删除
注意:
1. Servlet程序方法写好后,需要在页面跳转处绑定Servlet方法入口action
2.正常创建的Cookie都是session类型-----------浏览器关就删
Path一般为当前工程路径
例如:
访问路径中增加abc
敲回车---客户端发送过来的Cookie两个都有,因为/工程路径/abc也包含了默认的工程路径
登陆成功后才有cookie
回显的用户名,使用的是EL表达式的cookie隐含对象,username表示cookie的Name,value表示cookie的Value
---------维护一个客户端和服务器之间关联的一种技术
第一次点击是true---新创建的
后面点击的是false---不是新创建的
设置跳转Servlet和参数
在iframe中输出存取的信息
session超时时长的概念:
当设置了超时时长为3秒后,在期间不停请求( isNew / req.getSession().getAttribute() )
每次请求后,超时时长 timeout 都被刷新, timeout=3
示例代码:
先创建一个session ----- isNew----true
再次点击创建、获取 ----- isNew----false
设置
3秒后,再次点击创建获取 ----- isNew----true