完整版见
https://jadyer.github.io/
代码才是硬道理,本人喜欢把话语权交给代码,请往下看。。
首先是web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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-app_2_5.xsd">
<servlet>
<servlet-name>Mp3</servlet-name>
<servlet-class>com.jadyer.servlet.Mp3Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Mp3</servlet-name>
<url-pattern>/servlet/Mp3</url-pattern>
</servlet-mapping>
<!-- 在version="2.5"中,可以直接在<welcome-file-list>里执行Servlet应用 -->
<welcome-file-list>
<welcome-file>servlet/Mp3</welcome-file>
</welcome-file-list>
</web-app>
用到的实体类Mp3.java
package com.jadyer.model;
public class Mp3 {
private Integer id; //歌曲编号
private String name; //歌曲名
private String singer; //歌曲演唱者
private String author; //歌曲作者
private Double size; //歌曲大小
/*--它们的setter和getter略--*/
}
这是我们自定义的异常类MyRuntimeException.java
package com.jadyer.exception;
/**
* 自定义异常类
*/
@SuppressWarnings("serial")
public class MyRuntimeException extends RuntimeException {
/**
* 直接构造一个RuntimeException
* @see 而不抛任何东西
*/
public MyRuntimeException() {
super();
}
/**
* 只抛出提示信息
* @param message---错误提示信息
*/
public MyRuntimeException(String message) {
super(message);
}
/**
* 只抛出异常类对象
* @param cause-----所抛出的异常类对象
*/
public MyRuntimeException(Throwable cause) {
super(cause);
}
/**
* 抛出提示信息和异常类对象
* @param message---错误提示信息
* @param cause-----所抛出的异常类对象
* @see 一般情况下都使用该方法
*/
public MyRuntimeException(String message, Throwable cause) {
super(message, cause);
}
}
这是用于连接Oracle数据库的工具类OracleConnUtil.java
package com.jadyer.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.jadyer.exception.MyRuntimeException;
/**
* 我们的目的是只装载一次驱动类,这时有两个办法可以实现
* @see 第一个办法是使用单子模式。使用该模式的人居多
* @see 第二个办法是使用static语句块
* @see public OracleConnUtil(){}
* @see static{
* @see try {
* @see Class.forName(DB_DRIVER);
* @see } catch (ClassNotFoundException e) {
* @see e.printStackTrace();
* @see throw new MyRuntimeException("数据库驱动装载失败", e);
* @see }
* @see }
*/
public class OracleConnUtil {
//由于以下四个都是常量,所以用final修饰
//那么既然是常量,所以在内存中只存在一份就可以了,所以用static修饰
//并且final和static是经常在一起使用的
private static final String DB_DRIVER = "oracle.jdbc.OracleDriver";
private static final String DB_URL = "jdbc:oracle:thin:@127.0.0.1:1521:jadyer";
private static final String DB_USERNAME = "scott";
private static final String DB_PASSWORD = "jadyer";
private static OracleConnUtil oracleConn;
Connection conn = null;
/**
* 获得数据库连接的实例
*/
public static OracleConnUtil getInstance(){
if(null == oracleConn){
oracleConn = new OracleConnUtil();
}
return oracleConn;
}
/**
* 装载数据库驱动
*/
private OracleConnUtil(){
try {
Class.forName(DB_DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new MyRuntimeException("数据库驱动装载失败", e);
}
}
/**
* 连接数据库
*/
public Connection getConnection(){
try {
conn = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
//我们完全可以测试一下,没有启动Oracle服务的情况下,运行项目
//这时会在浏览器中显示很多异常信息,并提示这里自定义的消息:【数据库连接失败】
throw new MyRuntimeException("数据库连接失败", e);
}
return conn;
}
/**
* 关闭数据库链接
*/
public static void close(ResultSet rs, PreparedStatement ps, Connection conn){
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(ps!=null){
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
下面是关于分页操作的接口类Mp3Dao.java
package com.jadyer.dao;
import java.util.List;
import com.jadyer.model.Mp3;
public interface Mp3Dao {
/**
* 设置每页显示的记录数
*/
void setCountPerPage(int countPerPage);
/**
* 获取总页数
*/
int getTotalPage();
/**
* 获取总记录数
*/
int getTotalCount();
/**
* 按页获取记录
*/
List<Mp3> queryPerPage(int page);
}
下面是关于分页操作的接口实现类Mp3DaoImpl.java
package com.jadyer.dao.imp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.jadyer.dao.Mp3Dao;
import com.jadyer.exception.MyRuntimeException;
import com.jadyer.model.Mp3;
import com.jadyer.util.OracleConnUtil;
public class Mp3DaoImpl implements Mp3Dao{
int countPerPage = 10; //每页显示的记录数,默认为10
private static final String SQL_TOTAL_COUNT = "select count(*) from t_mp3";
private static final String SQL_QUERY_PERPAGE = "select * from" +
" (select m.*, ROWNUM rn from" +
" (select * from t_mp3 order by s_id) m" +
" where ROWNUM <= ?)" +
" where rn >= ?";
public void setCountPerPage(int countPerPage) {
this.countPerPage = countPerPage;
}
public int getTotalCount() {
int totalCount = 0; //总记录数
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = OracleConnUtil.getInstance().getConnection();
ps = conn.prepareStatement(SQL_TOTAL_COUNT);
rs = ps.executeQuery();
if(rs.next()){
totalCount = rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
throw new MyRuntimeException("查询总记录数失败", e);
}finally{
OracleConnUtil.close(rs, ps, conn);
}
return totalCount;
}
public int getTotalPage() {
int totalCount = this.getTotalCount(); //总记录数
int totalPage = 0; //总页数
// totalPage = (totalCount + countPerPage - 1) / countPerPage;
if(totalCount % countPerPage == 0){
totalPage = totalCount / countPerPage;
}else{
totalPage = totalCount / countPerPage + 1;
}
return totalPage;
}
public List<Mp3> queryPerPage(int page) {
List<Mp3> list = new ArrayList<Mp3>();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
int endRow = countPerPage * page; //结束下标
int startRow = countPerPage * (page-1) + 1; //起始下标
try {
conn = OracleConnUtil.getInstance().getConnection();
ps = conn.prepareStatement(SQL_QUERY_PERPAGE);
ps.setInt(1, endRow);
ps.setInt(2, startRow);
rs = ps.executeQuery();
while(rs.next()){
Mp3 mp3 = new Mp3(); //若把new Mp3()定义到while()外面,会导致list中保存的元素都是重复的
mp3.setId(rs.getInt("s_id"));
mp3.setName(rs.getString("s_name"));
mp3.setSinger(rs.getString("s_singer"));
mp3.setAuthor(rs.getString("s_author"));
mp3.setSize(rs.getDouble("s_size"));
list.add(mp3);
}
} catch (SQLException e) {
e.printStackTrace();
throw new MyRuntimeException("查询总记录数失败", e);
}finally{
OracleConnUtil.close(rs, ps, conn);
}
return list;
}
}
接着是控制层的Servlet处理类Mp3Servlet.java
package com.jadyer.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.jadyer.dao.Mp3Dao;
import com.jadyer.dao.imp.Mp3DaoImpl;
import com.jadyer.model.Mp3;
@SuppressWarnings("serial")
public class Mp3Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
Mp3Dao mp3Dao = new Mp3DaoImpl();
int currentPage = 1; //当前页数。默认为首页
int totalPage = mp3Dao.getTotalPage(); //获取总页数
String cp = request.getParameter("currentPage"); //获取当前页数
//不应该在接收参数的时候进行空格过滤
//因为当第一次跳转到main.jsp时,currentPage是空的,那么就会报空指针错误
//所以应该在判断了currentPage不为空之后,再进行trim()过滤掉首尾空格
if(null != cp){
cp = cp.trim();
try {
currentPage = Integer.parseInt(cp);
} catch (NumberFormatException e) {
e.printStackTrace(); //如果用户在跳转页面的文本框中输入的是字母,那么就会出现异常
currentPage = (Integer)session.getAttribute("pp"); //一旦用户输入的页数不合法,就停留在原页面不动
}
if(currentPage < 1){
currentPage = (Integer)session.getAttribute("pp"); //若用户输入的页数为零或负数,那么就停留在原页面不动
}
if(currentPage > totalPage){
currentPage = (Integer)session.getAttribute("pp"); //如果用户输入的页数的数值过大,那么就停留在原页面不动
}
}
int totalCount = mp3Dao.getTotalCount(); //获取总记录数
List<Mp3> list = mp3Dao.queryPerPage(currentPage); //按页查询记录
int pp = currentPage; //原来的页数
session.setAttribute("pp", pp);
request.setAttribute("currentPage", currentPage);
request.setAttribute("totalPage", totalPage);
request.setAttribute("totalCount", totalCount);
request.setAttribute("list", list);
// request.getRequestDispatcher("/main_jsp.jsp").forward(request, response);
// request.getRequestDispatcher("/main_jstl.jsp").forward(request, response);
request.getRequestDispatcher("/main_mytag.jsp").forward(request, response);
}
}
然后是展示层的分页效果页面main_jsp.jsp
<%@ page pageEncoding="UTF-8"%>
<%@ page import="java.util.List"%>
<%@ page import="java.util.Iterator"%>
<%@ page import="com.jadyer.model.Mp3"%>
<%
String path = request.getContextPath();
int currentPage = (Integer)request.getAttribute("currentPage");
int totalPage = (Integer)request.getAttribute("totalPage");
int totalCount = (Integer)request.getAttribute("totalCount");
List list = (List)request.getAttribute("list");
Iterator it = list.iterator();
%>
<center>
<h1>Mp3列表</h1>
歌曲总数:<font color="green"><%=totalCount%></font>
当前页数:<font color="red"><%=currentPage%></font>/<font color="blue"><%=totalPage%></font><br/><br/>
<table width="666" border="0" cellspacing="1" bgcolor="#000000">
<tr align="center">
<th bgcolor="#FFFFFF">歌曲编号</th>
<th bgcolor="#FFFFFF">歌曲名称</th>
<th bgcolor="#FFFFFF">歌手</th>
<th bgcolor="#FFFFFF">词作者</th>
<th bgcolor="#FFFFFF">歌曲大小</th>
<th bgcolor="#FFFFFF">压缩后大小</th>
</tr>
<%-- 这里<th>能够自动加粗表头,而<td>则不能 --%>
<%-- 这里<del>标签用来在文本上显示一道横线效果 --%>
<% while(it.hasNext()){ Mp3 mp3 = (Mp3)it.next(); %>
<tr align="center">
<td bgcolor="#FFFFFF"><%=mp3.getId()%></td>
<td bgcolor="#FFFFFF"><%=mp3.getName()%></td>
<td bgcolor="#FFFFFF"><%=mp3.getSinger()%></td>
<td bgcolor="#FFFFFF"><%=mp3.getAuthor()%></td>
<td bgcolor="#FFFFFF"><del><%=mp3.getSize()%></del></td>
<td bgcolor="#FFFFFF"><%=mp3.getSize()*0.8%></td>
</tr>
<% } %>
</table><br/>
<%-- 以下是分页链接 --%>
<% if(currentPage == 1){ %>
首页 上一页
<% }else{ %>
<a href="<%=path%>/servlet/Mp3?currentPage=1">首页</a>
<a href="<%=path%>/servlet/Mp3?currentPage=<%=currentPage-1%>">上一页</a>
<% }if(currentPage == totalPage){ %>
下一页 末页
<% }else{ %>
<a href="<%=path%>/servlet/Mp3?currentPage=<%=currentPage+1%>">下一页</a>
<a href="<%=path%>/servlet/Mp3?currentPage=<%=totalPage%>">末页</a>
<% } %>
<%-- 以下是为用户提供自定义的跳转页面 --%>
<form action="<%=path%>/servlet/Mp3">
跳转至<input type="text" name="currentPage" size="2">页
<input type="submit" value="跳转">
</form>
</center>
最后是用到的数据库脚本文件
create table T_MP3(
S_ID NUMBER primary key,
S_NAME VARCHAR2(32) not null,
S_SINGER VARCHAR2(16) not null,
S_AUTHOR VARCHAR2(32),
S_SIZE NUMBER
)
create sequence T_MP3_SID_SEQ minvalue 1 maxvalue 9999999999999999999999 start with 1 increment by 1 cache 20;
insert into t_mp3(s_id,s_name,s_singer,s_author,s_size) values(T_MP3_SID_SEQ.NEXTVAL,'A22', 'aa' , 'aa','2.2');
insert into t_mp3(s_id,s_name,s_singer,s_author,s_size) values(T_MP3_SID_SEQ.NEXTVAL,'A44', 'bb' , 'bb','4.4');
insert into t_mp3(s_id,s_name,s_singer,s_author,s_size) values(T_MP3_SID_SEQ.NEXTVAL,'A22', 'aa' , 'aa','2.2');
insert into t_mp3(s_id,s_name,s_singer,s_author,s_size) values(T_MP3_SID_SEQ.NEXTVAL,'A44', 'bb' , 'bb','4.4');
--Oracle中的分页查询语句
select * from
(select m.*, ROWNUM rn
from (select * from t_mp3 order by s_id) m)
where rn BETWEEN 11 AND 20;
-- 更推荐下面的分页查询语句,因为其算法会更好一些
select * from
(select m.*, ROWNUM rn
from (select * from t_mp3 order by s_id) m
where ROWNUM <= 20)
where rn >= 11;
-- MySQL实现分页显示,需要用到MySQL中的limit关键字
-- 分页SQL为select * from book limit ?,?
-- 其中limit后的第一个参数是所显示的第一条记录的下标,第二个参数是当前页所显示的记录数
另附:展示层使用JSTL实现的分页效果页面main_jstl.jsp
<%@ page pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<% String path = request.getContextPath(); %>
<center>
<h1>Mp3列表</h1>
歌曲总数:<font color="green">${totalCount}</font>
当前页数:<font color="red">${currentPage}</font>/<font color="blue">${totalPage}</font><br/><br/>
<table width="666" border="0" cellspacing="1" bgcolor="#000000">
<tr align="center">
<th bgcolor="#FFFFFF">歌曲编号</th>
<th bgcolor="#FFFFFF">歌曲名称</th>
<th bgcolor="#FFFFFF">歌手</th>
<th bgcolor="#FFFFFF">词作者</th>
<th bgcolor="#FFFFFF">歌曲大小</th>
<th bgcolor="#FFFFFF">压缩后大小</th>
</tr>
<c:forEach items="${list}" var="mp3">
<tr align="center">
<td bgcolor="#FFFFFF">${mp3.id}</td>
<td bgcolor="#FFFFFF">${mp3.name}</td>
<td bgcolor="#FFFFFF">${mp3.singer}</td>
<td bgcolor="#FFFFFF">${mp3.author}</td>
<td bgcolor="#FFFFFF"><del>${mp3.size}</del></td>
<td bgcolor="#FFFFFF">${mp3.size*0.8}</td>
</tr>
</c:forEach>
</table><br/>
<c:if test="${1 == currentPage}">
首页 上一页
</c:if>
<c:if test="${1 < currentPage}">
<a href="<%=path%>/servlet/Mp3?currentPage=1">首页</a>
<a href="<%=path%>/servlet/Mp3?currentPage=${currentPage-1}">上一页</a>
</c:if>
<c:if test="${currentPage == totalPage}">
下一页 末页
</c:if>
<c:if test="${currentPage < totalPage}">
<a href="<%=path%>/servlet/Mp3?currentPage=${currentPage+1}">下一页</a>
<a href="<%=path%>/servlet/Mp3?currentPage=${totalPage}">末页</a>
</c:if>
<%--
<form action="<%=path%>/servlet/Mp3">
跳转至
<select name="currentPage">
<c:forEach var="i" begin="1" end="${totalPage}">
<c:if test="${i == currentPage}">
<option value="${i}" selected>${i}</option>
</c:if>
<c:if test="${i != currentPage}">
<option value="${i}">${i}</option>
</c:if>
</c:forEach>
</select>
页
<input type="submit" value="跳转">
</form>
--%>
<%-- 这里应该注意一下多表单提交的情况 --%>
<%-- 如果浏览器不支持JavaScript的话,那就老老实实的加个按钮吧 --%>
<form action="<%=path%>/servlet/Mp3">
跳转至
<select name="currentPage" οnchange="javascript:document.forms[0].submit()">
<c:forEach var="i" begin="1" end="${totalPage}">
<c:if test="${i == currentPage}">
<option value="${i}" selected>${i}</option>
</c:if>
<c:if test="${i != currentPage}">
<option value="${i}">${i}</option>
</c:if>
</c:forEach>
</select>
页
</form>
</center>
市场上也有一些开源的分页标签类库,诸如displaytag、pager
我们亦可自定义分页标签。此时首先要自定义一个分页标签类PageTag.java
package com.jadyer.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 自定义的分页标签类
*/
public class PageTag extends SimpleTagSupport {
//private int pageStyle = 1; // 分页风格
private String path; // 后台处理分页显示的Servlet的路径
private String param; // 传递的参数
private int currPage; // 当前页数
private int totalPage; // 总页数
private boolean hasSelect; // 是否有下拉列表
private boolean hasTextField; // 是否有提交文本框
/*--六个属性的setter和getter略--*/
@Override
public void doTag() throws JspException, IOException {
JspWriter out = this.getJspContext().getOut();
// 若使用String的话,它每次都会在内存中产生一个字符串,而这些字符串会在内存中成为垃圾
// 比如out.println("a" + "b" + "c"); //这时会在内存中产生四个对象:a、b、c、abc
// 其中单独的a、b、c根本就没有意义,它们三个就会在内存中成为垃圾
// 使用StringBuffer或StringBuilder之后,在内存中永远只有一个对象,我们是对该对象的值反复修改
StringBuffer sb = new StringBuffer();
if(currPage == 1){
// 在第一页中,显示【首页】和【上一页】的时候,不需要显示链接
sb.append("首页");
sb.append(" ");
sb.append("/n"); //在页面的源代码中换行,但不是在页面中换行
sb.append("上一页"); //换行之后,在查看源代码时,看得会更方便些
sb.append(" ");
sb.append("/n");
}else{
// 构造【<a href="<%=path%>/servlet/Mp3?currentPage=1">首页</a>】
sb.append("<a href=/"");
sb.append(path);
sb.append("?");
sb.append(param);
sb.append("=");
sb.append(1);
sb.append("/"");
sb.append(">");
sb.append("首页");
sb.append("</a>");
sb.append(" ");
sb.append("/n");
// 构造【<a href="<%=path%>/servlet/Mp3?currentPage=<%=currentPage-1%>">上一页</a>】
sb.append("<a href=/"");
sb.append(path);
sb.append("?");
sb.append(param);
sb.append("=");
sb.append(currPage-1);
sb.append("/"");
sb.append(">");
sb.append("上一页");
sb.append("</a>");
sb.append(" ");
sb.append("/n");
}
if(currPage == totalPage){
// 在最后一页中,显示【下一页】和【末页】的时候,不需要显示链接
sb.append("下一页");
sb.append(" ");
sb.append("/n");
sb.append("末页");
sb.append(" ");
sb.append("/n");
}else{
// 构造【<a href="<%=path%>/servlet/Mp3?currentPage=<%=currentPage+1%>">下一页</a>】
sb.append("<a href=/"");
sb.append(path);
sb.append("?");
sb.append(param);
sb.append("=");
sb.append(currPage+1);
sb.append("/"");
sb.append(">");
sb.append("下一页");
sb.append("</a>");
sb.append(" ");
sb.append("/n");
//a 构造【<a href="<%=path%>/servlet/Mp3?currentPage=<%=totalPage%>">末页</a>】
sb.append("<a href=/"");
sb.append(path);
sb.append("?");
sb.append(param);
sb.append("=");
sb.append(totalPage);
sb.append("/"");
sb.append(">");
sb.append("末页");
sb.append("</a>");
sb.append(" ");
sb.append("/n");
}
if(this.hasSelect){
// 构造【<form action="<%=path%>/servlet/Mp3">】
sb.append("<form action=/"");
sb.append(path);
sb.append("/">");
sb.append("/n");
sb.append("跳转至");
sb.append("/n");
// 构造【<select name="page" οnchange="javascript:document.forms[0].submit()">】
sb.append("<select name=/"");
sb.append(param);
sb.append("/" ");
sb.append("οnchange=/"javascript:document.forms[0].submit()/">");
sb.append("/n");
// 构造【<option value="${i}" selected>${i}</option>】
for(int i=1; i<=totalPage; i++){
sb.append("<option value=/"");
sb.append(i);
sb.append("/" ");
if(currPage == i){
sb.append("selected");
}
sb.append(">");
sb.append(i);
sb.append("</option>");
sb.append("/n");
}
// 构造【</select>】
sb.append("</select>");
sb.append("/n");
sb.append("页");
sb.append("/n");
// 构造【</form>】
sb.append("</form>");
sb.append("/n");
}
if(this.hasTextField){
// 构造【<form name="ff" action="<%=path%>/servlet/Mp3">】
sb.append("<form name=/"ff/" action=/"");
sb.append(path);
sb.append("/">");
sb.append("/n");
// 构造【跳转至<input type="text" size="2" name="currentPage">页 】
sb.append("跳转至");
sb.append("<input type=/"text/" size=/"2/" name=/"");
sb.append(param);
sb.append("/">页 ");
// 它的缺点是:只有在鼠标滑过的时候才会聚焦文本框,功能不如下面构造的JavaScript代码
// sb.append("/" onMouseOver=/"javascript:focus()/">页 ");
sb.append("/n");
// 构造【<input type="submit" value="跳转">】
sb.append("<input type=/"submit/" value=/"跳转/">");
sb.append("/n");
// 构造【</form>】
sb.append("</form>");
sb.append("/n");
// 构造聚焦文本框的JavaScript代码
sb.append("<script language=/"javascript/">");
sb.append("document.ff.elements[0].focus()");
sb.append("</script>");
}
out.println(sb);//打印到页面上
}
}
然后在//WebRoot//WEB-INF//创建用于描述该分页标签的tld文件mytag.tld
<?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">
<tlib-version>1.0</tlib-version>
<short-name>mt</short-name>
<uri>/WEB-INF/mytag</uri>
<tag>
<name>page</name>
<tag-class>com.jadyer.tag.PageTag</tag-class>
<body-content>empty</body-content>
<attribute>
<!-- 定义属性名 -->
<name>currPage</name>
<!-- 是否是必须的 -->
<required>true</required>
<!-- 是否支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
<!-- 定义属性的类型 -->
<type>java.lang.Integer</type>
</attribute>
<attribute>
<name>totalPage</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.Integer</type>
</attribute>
<attribute>
<name>path</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>param</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>hasSelect</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.Boolean</type>
</attribute>
<attribute>
<name>hasTextField</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.Boolean</type>
</attribute>
</tag>
</taglib>
下面就是一个在展示层使用自定义分页标签的页面main_mytag.jsp
<%@ page pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="mt" uri="/WEB-INF/mytag"%>
<%
String path = request.getContextPath();
pageContext.setAttribute("path", path);
%>
<center>
<h1>Mp3列表</h1>
歌曲总数:<font color="green">${totalCount}</font>
当前页数:<font color="red">${currentPage}</font>/<font color="blue">${totalPage}</font><br/><br/>
<table width="666" border="0" cellspacing="1" bgcolor="#000000">
<tr align="center">
<th bgcolor="#FFFFFF">歌曲编号</th>
<th bgcolor="#FFFFFF">歌曲名称</th>
<th bgcolor="#FFFFFF">歌手</th>
<th bgcolor="#FFFFFF">词作者</th>
<th bgcolor="#FFFFFF">歌曲大小</th>
<th bgcolor="#FFFFFF">压缩后大小</th>
</tr>
<c:forEach items="${list}" var="mp3">
<tr align="center">
<td bgcolor="#FFFFFF">${mp3.id}</td>
<td bgcolor="#FFFFFF">${mp3.name}</td>
<td bgcolor="#FFFFFF">${mp3.singer}</td>
<td bgcolor="#FFFFFF">${mp3.author}</td>
<td bgcolor="#FFFFFF"><del>${mp3.size}</del></td>
<td bgcolor="#FFFFFF">${mp3.size*0.8}</td>
</tr>
</c:forEach>
</table><br/>
<%-- 下面就是使用自定义标签实现的分页效果 --%>
<mt:page currPage="${currentPage}" totalPage="${totalPage}" path="${path}/servlet/Mp3" param="currentPage"
hasSelect="false" hasTextField="true"/>
</center>