2010.1.4 高级分页查询和session加强
来源:互联网 发布:有做标书软件 编辑:程序博客网 时间:2024/06/05 17:18
2010-01-04 今天是第一天写学习博客,希望能坚持下去,从此培养出一个良好的学习习惯来。
废话少说,开始做今天的学习总结!
今天老冯上午讲了利用DBUtil做高级分页查询,下午讲了利用session防止表单重复提交以及实现一次性验证码。
一.高级分页查询
1.高级分页查询就是添加了搜索功能的分页查询,要达到的具体效果是:在文本框中输入新的查询条件后,不按搜索按钮只点击上页、下页等超链接时,显示的记录仍然是继续执行当前的查询条件所产生的效果;而只有在输入新的查询条件后,点击搜索按钮才会按照新的查询条件返回结果。
关于分页的知识昨天老冯已具体说过,今天主要说下如何编写实现上述效果的高级查询代码。主要思路:编写javascript代码来完成表单提交;对隐藏域的使用。
首先在jsp页面中编写搜索按钮,注意这里type是button而不是submit,所以要写一段javascript脚本代码来完成表单提交的功能。老冯说在实际开发中button使用灵活,比submit来得常用,特别是当有一排提交按钮的时候就只有用button才能解决。
<td><input type="button" value="搜索" onclick="search();"></td>
//点击搜索按钮的javsscript代码
function search(){
var searchFlag=document.getElementById("searchFlag");
searchFlag.value="search";
document.forms[0].submit();
}
然后处理首页 上页 下页 尾页的超链接,这里不能直接连接到servlet控制台,因为这样子并没有保存查询条件,点击后得到的不是查询结果。为了把查询信息保存起来,在点击这些超链接时也必须采用提交表单的方式。
<a href="javaScript:toPage(1,${pageBean.maxSize})">首页</a>
<a href="javaScript:toPage(${pageBean.prePage},${pageBean.maxSize})">上页</a>
<a href="javaScript:toPage(${pageBean.nextPage},${pageBean.maxSize})">下页</a>
<a href="javaScript:toPage(${pageBean.pageCnt},${pageBean.maxSize})">尾页</a>
//点击上页 下页 首页 尾页 超链接时的javacript代码
function toPage(curPage,maxSize){
var searchFlag=document.getElementById("searchFlag");
searchFlag.value="page";
document.forms[0].action=document.forms[0].action+"?curPage="+curPage+"&maxSize="+maxSize;
//alert(document.forms[0].action);
document.forms[0].submit();
}
接下来就是重点,为每一个搜索条件配一个隐藏域,因为隐藏域中的值是固定的不会因为输入框里的值更改而更改(在浏览器
中尝试后查看源码可知),只有在点击搜索按钮后,在servlet中封装新的查询条件,再传给jsp页面后才会更改。
<tr>
<td>cname:</td>
<td><input type="text" id="cname" name="cname" value="${searchCompany.cname}">
<input type="hidden" id="old_cname" name="old_cname" value="${searchCompany.cname}">
</td>
</tr>
<tr>
<td>address:</td>
<td><input type="text" id="address" name="address" value="${searchCompany.address}">
<input type="hidden" id="old_address" name="old_address" value="${searchCompany.address}">
</td>
</tr>
于是下面要解决的就是如何在点击搜索按钮时候在servlet获取的值是文本框里的cname 和address,而在点击下页等超链
接时候是隐藏域中的old_cname何old_address。用的还是先建立个隐藏域作为标识,然后在javascript的代码中进行处
理。
<!-- 执行查询条件的标识
该值为search时,servlet 获取的是cname address
该值为page时,servlet获取的是 old_cname old_address
-->
<input type="hidden" id="searchFlag" name="searchFlag" value="search">
-------------------------------------------------------------------------------
//在servlet中获取查询标识
String flag="search";
String sflag=request.getParameter("searchFlag");
if(sflag!=null){
flag=sflag;
}
--------------------------------------------------------------------------------
//点击搜索按钮 执行javascript 中的 search方法
function search(){
var searchFlag=document.getElementById("searchFlag");
searchFlag.value="search";//更改searchFlag的值
document.forms[0].submit();
}
//查询标识为search时执行servlet中的代码
//点击搜索按钮执行
if("search".equals(flag)){
cname = request.getParameter("cname");
address = request.getParameter("address");
}
--------------------------------------------------------------------------------
//点击上页 下页 首页 尾页 超链接 执行javascript 中的 topage方法
function toPage(curPage,maxSize){
var searchFlag=document.getElementById("searchFlag");
searchFlag.value="page";//更改searchFlag的值
document.forms[0].action=document.forms[0].action+"?curPage="+curPage+"&maxSize="+maxSize;
//alert(document.forms[0].action);
document.forms[0].submit();
}
//点击上页 下页 首页 尾页 超链接 执行servlet中的代码
//点击上页 下页 首页 尾页 超链接
if("page".equals(flag)){
cname = request.getParameter("old_cname");
address = request.getParameter("old_address");
}
----------------------------------------------------------------------
最后是在serblet中封装传来的值,并放到request作用域中。
// 封装查询条件
SearchCompany searchCompany = new SearchCompany();
searchCompany.setAddress(address);
searchCompany.setCname(cname);
request.setAttribute("searchCompany", searchCompany);
2.老冯在讲解高级分页的时候还提到了代码的优化:一个是利用函数的重载对代码进行的优化;一个是将servlet中
doGet方法中的代码按照功能提取出来,每一个功能封装成一个方法,然后再在doGet中进行调用(略)。
对BaceDao中的查询记录数的方法的优化,利用重载的方式,在一个方法中调用其的重载方法,简化了代码的编写。
/**
* 查询有条件的所有记录数
* @param conn
* @param sqlCount
* @return
*/
public Integer findCountByCondition(Connection conn, String sql,Object[] params) {
int recordCount=0;
//*****************************************************************************************
ResultSetHandler resultSetHandler=new ResultSetHandler(){
public Object handle(ResultSet rs) throws SQLException {
int count=0;
if(rs.next()){
count=rs.getInt(1);
}
return count;
}
};
//*****************************************************************************************
QueryRunner query=new QueryRunner();
try {
recordCount=(Integer)query.query(conn, sql,resultSetHandler,params);
} catch (SQLException e) {
e.printStackTrace();
}
return recordCount;
}
/**
* 查询没有条件的总的记录数
* @param conn
* @param sql
* @return
*/
public Integer findCountByCondition(Connection conn, String sql) {
return findCountByCondition(conn,sql,null);
}
二.Session加强
1.先将的是利用session防止表单的重复提交,表单的重复提交状况的出现会向数据库中添加同一条信息多次,造成数据库
中的错误的记录信息,特别在银行系统中表单的重负提交会带来极大的经济损失。
表单重复提交的三种情况:
①由于网络延迟或服务器变慢,重复点击提交按钮
②添加成功之后转到成功页面,按F5刷新成功页面,也会发生表单重复提交
③到达成功页面以后,点击后退,再提交,页是表单重复提交。
注:添加成功之后转到成功页面,后退到添加页面,再次刷新该页面,此时再提交一次请求,不算重复提交
情况①的解决原理:让其点击提交按钮后,只发送一次请求到servlet。具体还有两种情况
当提交按钮的类型是”submit"时,要建立个控制符来对代码的执行进行控制。有三种方法
1)<td><input type="submit" value="提交" onclick="checkSubmit(); return false;" ></td>
<!--
return false :阻止后续代码的执行
-->
</tr>
</table>
</form>
<script type="text/javascript">
var flag=false;
function checkSubmit(){
if(!flag){
document.forms[0].submit();
flag=true;
}else{
alert("您已经重复提交了");
}
}
</script>
2)<td><input type="submit" value="提交" onclick="return checkSubmit()" ></td>
<!--
return false :阻止后续代码的执行
-->
</tr>
</table>
</form>
<script type="text/javascript">
var flag=false;
function checkSubmit(){
if(!flag){
document.forms[0].submit();
flag=true;
return true; //通过
}else{
alert("您已经重复提交了");
}
return false; //阻止
}
</script>
3) <form action="${pageContext.request.contextPath}/saveEmpServlet" method="post" onsubmit="return false;">
<td><input type="submit" value="提交" onclick="checkSubmit()" ></td>
<!--
return false :阻止后续代码的执行
-->
</tr>
</table>
</form>
<script type="text/javascript">
var flag=false;
function checkSubmit(){
if(!flag){
document.forms[0].submit();
flag=true;
}else{
alert("您已经重复提交了");
}
}
</script>
当类型为button时也有两种解决方法
1)<td><input type="button" name="ok" value="提交" onclick="checkSubmit()" ></td>
<!--
return false :阻止后续代码的执行
-->
</tr>
</table>
</form>
<script type="text/javascript">
function checkSubmit(){
document.forms[0].submit();
document.forms[0].ok.disabled=true;
}
</script>
2)<td><input type="button" value="提交" onclick="checkSubmit()" ></td>
<!--
return false :阻止后续代码的执行
-->
</tr>
</table>
</form>
<script type="text/javascript">
var flag=false;
function checkSubmit(){
if(!flag){
document.forms[0].submit();
flag=true;
}else{
alert("您已经重复提交了");
}
}
</script>
情况②③只有在servlet执行转发的情况下才会发生,而在重定向时不会发生。因为调用forward()方法时候,浏览器所保留的
Url是先前表单提交的url,再次刷新的时候,浏览器将再次提交用户先前输入的数据,引起重复提交。如果用sendDirect()方法,将
客户端重定向到服务器,就不会出现重复提交了。
解决原理,利用session在一次会话中共享的原理,在jsp页面中建立一个标识“flag”,把这个flag放到session中,传给
Servlet用它来控制servlet中代码的执行。
<%
session.setAttribute("flag","flag");
%>
但是上面的代码知识原理,开发中不能怎么写。应该使用java中UUID通用唯一标示符这个类中的方法随机生成一个唯一
的标示符。
然后当jsp页面运行时,生成一个唯一的UUID数,放置在session中一份,同时也放置到页面的一个隐藏域中
隐藏域:
<input type="hidden" name="uuid.html" value="<%=TokenUUID.getTokenUUID().getUUIDAsString(request)%>" >
session:
public String getUUIDAsString(HttpServletRequest request){
//如session存在使用存在,如sessioon不存在,创建一个新的
HttpSession session=request.getSession();
//生成uuid唯一标识
String uuid=UUID.randomUUID().toString();
if(uuid!=null){
//放置uuid到session中
session.setAttribute("uuid.action", uuid);
}
return uuid;
}
接着jsp页面提交给Servlet进行比对
boolean flag=TokenUUID.getTokenUUID().isUUIDValidate(request);
//如存在
if(flag){
TokenUUID.getTokenUUID().resetUUID(request);
String name=request.getParameter("name");
String email=request.getParameter("email");
Emp emp=new Emp();
emp.setName(name);
emp.setEmail(email);
System.out.println("执行SaveEmpServlet");
EmpDaoImpl empDaoImpl=new EmpDaoImpl();
empDaoImpl.saveEmp(emp);
}else{
//如不存在
System.out.println("您已经重复提交了");
}
注意在 Servlet中uuid必须从session中删除
TokenUUID.getTokenUUID().resetUUID(request);
2.生成验证码
验证码在我们登录注册的时候是最为常见的了,它是一种防止暴力循环破解密码的方法。验证码的使用原理也
与上面防止表单重复提交的原理一样,先生成一个随机的验证码,然后把它提交给servlet的session和jsp页面中,
然后做比较。
弄出验证码(ImageServlet.java)
* 定义宽度和高度
*用BufferdImage类在缓冲区中生成一个图像
*把图像从缓冲区写入到流里
*对图形进行设置:获取图形的上下文 ,设置颜色
*定义图像中的字
*生成验证码并放到session中用来与页面提交的验证码作比对
*设置干扰点
*禁止使用缓存,为什么要有三句代码
//禁止使用缓存 ,这三个方法要同时使用,其中的某个方法某个浏览器可能不支持
//设定网页的到期时间,一旦过期则必须到服务器上重新调用
response.setDateHeader("Expires",-1);
//Cache-Control指定请求和响应遵循的缓存机制 no-cache指示请求或响应消息不能缓存
response.setHeader("Cache-Control","no-cache");
//是用于设定禁止浏览器从本地机的缓存中调阅页面内容,设定后一旦离开网页就无法从Cache中再调出
response.setHeader("Pragma","no-cache");
login.jsp页面完成点击验证码换下一张的操作
<td><img src="${pageContext.request.contextPath}/imageServlet" id="pic" onclick="nextPic()"></td>
<script type="text/javascript">
function nextPic(){
var pic=document.getElementById("pic");
pic.src="${pageContext.request.contextPath}/imageServlet";
}
</script>
在LoginServlet.java中比对session中和jsp页面中的验证码
验证码只要求理解,不要求去写,用的时候就copy
- 2010.1.4 高级分页查询和session加强
- 分页高级查询步骤
- 分页与高级查询
- springMVC、myBatis的物理分页和高级查询
- springMVC、myBatis的物理分页和高级查询
- 高级查询公共分页包
- JavaWeb之高级分页查询
- JDBC的分页查询以及hibernate高级查询分页
- MyBatis分页的拓展--合并高级查询
- Mongodb高级查询Aggregation聚合组件分页
- c# linq的高级用法:分页查询和导出Excel共用一个方法
- 子查询和分页查询
- 查询优化和分页
- 查询优化和分页
- jpa 分页和查询
- Hibernate 高级查询技巧——分页查询
- Oracle数据库高级查询(二)分页查询
- mongoDB的高级查询和高级修改
- 学习的乐趣
- 学习编程语言
- 文件操作之:fstat、stat和lstat 区别
- 开始博客
- 面试后的反思
- 2010.1.4 高级分页查询和session加强
- 日记一则
- atl键盘钩子函数用法
- Resize View from Nib 的作用
- 通信中如何一次性完整地接收数据
- shell - 总结
- intel的cpu跑websphere 7居然比ibm的power pc更快
- ajax技术原理
- 图片操作(二)--保存DC到BMP文件 win32