Oracle大数据量分页显示的初步实现

完整版见 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("&nbsp;&nbsp;");
			sb.append("/n"); //在页面的源代码中换行,但不是在页面中换行
			sb.append("上一页"); //换行之后,在查看源代码时,看得会更方便些
			sb.append("&nbsp;&nbsp;");
			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("&nbsp;&nbsp;");
			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("&nbsp;&nbsp;");
			sb.append("/n");
		}
		if(currPage == totalPage){
			// 在最后一页中,显示【下一页】和【末页】的时候,不需要显示链接
			sb.append("下一页");
			sb.append("&nbsp;&nbsp;");
			sb.append("/n");
			sb.append("末页");
			sb.append("&nbsp;&nbsp;");
			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("&nbsp;&nbsp;");
			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("&nbsp;&nbsp;");
			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">页&nbsp;&nbsp;】
			sb.append("跳转至");
			sb.append("<input type=/"text/" size=/"2/" name=/"");
			sb.append(param);
			sb.append("/">页&nbsp;&nbsp;");
			// 它的缺点是:只有在鼠标滑过的时候才会聚焦文本框,功能不如下面构造的JavaScript代码
			// sb.append("/" onMouseOver=/"javascript:focus()/">页&nbsp;&nbsp;");
			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>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值