在网上看了好多的struts2的分页,虽然都实现了分页的功能,但是感觉不是非常好,需要我们在每次写分页的时候做很多的工作,而我认为分页应该是一个通用的组件,开发人员在开发的过程中不应该在分页上花费太多的精力。所以,一直想封装一个比较通用的分页组件,而设计分页组件的时候,怎样保证动态查询的参数不丢失,成为实现的一个难点。
该组件采用自定struts2标签的方式实现。
首先建立一个构建分页标签信息的类:Pages.java
/**
* *构建分页标签体的类
* *@authorJava软件工程师,艳子。
* *@version1.0
*/
public class Pages extends Component {
private HttpServletRequest request;
private String pageNo; // 当前页码
private String total; // 总页数
private String styleClass; // 分页的样式
private String theme; // 分页的主题
private String url; // action的路径
private String urlType; // 路径的类型,主要用于URL重写的扩展
// 省略get、set方法
public Pages(ValueStack arg0, HttpServletRequest request) {
super(arg0);
this.request = request;
}
@Override
public boolean end(Writer writer, String body) {
boolean result = super.start(writer);
try {
// 从ValueStack中取出数值
Object obj = this.getStack().findValue(pageNo);
pageNo = String.valueOf((Integer) obj);
obj = this.getStack().findValue(total);
total = String.valueOf((Integer) obj);
StringBuilder str = new StringBuilder();
Map cont = this.getStack().getContext();
StrutsRequestWrapper req = (StrutsRequestWrapper) cont
.get(StrutsStatics.HTTP_REQUEST);
if (url == null || "".equals(url)) {
url = (String) req
.getAttribute("javax.servlet.forward.request_uri");
}
String pageNoStr = "?pageNo=";
if ("dir".equals(urlType)) {
// 当url的类型为目录类型时,比如http://localhost:8090/yongtree/page/1
pageNoStr = "";
if ("1".equals(pageNo)) {// 第一页时
if (url.lastIndexOf("/") != url.length() - 1) {
if (url.lastIndexOf("1") == url.length() - 1) {// 如果有页码1,则去掉1
url = url.substring(0, url.length() - 1);
} else if (url.lastIndexOf("/") != url.length() - 1) {// 如果没有页码1,并且最后不是'/'时,加上'/'
url = url + "/";
}
}
} else {
url = url.substring(0, url.lastIndexOf("/") + 1);
}
}
// 下面这段处理主要是用来处理动态查询的参数,并拼接成url
StringBuffer perUrl = new StringBuffer("");
if (this.getParameters().size() != 0) {
Iterator iter = this.getParameters().keySet().iterator();
while (iter.hasNext()) {
String key = (String) iter.next();
Object o = this.getParameters().get(key);
perUrl.append("&").append(key).append("=").append(o);
}
}
Integer cpageInt = Integer.valueOf(pageNo);
str.append("<span ");
if (styleClass != null) {
str.append(" class='" + styleClass + "'>");
} else {
str.append(">");
}
// 文本样式
if (theme == null || "text".equals(theme)) {
// 当前页与总页数相等
if (pageNo.equals(total)) {
// 如果total = 1,则无需分页,显示“[第1页] [共1页]”
if ("1".equals(total)) {
str.append("[第 " + pageNo + " 页]");
str.append(" [共 " + total + " 页]");
} else {
// 到达最后一页,显示“[首页] [上一页] [末页]”
str.append("<a href='" + url + pageNoStr + "1" + perUrl
+ "'>[首页]</a> ");
str.append("<a href='" + url + pageNoStr
+ (cpageInt - 1) + perUrl + "'>[上一页]</a>");
str.append(" <a href='" + url + pageNoStr + total
+ perUrl + "'>[末页]</a> ");
}
} else {
// 当前页与总页数不相同
if ("1".equals(pageNo)) {
// 第一页,显示“[首页] [下一页] [末页]”
str.append("<a href='" + url + pageNoStr + "1" + perUrl
+ "'>[首页]</a>");
str.append("<a href='" + url + pageNoStr
+ (cpageInt + 1) + perUrl + "'>[下一页]</a>");
str.append("<a href='" + url + pageNoStr + total
+ perUrl + "'>[末页]</a>");
} else {
// 不是第一页,显示“[首页] [上一页] [下一页] [末页]”
str.append("<a href='" + url + pageNoStr + "1" + perUrl
+ "'>[首页]</a>");
str.append("<a href='" + url + pageNoStr
+ (cpageInt - 1) + perUrl + "'>[上一页]</a>");
str.append("<a href='" + url + pageNoStr
+ (cpageInt + 1) + perUrl + "'>[下一页]</a>");
str.append("<a href='" + url + pageNoStr + total
+ perUrl + "'>[末页]</a>");
}
}
} else if ("number".equals(theme)) {
// 数字样式 [1 2 3 4 5 6 7 8 9 10 > >>]
Integer totalInt = Integer.valueOf(total);
// 如果只有一页,则无需分页
str.append("[ ");
if (totalInt == 1) {
str.append("<strong>1</strong> ");
} else {
if (cpageInt > 1) {
// 当前不是第一组,要显示“<< <”
// <<:返回前一组第一页
// <:返回前一页
str.append("<a href='" + url + pageNoStr + "1" + perUrl
+ "'>?</a> ");
str.append("<a href='" + url + pageNoStr
+ (cpageInt - 1) + perUrl);
str.append("'>‹</a> ");
} else {
str.append("? ‹ ");
}
int v = (cpageInt - 4) > 0 ? (cpageInt - 4) : 1;
int v1 = (cpageInt + 4) < totalInt ? (cpageInt + 4)
: totalInt;
if (v1 == totalInt) {
v = totalInt - 10;
v = (v <= 0 ? 1 : v); // 如果为负数,则修改为1
} else if (v == 1 && v1 < totalInt) {
v1 = totalInt > 10 ? 10 : totalInt;
}
// 10个为一组显示
for (int i = v; i <= v1; i++) {
if (cpageInt == i) { // 当前页要加粗显示
str.append("<strong>" + i + "</strong> ");
} else {
// str.append("<a href='"+url + i +perUrl+"'>" + i +
// "</a> ");
str.append("<a href='" + url + pageNoStr + i
+ perUrl + "'>" + i + "</a> ");
}
}
// 如果多于1组并且不是最后一组,显示“> >>”
if (cpageInt < totalInt) {
// >>:返回下一组最后一页
// >:返回下一页
str.append("<a href='" + url + pageNoStr
+ (cpageInt + 1) + perUrl);
str.append("'>›</a> ");
str.append("<a href='" + url + pageNoStr + totalInt
+ perUrl);
str.append("'>?</a> ");
} else {
str.append("› ? ");
}
}
str.append("]");
}
str.append("</span>");
writer.write(str.toString());
} catch (IOException ex) {
ex.printStackTrace();
}
return result;
}
}
自定义分页标签结构的类:PageTag.java
/**
* *自定义分页标签结构或属性
* @author艳子,
* *@version1.0
*/
public class PageTag extends ComponentTagSupport {
private String pageNo;
private String total;
private String styleClass;
private String theme;
private String url;
private String urlType;
public void setUrlType(String urlType) {
this.urlType = urlType;
}
public void setUrl(String url) {
this.url = url;
}
public void setTheme(String theme) {
this.theme = theme;
}
public void setStyleClass(String styleClass) {
this.styleClass = styleClass;
}
public void setPageNo(String pageNo) {
this.pageNo = pageNo;
}
public void setTotal(String total) {
this.total = total;
}
@Override
public Component getBean(ValueStack arg0, HttpServletRequest arg1,
HttpServletResponse arg2) {
return new Pages(arg0, arg1);
}
protected void populateParams() {
super.populateParams();
Pages pages = (Pages) component;
pages.setPageNo(pageNo);
pages.setTotal(total);
pages.setStyleClass(styleClass);
pages.setTheme(theme);
pages.setUrl(url);
pages.setUrlType(urlType);
}
}
创建自定义标签的tld文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>yt</short-name>
<uri>/yongtree-tags</uri>
<display-name>"Java软件工程师,专注于java领域新技术的研究和系统设计。的自定义标签"</display-name>
<tag>
<name>pages</name>
<tag-class>com.baiyyy.polabs.tag.PageTag</tag-class>
<body-content>jsp</body-content>
<description>分页标签</description>
<attribute>
<name>pageNo</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>total</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>styleClass</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>分页标签的样式,不配置此项将采用默认的样式</description>
</attribute>
<attribute>
<name>theme</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>分页的主题,现支持number|text两种主题</description>
</attribute>
<attribute>
<name>url</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>分页提交的路径,默认不用配置该项,自动获取系统访问路径。</description>
</attribute>
<attribute>
<name>urlType</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>
url的类型,现在支持两种url类型,第一种默认的url,这种情况不需要设置;第二种情况是目录型的url,比如http://blog.youkuaiyun.com/yongtree,此种情况请配置成dir。此种情况不支持动态查询,故标签体中不能加入参数 </description>
</attribute>
</tag>
</taglib>
这样一个分页标签就实现完了,下一步让我们看看该怎样使用吧。
在页面中引入自定义的标签库: <%@ taglib prefix="yt" uri="/yongtree-tags"%>
开始配置分页标签信息:
<br>
共
<s:property value="total" />
页第
<s:property value="pageNo" />
页
<br>
<br>
<yt:pages pageNo="pageNo" total="total" styleClass="page"
theme="number"> <!—分页的动态查询参数需要全部注册在这里à
<s:param name="test1" value="test1"></s:param>
<s:param name="test2" value="test2"></s:param>
<s:param name="test3" value="test3"></s:param>
</yt:pages>
这样一个分页组件就完成了,但是只是完成了表现上的功能,我们还需要在后台进行封装,我对它进行了封装,
做了一个PageAction.java
public class PageAction extends BaseAction {
private Integer pageNo = 1;
private Integer everyPage = 10;
private Integer total;
Page page = new Page();
public Integer getPageNo() {
return pageNo;
}
public void setPageNo(Integer pageNo) {
this.page.setCurrentPage(pageNo);
this.pageNo = pageNo;
}
public Integer getEveryPage() {
return everyPage;
}
public void setEveryPage(Integer everyPage) {
this.everyPage = everyPage;
}
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
public Integer getTotal() {
return this.page.getTotalPage();
}
public void setTotal(Integer total) {
this.total = total;
}
}