1.定义分页标签的xml文件,需要引用taglib标签库,在<tag></tag>里面定义自定义标签
<?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">
<tlib-version>1.0</tlib-version>
<short-name>commons</short-name>
<uri>http://page.yimin.com/tag</uri>
<tag>
<description>test</description>
<name>pages</name>
<tag-class>com.data.util.Tag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>bean</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>number</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>url</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
2.实现标签需要的Java类<tag-class>com.data.util.Tag</tag-class>,这里使用的是page对象来保存分页信息。
package com.data.util;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;
/**
* 显示格式 上一页 1 2 3 4 5 下一页
*/
public class Tag extends TagSupport {
static final long serialVersionUID = 2372405317744358833L;
/**
* request 中用于保存Page<E> 对象的变量名,默认为“page”
*/
private String bean = "page";
/**
* 分页跳转的url地址,此属性必须
*/
private String url = null;
/**
* 显示页码数量
*/
private int number = 5;
@Override
public int doStartTag() throws JspException {
JspWriter writer = pageContext.getOut();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
Page page = (Page)request.getAttribute(bean);
if (page == null)
return SKIP_BODY;
url = resolveUrl(url, pageContext);
try {
//计算总页数
int pageCount = page.getTotal() / page.getSize();
if (page.getTotal() % page.getSize() > 0) {
pageCount++;
}
writer.print("<nav><ul class=\"pagination\">");
//显示首页按钮
String purl = append(url, "page", 1);
purl = append(purl, "rows", page.getSize());
writer.print("<li><a href=\"" + purl + "\">第一页</a></li>");
//显示“上一页”按钮
if (page.getPage() > 1) {
String preUrl = append(url, "page", page.getPage() - 1);
preUrl = append(preUrl, "rows", page.getSize());
writer.print("<li><a href=\"" + preUrl + "\">上一页</a></li>");
} else {
writer.print("<li class=\"disabled\"><a href=\"#\">上一页</a></li>");
}
//显示当前页码的前2页码和后两页码
//若1 则 1 2 3 4 5, 若2 则 1 2 3 4 5, 若3 则1 2 3 4 5,
//若4 则 2 3 4 5 6 ,若10 则 8 9 10 11 12
int indexPage = (page.getPage() - 2 > 0)? page.getPage() - 2 : 1;
for(int i=1; i <= number && indexPage <= pageCount; indexPage++, i++) {
if(indexPage == page.getPage()) {
writer.print( "<li class=\"active\"><a href=\"#\">"+indexPage+"<span class=\"sr-only\">(current)</span></a></li>");
continue;
}
String pageUrl = append(url, "page", indexPage);
pageUrl = append(pageUrl, "rows", page.getSize());
writer.print("<li><a href=\"" + pageUrl + "\">"+ indexPage +"</a></li>");
}
//显示“下一页”按钮
if (page.getPage() < pageCount) {
String nextUrl = append(url, "page", page.getPage() + 1);
nextUrl = append(nextUrl, "rows", page.getSize());
writer.print("<li><a href=\"" + nextUrl + "\">下一页</a></li>");
} else {
writer.print("<li class=\"disabled\"><a href=\"#\">下一页</a></li>");
}
//显示末页按钮
String purl2 = append(url, "page", pageCount);
purl2 = append(purl2, "rows", page.getSize());
writer.print("<li><a href=\"" + purl2 + "\">末页</a></li>");
writer.print("<p class=\"navbar-text\">(共"+page.getTotal()+"项记录,分"+pageCount+"页,当前为第"+page.getPage()+"页)</p>");
writer.print("</nav>");
} catch (IOException e) {
e.printStackTrace();
}
return SKIP_BODY;
}
private String append(String url, String key, int value) {
return append(url, key, String.valueOf(value));
}
/**
* 为url 参加参数对儿
*
* @param url
* @param key
* @param value
* @return
*/
private String append(String url, String key, String value) {
if (url == null || url.trim().length() == 0) {
return "";
}
if (url.indexOf("?") == -1) {
url = url + "?" + key + "=" + value;
} else {
if(url.endsWith("?")) {
url = url + key + "=" + value;
} else {
url = url + "&" + key + "=" + value;
}
}
return url;
}
/**
* 为url 添加翻页请求参数
*
* @param url
* @param pageContext
* @return
* @throws JspException
*/
private String resolveUrl(String url, javax.servlet.jsp.PageContext pageContext) throws JspException{
//UrlSupport.resolveUrl(url, context, pageContext)
Map params = pageContext.getRequest().getParameterMap();
for (Object key:params.keySet()) {
if ("page".equals(key) || "rows".equals(key)) continue;
Object value = params.get(key);
if (value == null) continue;
if (value.getClass().isArray()) {
url = append(url, key.toString(), ((String[])value)[0]);
} else if (value instanceof String) {
url = append(url, key.toString(), value.toString());
}
}
return url;
}
/**
* @return the bean
*/
public String getBean() {
return bean;
}
/**
* @param bean the bean to set
*/
public void setBean(String bean) {
this.bean = bean;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
public int getNumber(){
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
package com.data.util;
import java.util.List;
public class Page<T> {
private int total;//信息总数
private int page;//当前页
private int size;//每页信息条数
private List<T> rows;//每一页的信息存放的列表
@Override
public String toString() {
return "Page{" +
"total=" + total +
", page=" + page +
", size=" + size +
", rows=" + rows +
'}';
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
}
3.页面的使用,这里用了bootstrap的分页样式
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="commons" uri="http://page.yimin.com/tag"%>
//这里的uri与xml文件里定义的uri一致就可以了,不需要真是的网址
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">数据列表</div>
<!-- /.panel-heading -->
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="display: none">ID</th>
<th>名称</th>
<th>上传人</th>
<th>电话</th>
<th colspan="2">描述</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${pages.rows}" var="row">
<tr>
<td style="display: none">${row.dataID}</td>
<td>${row.dataName}</td>
<td>${row.people}</td>
<td>${row.telphone}</td>
<td colspan="2">${row.des}</td>
<td>
<a href="#" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#dataEditDialog" onclick="editdata('${row.dataID}')">修改</a>
<a href="#" class="btn btn-danger btn-xs" onclick="deletedata('${row.dataID}')">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<div class="col-md-12 text-right">
<%--<commons:page size="${pages.size}" total="${pages.total}" curr="${pages.page}" href="/dataMange/list.action" />--%>
<commons:pages url="/dataMange/list.action" bean="pages"/>
</div>
</div>
</div>
4.后端代码
@RequestMapping(value = "list",method = RequestMethod.GET)
public String list(@RequestParam(value = "dataName",required = false) String dataName,
@RequestParam(value = "people",required = false) String people,
@RequestParam(value = "telphone",required = false) String telphone,
@RequestParam(value = "primarykey",required = false) String des,
@RequestParam(value = "page",required = false) Integer pages,
@RequestParam(value = "window_height",required = false) Integer height,
Model model, HttpServletRequest request){
String auth = (String)request.getSession().getAttribute("authority");
String username = (String)request.getSession().getAttribute("user");
//将获得的参数封装成一个QueryVo对象,这里有待改进
dataQueryVo vo ;
if(auth.equals("1")){
String admin = userservice.getAdminName(username);
vo=new dataQueryVo(dataName,people,telphone,des,pages,height,username,admin);
}
else if(auth.equals("2")){
vo=new dataQueryVo(dataName,people,telphone,des,pages,height,username,null);
}
else{
vo=new dataQueryVo(dataName,people,telphone,des,pages,height,null,null);
}
if(vo.getHeight() != null){
Integer size = vo.getHeight()/90;
vo.setSize(size);
}
else {
vo.setSize(8);
}
// 判断当前页
if (null != vo.getPage()) {
vo.setStartRow((vo.getPage() -1)*vo.getSize());
}
if(null != vo.getData_Name() && !"".equals(vo.getData_Name().trim())){
vo.setData_Name(vo.getData_Name().trim());
}
if(null != vo.getData_people() && !"".equals(vo.getData_people().trim())){
vo.setData_people(vo.getData_people().trim());
}
if(null != vo.getData_telphone() && !"".equals(vo.getData_telphone().trim())){
vo.setData_telphone(vo.getData_telphone().trim());
}
if(null != vo.getData_des() && !"".equals(vo.getData_des().trim())){
vo.setData_des(vo.getData_des().trim());
}
if(null != vo.getData_path() && !"".equals(vo.getData_path().trim())){
vo.setData_path(vo.getData_path().trim());
}
//通过条件 查询分页对象
Page<dataModel> page = dataservice.selectPageByQueryVo(vo);
model.addAttribute("pages", page);
request.setAttribute("size",vo.getSize());
request.setAttribute("total",page.getTotal());
return "dataMange/dataManges";
}
@Override
public Page<dataModel> selectPageByQueryVo(dataQueryVo vo){
Page<dataModel> page = new Page<>();
//每页数
page.setSize(vo.getSize());
if(vo.getPage()==null){
page.setPage(1);
}
else {
page.setPage(vo.getPage());
}
if (null != vo) {
//总条数
page.setTotal(datamapper.dataModelCountByQueryVo(vo));
page.setRows(datamapper.selectdataModelListByQueryVo(vo));
}
return page;
}
效果展示
分析:
写代码过程中最主要的困惑是,它是怎么实现跳转到下一页的。
其实它这里就是简单的每一个对应页的按钮为一个a标签,走get请求时,在生成的时候对里面动态的拼接当前页的信息
String pageUrl = append(url, "page", indexPage);//这里的url是包括查询信息在内的get请求路径,在后面再拼接indexPage即此按钮对应的页数,
pageUrl = append(pageUrl, "rows", page.getSize());
writer.print("<li><a href=\"" + pageUrl + "\">"+ indexPage +"</a></li>");//将上面得到的拼接好的请求路径加入到需要生成的按钮里,该按钮本质就是一个a标签
第一次form表单提交的时候,在controller层得到的pages是为null,所以在service层进行判断,如果其为null就说明是第一次请求就是第一页。这样返回的page对象里面包含的当前页就是第一页,在tag类里面进行了第一次生成,生成其他的页数的按钮,下次进行点击的时候,发送给后端的请求就是带有当前页信息的请求了。