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控制台,因为这样子并没有保存查询条件,点击后得到的不是查询结果。为了把查询信息保存起来,在点击这些超链接时也必须采用提交表单的方式。

    

     <href="javaScript:toPage(1,${pageBean.maxSize})">首页</a>

 <href="javaScript:toPage(${pageBean.prePage},${pageBean.maxSize})">上页</a>

 <href="javaScript:toPage(${pageBean.nextPage},${pageBean.maxSize})">下页</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

原创粉丝点击