什么是自定义标签
自定义标签可以有效的将HTML代码与java代码分离
首先说一下自定义标签的开发步骤
1.编写标签处理器类
(1)实现javax.servlet.jsp.tagext.Tag接口,重写doStartTag()方法
(2)实现javax.servlet.jsp.tagext.SimpleTag接口,重写doTag()方法
定义了JSP页面与标签处理类之间的通信规则。
2.编写标签库描述符(tld)文件
要想让JSP引擎在遇到自定义标签时,能找到其所对应的标签处理器类,必须编写一个标签库描述符
tld文件可以注册多个标签处理器类,这样就形成了自定义标签库
注意:TLD文件是基于xml文件的,其内容的编写需要遵循xml语法规范
3.在JSP页面导入和使用自定义标签
<%@taglib uri="" prefix=""%>
注意:uri需要与TLD文件中<uri>元素的值一致
1.继承SimpleTagSupport(标签处理类)
package com.bookstore.utils;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
public class PageTag extends SimpleTagSupport {
/**
* 定义请求URL中的占位符常量
*/
private static final String TAG = "{0}";
/**
* 当前页码
*/
private int pageIndex;
/**
* 每页显示的数量
*/
private int pageSize;
/**
* 总记录条数
*/
private int recordCount;
/**
* 请求URL page.action?pageIndex={0}
*/
private String submitUrl;
/**
* 样式
*/
private String style = "sabrosus";
/**
* 定义总页数
*/
private int totalPage = 0;
/**
* 在页面上引用自定义标签就会触发一个标签处理类
*/
@Override
public void doTag() throws JspException, IOException {
/** 定义它拼接是终的结果 */
StringBuilder res = new StringBuilder();
/** 定义它拼接中间的页码 */
StringBuilder str = new StringBuilder();
/** 判断总记录条数 */
if (recordCount > 0) { //1499 / 15 = 100
/** 需要显示分页标签,计算出总页数 需要分多少页 */
totalPage = (this.recordCount - 1) / this.pageSize + 1;
/** 判断上一页或下一页需不需要加a标签 */
if (this.pageIndex == 1) { // 首页
str.append("<span class='disabled'>上一页</span>");
/** 计算中间的页码 */
this.calcPage(str);
/** 下一页需不需要a标签 */
if (this.pageIndex == totalPage) {
/** 只有一页 */
str.append("<span class='disabled'>下一页</span>");
} else {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex + 1));
str.append("<a href='" + tempUrl + "'>下一页</a>");
}
} else if (this.pageIndex == totalPage) { // 尾页
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex - 1));
str.append("<a href='" + tempUrl + "'>上一页</a>");
/** 计算中间的页码 */
this.calcPage(str);
str.append("<span class='disabled'>下一页</span>");
} else { // 中间
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex - 1));
str.append("<a href='" + tempUrl + "'>上一页</a>");
/** 计算中间的页码 */
this.calcPage(str);
tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex + 1));
str.append("<a href='" + tempUrl + "'>下一页</a>");
}
/** 拼接其它的信息 */
res.append("<table width='100%' align='center' style='font-size:13px;' class='" + style + "'>");
res.append("<tr><td style='COLOR: #0061de; MARGIN-RIGHT: 3px; PADDING-TOP: 2px; TEXT-DECORATION: none'>" + str.toString());
res.append(" 跳转到 <input style='text-align: center;BORDER-RIGHT: #aaaadd 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #aaaadd 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 2px; MARGIN: 2px; BORDER-LEFT: #aaaadd 1px solid; COLOR: #000099; PADDING-TOP: 2px; BORDER-BOTTOM: #aaaadd 1px solid; TEXT-DECORATION: none' type='text' size='2' id='pager_jump_page_size'/>");
res.append(" <input type='button' style='text-align: center;BORDER-RIGHT: #dedfde 1px solid; PADDING-RIGHT: 6px; BACKGROUND-POSITION: 50% bottom; BORDER-TOP: #dedfde 1px solid; PADDING-LEFT: 6px; PADDING-BOTTOM: 2px; BORDER-LEFT: #dedfde 1px solid; COLOR: #0061de; MARGIN-RIGHT: 3px; PADDING-TOP: 2px; BORDER-BOTTOM: #dedfde 1px solid; TEXT-DECORATION: none' value='确定' id='pager_jump_btn'/>");
res.append("</td></tr>");
res.append("<tr align='center'><td style='font-size:13px;'><tr><td style='COLOR: #0061de; MARGIN-RIGHT: 3px; PADDING-TOP: 2px; TEXT-DECORATION: none'>");
/** 开始条数 */
int startNum = (this.pageIndex - 1) * this.pageSize + 1;
/** 结束条数 */
int endNum = (this.pageIndex == this.totalPage) ? this.recordCount : this.pageIndex * this.pageSize;
res.append("总共<font color='red'>" + this.recordCount + "</font>条记录,当前显示" + startNum + "-" + endNum + "条记录。");
res.append("</td></tr>");
res.append("</table>");
res.append("<script type='text/javascript'>");
res.append(" document.getElementById('pager_jump_btn').onclick = function(){");
res.append(" var page_size = document.getElementById('pager_jump_page_size').value;");
res.append(" if (!/^[1-9]\\d*$/.test(page_size) || page_size < 1 || page_size > " + this.totalPage + "){");
res.append(" alert('请输入[1-" + this.totalPage + "]之间的页码!');");
res.append(" }else{");
res.append(" var submit_url = '" + this.submitUrl + "';");
res.append(" window.location = submit_url.replace('" + TAG + "', page_size);");
res.append(" }");
res.append("}");
res.append("</script>");
} else {
res.append("<table align='center' style='font-size:13px;'><tr><td style='COLOR: #0061de; MARGIN-RIGHT: 3px; PADDING-TOP: 2px; TEXT-DECORATION: none'>总共<font color='red'>0</font>条记录,当前显示0-0条记录。</td></tr></table>");
}
this.getJspContext().getOut().print(res.toString());
}
/**
* 计算中间页码的方法
*/
private void calcPage(StringBuilder str) {
/** 判断总页数 */
if (this.totalPage <= 11) {
/** 一次性显示全部的页码 */
for (int i = 1; i <= this.totalPage; i++) {
if (this.pageIndex == i) {
/** 当前页码 */
str.append("<span class='current'>" + i + "</span>");
} else {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<a href='" + tempUrl + "'>" + i + "</a>");
}
}
} else {
/** 靠近首页 */
if (this.pageIndex <= 8) {
for (int i = 1; i <= 10; i++) {
if (this.pageIndex == i) {
/** 当前页码 */
str.append("<span class='current'>" + i + "</span>");
} else {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<a href='" + tempUrl + "'>" + i + "</a>");
}
}
str.append("...");
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(this.totalPage));
str.append("<a href='" + tempUrl + "'>" + this.totalPage + "</a>");
}
/** 靠近尾页 */
else if (this.pageIndex + 8 >= this.totalPage) {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(1));
str.append("<a href='" + tempUrl + "'>1</a>");
str.append("...");
for (int i = this.totalPage - 10; i <= this.totalPage; i++) {
if (this.pageIndex == i) {
/** 当前页码 */
str.append("<span class='current'>" + i + "</span>");
} else {
tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<a href='" + tempUrl + "'>" + i + "</a>");
}
}
}
/** 在中间 */
else {
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(1));
str.append("<a href='" + tempUrl + "'>1</a>");
str.append("...");
for (int i = this.pageIndex - 4; i <= this.pageIndex + 4; i++) {
if (this.pageIndex == i) {
/** 当前页码 */
str.append("<span class='current'>" + i + "</span>");
} else {
tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<a href='" + tempUrl + "'>" + i + "</a>");
}
}
str.append("...");
tempUrl = this.submitUrl.replace(TAG, String.valueOf(this.totalPage));
str.append("<a href='" + tempUrl + "'>" + this.totalPage + "</a>");
}
}
}
/**
* setter 方法
*/
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public void setRecordCount(int recordCount) {
this.recordCount = recordCount;
}
public void setSubmitUrl(String submitUrl) {
this.submitUrl = submitUrl;
}
public void setStyle(String style) {
this.style = style;
}
}
2.编写标签库描述符(tld)文件
这个文件需要放在webapp.WEB-INF下
<?xml version="1.0" encoding="utf-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<!-- 描述 自定义标签版本的一种描述 -->
<description>Pager 1.0 core library</description>
<!-- 显示的名称 导包进行的一个展示 -->
<display-name>Pager core</display-name>
<!-- 版本号 -->
<tlib-version>1.0</tlib-version>
<!-- 短名 -->
<short-name>fkjava</short-name>
<!-- uri :导包 -->
<uri>http://yyf.pager-tags</uri>
<!-- 定义一个标签 -->
<tag>
<!-- 标签名 -->
<name>pager</name>
<!-- 标签处理类 -->
<tag-class>com.bookstore.utils.PageTag</tag-class>
<!-- 设置标签为空 -->
<body-content>empty</body-content>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 表示分页的第几页 -->
<name>pageIndex</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 表示分页标签 ,每页显示多少条数据 -->
<name>pageSize</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 记录分页的总数 -->
<name>recordCount</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 -->
<name>submitUrl</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 -->
<name>style</name>
<!-- 必须的 -->
<required>false</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
3.在JSP页面导入和使用自定义标签
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="l" uri="http://yyf.pager-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>bookStore列表</title>
<%--导入css --%>
<link rel="stylesheet" href="${pageContext.request.contextPath }/client/css/main.css" type="text/css" />
</head>
<body class="main">
<jsp:include page="head.jsp" />
<jsp:include page="menu_search.jsp" />
<div id="divpagecontent">
<table width="100%" border="0" cellspacing="0">
<tr>
<td><div style="text-align:right; margin:5px 10px 5px 0px">
<a href="${pageContext.request.contextPath }/index.jsp">首页</a> >
${category} > 图书列表
</div>
<table cellspacing="0" class="listcontent">
<tr>
<td>
<h1>商品目录</h1>
<hr />
<h1>${category}</h1> 共${pageModel.recordCount}种商品
<hr />
<div style="margin-top:20px; margin-bottom:5px">
<img src="${pageContext.request.contextPath }/client/images/productlist.gif" width="100%" height="38" />
</div>
<table cellspacing="0" class="booklist">
<tr>
<c:forEach items="${products}" var="p" varStatus="vs">
<td>
<div class="divbookpic">
<p>
<a href="${pageContext.request.contextPath}/client/product/findProductById?id=${p.id}">
<img src="${pageContext.request.contextPath}${p.imgurl}" width="115" height="129" border="0" />
</a>
</p>
</div>
<div class="divlisttitle">
<a href="${pageContext.request.contextPath}/client/product/findProductById?id=${p.id}">书名: ${p.name}<br />售价:¥${p.price} </a>
</div>
</td>
</c:forEach>
</tr>
</table>
<div class="pagination">
<yyf:pager
pageIndex="${pageModel.pageIndex}"
pageSize="${pageModel.pageSize}"
recordCount="${pageModel.recordCount}"
submitUrl="${pageContext.request.contextPath}/client/product/findProductByCategory?pageIndex={0}&category=${category}"
/>
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<jsp:include page="foot.jsp" />
</body>
</html>