为什么需要自定义标签
在开发项目过程中,我们经常有这样的体会:同一个控件我们可能多处使用,同时我们需要在基础的样式上加上自己的样式和操作的js代码;遇到这种情况,如果每个地方都copy代码的话那么,后期如果要做修改,那么维护的工作量是巨大的。基于这种情况,我们可以考虑使用自定义标签,实现代码的复用,易维护。
JSP自定义标签,实质上就是以标记的形式封装了一个俱有独立功能的Java类。标记的使用减少了直接嵌入JSP页面的Java代码,方便了页面的布局,并且有利于代码的复用,提高了开发的效率。
原理介绍
- JSP服务器解析标记的过程:
当一个用户访问一个JSP页面时,这个请求被发送到JSP服务器,JSP服务器会根据这个请求去调用相应的页面,如果这个页面中有自定义的标记, JSP服务就会根据页面指令<%@ taglib>去访问TLD得到处理程序的相关信息,接着调用该处理程序的构造器方法,启动标记符处理程序,并读取标记符的属性和相应值。 - TLD文件
TLD(TLD:Tag Library Descriptor标记库描述符)文件,标准的XML格式的标记定义文件,被用来存放标记符的信息。 - Taglib 指令
<%@ taglib uri=”URIToTagLibrary” prefix=”tagPrefix” %>
<% @ taglib %>指令声明此JSP文件使用了自定义的标记,同时引用标记库,也指定了他们的标记的前缀。必须在使用自定义标记之前使用<% @ taglib %>指令。
属性:
uri=”URIToTagLibrary” :Uniform Resource Identifier (URI)根据标记的前缀对自定义的标记进行唯一的命名,URI可以是一个相对或绝对的路径。
prefix=”tagPrefix”:在自定义标记之前的前缀。
举例代码
PageUtil.java代码
package com.util;
import java.util.List;
public class PageUtil<T> {
// 以下4个属性必须指定
private List<T> records; // 分页数据
private int totalRecord; // 总记录数
private int pageNo; // 当前页码,第几页
private int pageSize; // 每页显示的记录数,每页显示多少条数据
private int totalPage; // 总页数
private int startIndex; // 开始索引
private int endIndex; // 结束索引
private int indexCount = 10;// 显示的索引数目,如:10的话, 则显示1-10, 2-11
// public Pagination() {}
public PageUtil(List<T> records,int totalRecord,int pageNo, int pageSize) {
this.records = records;
this.totalRecord = totalRecord;
this.pageNo = pageNo;
this.pageSize = pageSize;
// 根据总记录数和每页显示数计算总页数(totalRecord+pageSize->totalPage)
totalPage = this.totalRecord / this.pageSize;
totalPage = (this.totalRecord % pageSize == 0) ? totalPage: (totalPage + 1);
// 计算显示索引数目
if (indexCount > totalPage) {
indexCount = totalPage;
}
// 根据索引数目,当前页,总页数计算开始索引和结束索引(indexCount+pageNo+totalPage->startIndex+endIndex)
startIndex = indexCount / 2;
startIndex = pageNo- (indexCount % 2 == 0 ? (startIndex - 1) : startIndex);
endIndex = pageNo + indexCount / 2;
// 1 <= startIndex < pageNo < endIndex <= totalPage
// startIndex = pageNo - indexCount/2
// endIndex = pageNo + indexCount/2
if (startIndex < 1) {
startIndex = 1;
if (totalPage >= indexCount) {
endIndex = indexCount;
} else {
endIndex = totalPage;
}
}
if (endIndex > totalPage) {
endIndex = totalPage;
if (endIndex > indexCount) {
startIndex = endIndex - indexCount + 1;
} else {
startIndex = 1;
}
}
}
/**
* 获取分页数据
*
* @return
*/
public List<T> getRecords() {
return records;
}
/**
* 获取总记录数
*
* @return
*/
public int getTotalRecord() {
return totalRecord;
}
/**
* 当前页数(第几页)
*
* @return
*/
public int getPageNo() {
return pageNo;
}
/**
* 每页显示数据记录数
*
* @return
*/
public int getPageSize() {
return pageSize;
}
/**
* 总页数
*
* @return
*/
public int getTotalPage() {
return totalPage;
}
/**
* 起始索引
*
* @return
*/
public int getStartIndex() {
return startIndex;
}
/**
* 结束索引
*
* @return
*/
public int getEndIndex() {
return endIndex;
}
/****************************************************************/
/************************ get/set方法 ******************************/
/****************************************************************/
public int getIndexCount() {
return indexCount;
}
public void setIndexCount(int indexCount) {
this.indexCount = indexCount;
}
@Override
public String toString() {
return "PageUtil [records=" + records + ", totalRecord=" + totalRecord
+ ", pageNo=" + pageNo + ", pageSize=" + pageSize
+ ", totalPage=" + totalPage + ", startIndex=" + startIndex
+ ", endIndex=" + endIndex + ", indexCount=" + indexCount + "]";
}
}
PageTag.java
package com.util;
import java.io.IOException;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class PageTag extends SimpleTagSupport {
/**
* 分页数据(required)
*/
private PageUtil pagination;
/**
* 请求路径
*/
private String href;
/**
* 分页div
*/
private String divId;
/**
* 分页样式
*/
private String divClass;
@Override
public void doTag() throws JspException, IOException {
// 缓冲字符串对象
StringBuffer strBuf = new StringBuffer();
strBuf.append("<script type=\"text/javascript\">\n");
strBuf.append("function paga_toPage(pageNo) {");
strBuf.append("window.location.href=\"").append(href);
if (href.indexOf("?") == -1) {
strBuf.append("?");
} else {
strBuf.append("&");
}
strBuf.append("pageNo=\"").append("+pageNo;").append("}");
strBuf.append(" </script> ");
strBuf.append(" <div id=\"").append(divId).append("\" class=\"")
.append(divClass).append("\"> ");
// 上一页
if (pagination.getPageNo() == 1) {
strBuf.append(" <a>◄</a>");
} else {
strBuf.append(" <a onclick=\"paga_toPage(")
.append(pagination.getPageNo() - 1)
.append(")\"> ◄ </a> ");
}
// 容器
strBuf.append(" <span>");
if (pagination.getStartIndex() != 1) {
// 显示第一页索引
strBuf.append(" <a").append(" onclick=\"paga_toPage(").append(1)
.append(");\">").append(1).append("</a> ");
}
// 显示省略号
if (pagination.getStartIndex() > 2) {
strBuf.append(" <i>...</i> ");
}
// 分页条主体
for (int i = pagination.getStartIndex(); i <= pagination.getEndIndex(); i++) {
if (pagination.getPageNo() == i) {
strBuf.append(" <a class=\"current\">").append(i)
.append("</a> ");
} else {
strBuf.append(" <a onclick=\"paga_toPage(").append(i)
.append(");\">").append(i).append("</a> ");
}
}
// 显示省略号
if (pagination.getEndIndex() < pagination.getTotalPage() - 1) {
strBuf.append(" <i>...</i> ");
}
if (pagination.getEndIndex() != pagination.getTotalPage()) {
// 显示最后一页索引
strBuf.append(" <a").append(" onclick=\"paga_toPage(")
.append(pagination.getTotalPage()).append(");\">")
.append(pagination.getTotalPage()).append("</a>");
}
// 容器结尾
strBuf.append(" </span> ");
// 下一页
if (pagination.getPageNo() == pagination.getTotalPage()) {
strBuf.append(" <a>►</a> ");
// strBuf.append("<a">末页</a> ");
} else {
strBuf.append(" <a onclick=\"paga_toPage(")
.append(pagination.getPageNo() + 1)
.append(")\"> ► </a> ");
// strBuf.append(" <a onclick=\"paga_toPage(").append(pagination.getTotalPage()).append(")\">末页</a> ");
}
strBuf.append(" </div> ");
JspContext ctx = getJspContext();
// 获取页面输出流,并输出字符串
JspWriter out = ctx.getOut();
out.print(strBuf.toString());
}
public PageUtil getPagination() {
return pagination;
}
public void setPagination(PageUtil pagination) {
this.pagination = pagination;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public String getDivId() {
return divId;
}
public void setDivId(String divId) {
this.divId = divId;
}
public String getDivClass() {
return divClass;
}
public void setDivClass(String divClass) {
this.divClass = divClass;
}
}
PageTag.tld
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>自定义标签类</description>
<tlib-version>1.0</tlib-version>
<short-name>Mytaglib</short-name>
<uri>/MyPageTag</uri>
<tag>
<description>分页标签</description>
<name>Pagination</name>
<tag-class>com.util.PageTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>pagination</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.Object</type>
</attribute>
<attribute>
<name>divId</name>
<required>false</required>
</attribute>
<attribute>
<name>divClass</name>
<required>false</required>
</attribute>
<attribute>
<name>href</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
page.css
@CHARSET "UTF-8";
#pagination {
display: inline-block;
vertical-align: middle;
border-radius: 4px;
padding: 1px 2px 4px 2px;
border-top: 1px solid #AEAEAE;
border-bottom: 1px solid #FFFFFF;
background-color: #DADADA;
background-image: -webkit-linear-gradient(top, #DBDBDB, #E2E2E2);
background-image: -moz-linear-gradient(top, #DBDBDB, #E2E2E2);
background-image: -ms-linear-gradient(top, #DBDBDB, #E2E2E2);
background-image: -o-linear-gradient(top, #DBDBDB, #E2E2E2);
background-image: linear-gradient(top, #DBDBDB, #E2E2E2);
}
#pagination a, #pagination i {
display: inline-block;
vertical-align: middle;
width: 22px;
color: #7D7D7D;
text-align: center;
font-size: 10px;
padding: 3px 0 2px 0;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
-o-user-select:none;
user-select:none;
}
#pagination a {
margin: 0 2px 0 2px;
border-radius: 4px;
border: 1px solid #E3E3E3;
cursor: pointer;
box-shadow: inset 0 1px 0 0 #FFF, 0 1px 2px #666;
text-shadow: 0 1px 1px #FFF;
background-color: #E6E6E6;
background-image: -webkit-linear-gradient(top, #F3F3F3, #D7D7D7);
background-image: -moz-linear-gradient(top, #F3F3F3, #D7D7D7);
background-image: -ms-linear-gradient(top, #F3F3F3, #D7D7D7);
background-image: -o-linear-gradient(top, #F3F3F3, #D7D7D7);
background-image: linear-gradient(top, #F3F3F3, #D7D7D7);
}
#pagination i {
margin: 0 3px 0 3px;
}
#pagination a.current {
border: 1px solid #E9E9E9;
box-shadow: 0 1px 1px #999;
background-color: #DFDFDF;
background-image: -webkit-linear-gradient(top, #D0D0D0, #EBEBEB);
background-image: -moz-linear-gradient(top, #D0D0D0, #EBEBEB);
background-image: -ms-linear-gradient(top, #D0D0D0, #EBEBEB);
background-image: -o-linear-gradient(top, #D0D0D0, #EBEBEB);
background-image: linear-gradient(top, #D0D0D0, #EBEBEB);
}
使用说明:
PageTag.tld放在WEB-INF目录下
引入
<%@taglib uri=”/MyPageTag” prefix=”Mytaglib”%>
page.css
调用
<Mytaglib:Pagination pagination="PageUtil" divId="divId" href="Action"/>