JSP自定义标签开发(八)—— xx.tag自定义标签开发之分页标签(jquery + div +css 美化)

来源:互联网 发布:Js代码高亮 编辑:程序博客网 时间:2024/05/17 23:33

        去年刚出从学校里走出来,由于大学教育理论与实际的脱节,我也不例外成了其牺牲品之一。在上一家公司的时候看到他们将分页 和 用户权限限制 这样的常用的功能封装成 标签,使用起来十分的方便。虽然实际的开发中,像我们这种刚进去的小罗罗只需要会调用就好了,但是自己的好奇心使然,总是想如果我要自己大件框架要自己实现这这些功能的封装,我要怎么办呢?所以,我必须去把它们学会。由于公司的那套框架封装的东西很多,层层叠叠的,每次去深究都看得我头昏脑胀的,其实主要还是自己以前在学校贪玩好耍,学艺不精,呵呵呵!这样反反复复的,第一年过去了,我还是没有真正的弄懂它们,真的是说来惭愧得很啦!

由于一遍一遍的看,在加上网上的资料实在少得可怜,没有哪个 好心人愿意分享一些正儿八经的正餐,通常大多是一些残羹冷炙的边角料。一遍一遍的看,再加上网上资料的搜索,终于是看懂了公司的那个分页标签的实现原理与细节。

原来的公司,用的是SSM (struts2.X + spring3.X + myBatis)的封装框架。所以那个分页标签就是实用的struts2的标签开发。xx.tld的标签类继承的是struts2 的标签类 而不是我们 通常直接看到的 TagSupport 或BodyTagSupport .标签页面的美化展现就使用 freemarker 的技术,在freemarker中使用css、jquery 那是一件多么幸福的事情啊。个人觉得这样才是所谓的mvc的开发思想嘛。类里面写逻辑,封装Pager 常用分页信息到 request 或 parameter 中去,再在 freemarker 中做 “首页” “尾页” 以及 页码数字 和 它们的样式美化的展现。到此,我想要看到的结果似乎已经看到了,所谓的分页技术我似乎就已经学会了。

然而,我是否真的学会了这个功能呢?假如,我用的不是 struts2 来做控制层又该怎么解决呢?比如现在比较流行好用的 spring mvc 也是很好的控制层啊。

随着这问题的抛出,我的思绪似乎又回到了零起点。我在网上寻寻觅觅,寻寻觅觅,可就是看不到我想要的mvc模式的分页标签功能实现。搜到的资料几乎都是在  xx.tld 对应的标签类中 既书写逻辑,又做 页码数字 与 样式的打印,一大堆的 双引号的 转义字符……,要在java类中实现 css 样式定位 与 javascript 的动作控制,那是一件多么痛苦的事情啊。简直忍无可忍。(给个例子瞧瞧)

public class PagerTag extends TagSupport {      private String value = "pb";// 存放数据实体的名字      public void setValue(String value) {         this.value = value;     }      @Override     public int doStartTag() throws JspException {         JspWriter out = pageContext.getOut();         String outStr = makeString();         try {             out.write(outStr);         } catch (IOException e) {             e.printStackTrace();         }          return SKIP_BODY;     }          private String makeString() {          // 获取到存放在request中的数据实体         Object p = pageContext.getRequest().getAttribute(                 value);         PageBean pageBean = (PageBean) pageContext.getRequest().getAttribute(value);                  StringBuffer sb = new StringBuffer();                  if (pageBean != null && pageBean.getItems() != null                 && pageBean.getItems().size() > 0) {              sb.append("共" + pageBean.getCurPage() + " / "                     + pageBean.getPageNum() + "页");             //首页 上一页             if (pageBean.getCurPage() > 1) {                 sb.append("<a href='?page=1'>首页</a>");                 sb.append("<a href='?page=" + (pageBean.getCurPage()-1) + "'>上一页</a>");             }                          //循环显示中间页码,这里也可控制最大只显示多少页码             for (int i = 1; i < pageBean.getPageNum() + 1; i++) {                  if (i == pageBean.getCurPage()) {                     sb.append(" " + i + " ");                 } else {                     sb.append("<a href='?page=" + i + "'> " + i + " </a>");                 }             }                          //下一页 末页             if(pageBean.getCurPage() != pageBean.getPageNum()){                 sb.append("<a href='?page=" + (pageBean.getCurPage() + 1) + "'>下一页</a>");                 sb.append("<a href='?page=" + pageBean.getPageNum() + "'>末页</a>");             }          }                  return sb.toString();     }  } 
看着都痛苦,简直要吐血的节奏啊,反正我是忍受不了这样的开发的,而且做出来的标签展现很丑的。

在没有看到它的日子里,我的生命里暗淡无光,总以为自己再也迈不开这个坎儿了。就在我几竟绝望的时候,我在自己买的那本spring企业开发实战一书中的一个例子中得到了灵感,找到了答案。从此这个分页功能实现的难度,在我面前变得荡然无存。哈哈哈,那一刻我心里简直爆发着灿烂的原子弹是的喜悦巨浪。那种喜悦与成就干难以被抑制啊。

下面进入正题!

对于jsp自定义标签的实现,大多数人知道xx.tld这种方法,其实还有一种方法的 xx.tag 实现。即:

1.xx.tld + 标签类 来实现;

2.xx.tag 文件来实现。

这两种方式都有各自的优缺点。第一种方法中因为有java类,任何复杂的逻辑,对它而言都是小儿科;第二种方法中,因为xx.tag文件就像jsp 中的include的使用,所以在xx.tag中就可以像实用jsp那样,可以写html 、css 、jquery,所以对于任何 酷炫的前端展现对它而言都是庖丁解牛的游刃有余。

分析一下便知道,分页标签重在于前端数字展现的人性化,复杂的逻辑也是集中在前端展现的逻辑,这完全可以用jquery 来轻轻松松地搞定的嘛。所以,就我个人而言,分页标签的实现最好的方法应该是 采用 xx.tag 的方式来实现,最最重要的事情是,这种方法是通用的,他不依赖于任何框架技术(如,常用的 struts2 和 spring). 有了它,分页标签的实现从此将变得是一次幸福愉快的开发之旅;有了它,分页标签的开发才真正是 美观、简单、快速高效 的代名词。

下面进入 xx.tag 分页标签开发的实际开发步骤!

xx.tag标签的开发只需要两个步骤:

1、pageBar.tag展示文件的创建与编辑;(放置路径:WEB-INF/tags/  )

2、使用标签页面的实用。(这里用的是usrListPaged.jsp)

下面贴出具体代码:

1、pageBar.tag

<%@ tag pageEncoding="utf-8" %><!-- 声明JSTL标签,以便在本标签中使用 --><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!-- 定义了两个标签属性 --><%@ attribute name="formID" required="true" rtexprvalue="true"  description="搜索条件提交的表单ID" %><%@ attribute name="isShowTotalPages" required="false" rtexprvalue="true" type="java.lang.Boolean"  description="是否显示总页数" %><%@ attribute name="isShowJumpToButton" required="false" rtexprvalue="true" type="java.lang.Boolean"  description="是否显示跳转按钮" %><div id="div_pager"><a  onclick="getLink(1)">首页</a><a  onclick="getLink(${customPage.currentPage -1})"><<上一页</a><%--  <c:forEach var="pageNo"  begin="1" end="${customPage.totalPages}" step="1"><c:choose><c:when test="${pageNo == customPage.currentPage }"> <span class="curr"><c:out value="${pageNo }"></c:out></span></c:when><c:otherwise><a  onclick="getLink(${pageNo })"><c:out value="${pageNo }"></c:out></a></c:otherwise></c:choose></c:forEach>  --%><label id="pagerNO"></label><a  onclick="getLink(${customPage.currentPage +1})">下一页>></a><a  onclick="getLink(${customPage.totalPages})">尾页</a><c:if test="${isShowTotalPages == null || isShowTotalPages != false }"><label id="totalPage">共${customPage.totalPages}页</label><label id="totalRecords">/${customPage.totalRows}条数据</label></c:if><c:if test="${isShowJumpToButton == null || isShowJumpToButton != false }"><label  id="go_page_wrap" class="normalsize">转到<span style="margin:0px 1px;padding:0px;"><input type="text" id="btn_go_input" maxlength="5" value="${customPage.currentPage}" /><input type="button" id="btn_go" value="确定"/></span>页</label></c:if></div><script type="text/javascript">$(function(){  //当前页码  var currentPage = ${customPage.currentPage};  //总页码    var totalPages = ${customPage.totalPages};  //总数据条数        var totalRows = ${customPage.totalRows};            var pageHtml = '';      var dot = '<span style="FONT-WEIGHT: normal;">...</span>';  //--------function in input text to jump into the page-------------//  $("#btn_go_input").focus(function(){  var $btn_go = $("#btn_go");  $btn_go.css("display","inline");  });  $("#btn_go_input").blur(function(){  validateInputPageNO()  });  $("#btn_go").click(function(){validateInputPageNO();  });    //----------------------------//      // 1.总页数不足9页,就全部显示      if(totalPages < 9){      for(var i=1; i<totalPages; i++){      if(currentPage == i){      pageHtml += '<span class="curr">'+ i +'</span>';      }else{      pageHtml += '<a onClick="getLink('+ i +')" title="第'+ i +'页">'+ i +'</a>';      }      }// end for loop      }else{      //2.总页数 9页及以上      if(currentPage <= 5){ // 2.1 当前页码小于 6, 1到7页全显示,最后面用 '...' 代替      for(var i=1; i<=7; i++){      if(currentPage == i){      pageHtml += '<span class="curr">'+ i +'</span>';      }else{      pageHtml += '<a onClick="getLink('+ i +')" title="第'+ i +'页">'+ i +'</a>';      }      }// end for loop      pageHtml += dot;      }else{      // 2.2当前页码为6及以上      pageHtml += '<a onClick="getLink(1)" title="第1页">1</a>';      pageHtml += '<a onClick="getLink(2)" title="第2页">2</a>';      pageHtml += dot;            var begin = currentPage - 2;      var end   = currentPage + 2;            if(end > totalPages){// 计算出来的end页码超过总页数,end取尾页      end = totalPages;      begin = end -4;      if(currentPage - begin < 2){      begin = begin - 1;      }      }else if(end + 1 == totalPages){      end = totalPages;      }//end else if            for(var i=begin; i<=end; i++){      if(currentPage == i){      pageHtml += '<span class="curr">'+ i +'</span>';      }else{      pageHtml += '<a onClick="getLink('+ i +')" title="第'+ i +'页">'+ i +'</a>';      }      }// end for loop            if(end != totalPages){      pageHtml += dot;      }//end if            }//end else 2.2当前页码为6及以上      }//end more than 8 pages      $("#pagerNO").html(pageHtml);  });// jump to the pagefunction getLink(n){var $form = $("#${formID}");var jdf_currentPage = '<input type="hidden" name="jdf_currentPage" value="'+n+'"/>';$form.append(jdf_currentPage);$form.submit();}// validdate the page .NO in input function validateInputPageNO(){var str_page = $("#btn_go_input").val();     if(isNaN(str_page)){       $("#btn_go_input").val(1);       return;   }   var n = parseInt(str_page);        // jump to the pagegetLink(n);}</script><style><!--#div_pager{      clear:both;      height:30px;    line-height:30px;      margin-top:20px;      color:black;    font-size:12px;}  #div_pager a{    padding:4px 8px;      margin:10px 3px;      border:1px solid #FF6600;     background-color:#FFF;      color:#FF6600;      text-decoration:none;     FONT-WEIGHT: bold;  }    #div_pager span{      padding:4px 8px;      margin:10px 3px;      font-size:14px;    FONT-WEIGHT: bold;}    #div_pager span.disabled{      padding:4px 8px;      margin:10px 3px;      border:1px solid #DFDFDF;      background-color:#FFF;      color:#DFDFDF;  }    #div_pager span.curr{      padding:4px 8px;      margin:10px 3px;      border:1px solid #FF6600;      background-color:#FF6600;      color:#FFF;  }    #div_pager a:hover{      background-color:#FFEEE5;      border:1px solid #FF6600;     cursor:pointer;    FONT-WEIGHT: bold;  }    #btn_go_input{width:42px;height:25px;line-height:25px;text-align:center;}#btn_go{margin:0px;padding:0px;width:40px;height:20px;line-height:20px;padding:0px;font-family:arial,宋体,sans-serif;text-align:center;border:0px;background-color:#0063DC;color:#FFF;display:none;}--></style> 

此页面需要注意这样几点:

1)、页面实用到了jquery,所以在引用此标签的jsp页面中一定要引入一个jquery包;

2)、也面中的customPage对象是一个Pager 对象,里面封装了常用页面处理信息(总记录数、总页数、当前页等)

这个对象需要封装到request 或者 各自使用框架的 类似的对象上,只要你的jsp 页面中能够访问到 pager对象就行;

3)、标签中使用到的属性,在xx.tag中可以通过 ${} 取得值,比如我这里要在pageBar.tag中取得jsp 页面中

<pager:pageBar formID="user_loadUserList" isShowTotalPages="false" isShowJumpToButton="true"/>

formID、 isShowTotalPages 和 isShowJumpToButton的值, 那就用了${} 来取值的。


2、usrListPaged.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@taglib prefix="pager" tagdir="/WEB-INF/tags" %>
<%
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
request.setAttribute("path", basePath);
%>

<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>用户创建成功</title>
    
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<script type="text/javascript" src="${path}/js/commons/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="${path}/js/commons/jquery.json-2.4.js"></script>
<style type="text/css">
body{
font-size: 12pt;
margin: 0;
padding: 0;
}
.button{
margin:0;
padding-left:5px;
padding-right:5px;
height: 30px;
line-height: 30px;
border: 2px solid black;
background-color: yellow;
}

</style>
  </head>
  
  <body>
  <form action="${path }/user/loadUserList.shtml"id="user_loadUserList">
  用户名:<input type="text" id="userName" name="userName" maxlength="20" value="${filter.userName }"/>
  <input type="submit" class="button" value="提交"/>
  </form>
  <br>
    <table id="friends"  width="700" border="1" cellspacing="0" cellpadding="0" >
    <caption style="margin-bottom:10px;">查看所有好友信息</caption>
    <thead>
    <tr bgcolor="yellow" height="30">
    <th width="30%">用户名</th>
    <th width="30%">密码</th>
    <th width="40%">真是姓名</th>
    </tr>
    </thead>
    <tbody>
    <c:if test="${userList != null}">
    <c:forEach items="${userList}" var="user">
    <tr height="30">
    <td>${user.userName }</td>
    <td>${user.password }</td>
    <td>${user.realName }</td>
    </tr>
    </c:forEach>
    </c:if>
    <c:if test="${userList == null}">
    <tr height="30">
    <td colspan="3" align="center">没有数据</td>
    </tr>
    </c:if>
    </tbody>
    </table>
    <pager:pageBarformID="user_loadUserList" isShowTotalPages="false" isShowJumpToButton="true"/>
  </body>
  
<script type="text/javascript">
$(function(){
//alert("aaaaaaaaaaaaaaaa");
});
</script>  
</html>

本文件注意的部分就是 描红 的部分了。

分页功能的总结: 前端分页 提交给后台 Java类的关键参数就是  当前的搜索条件、当前页号。所以,我的标签里面是给标签处理文件提供 formID 而不是 url地址。后台代码在封装时也要满足这样一条准则,使用你标签的用户只需关注他自己的业务需求,其他的一切分页工作都由你来封装实现。


也许说多了大家也不太相信,好吧,下面给大家秀一秀最终效果吧。












哈哈,就扯到这里吧,感觉如何呢?


0 0
原创粉丝点击