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

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

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

原来的公司,用的是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  οnclick="getLink(1)">首页</a>
<a  οnclick="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  οnclick="getLink(${pageNo })"><c:out value="${pageNo }"></c:out></a>
		</c:otherwise>
	</c:choose>
</c:forEach>  --%>
<label id="pagerNO"></label>

<a  οnclick="getLink(${customPage.currentPage +1})">下一页>></a>
<a  οnclick="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 page
function 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 page
	getLink(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地址。后台代码在封装时也要满足这样一条准则,使用你标签的用户只需关注他自己的业务需求,其他的一切分页工作都由你来封装实现。


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












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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值