本文介绍一种分页组件的完整代码,最后封装了一个简单的jsp自定义标签
分页效果如下:
没有加页面效果,只是意思一下。这个分页的功能比较简单,不过更复杂的分页功能,原理也是差不多的
首先是Page对象
public class Page {
private static final int DEFAULT_PAGE_SIZE = 10;
private static final int DEFAULT_CURRENT_PAGE = 1;
private int currentPage;// 当前页数,通常在Action层设置
private int pageSize;// 每页记录数,通常在Action层设置
private int totalCount;// 总记录数,在DAO层设置
public Page(int currentPage, int pageSize) {
this.currentPage = currentPage;
this.pageSize = pageSize;
}
public Page(int currentPage) {
this.currentPage = currentPage;
this.pageSize = DEFAULT_PAGE_SIZE;
}
public Page() {
this.currentPage = DEFAULT_CURRENT_PAGE;
this.pageSize = DEFAULT_PAGE_SIZE;
}
public int getFirstIndex() {
return pageSize * (currentPage - 1);
}
public boolean hasPrevious() {
return currentPage > 1;
}
public boolean hasNext() {
return currentPage < getTotalPage();
}
public int getTotalPage() {
long remainder = totalCount % this.getPageSize();
if (0 == remainder) {
return totalCount / this.getPageSize();
}
return totalCount / this.getPageSize() + 1;
}
}
省略了必须的getter和setter方法。这里主要有3个字段currentPage、pageSize、totalCount,分别表示当前页、每页记录数、总记录数。基本上所有的分页组件,都需要这些字段
其实总页数totalPage也是必须的,但是这个字段是由pageSize和totalCount算出来的,所以即时计算得到比较好,如果也作为一个字段的话,那么和另外2个字段就不正交
getFirstIndex()方法也很重要,因为后面查询数据库的时候,需要作为第一条记录的标识,作为参数传给查询数据库的方法
下面是DAO的写法
public interface IBookDAO extends IGenericDAO<Book> {
public Book queryByIsbn(String isbn);
public List<Book> queryByNameWithPage(String name, Page page);
public List<Book> queryByNameWithoutPage(String name);
}
其中涉及到分页查询的就是queryByNameWithPage()方法,这个Page对象是从Action传递下来的
@Repository
public class BookDAO extends GenericDAO<Book> implements IBookDAO {
public BookDAO() {
super(Book.class);
}
@Override
public Book queryByIsbn(String isbn) {
String hql = "from Book b where b.isbn = ?";
return queryForObject(hql, new Object[] { isbn });
}
@Override
public List<Book> queryByNameWithPage(String name, Page page) {
String hql = "from Book b where b.name = ?";
return queryForList(hql, new Object[] { name }, page);
}
@Override
public List<Book> queryByNameWithoutPage(String name) {
String hql = "from Book b where b.name = ?";
return queryForList(hql, new Object[] { name });
}
}
这里调用的是GenericDAO里的方法queryForList()
@SuppressWarnings("unchecked")
protected List<T> queryForList(String hql, Object[] params, Page page) {
generatePageTotalCount(hql, params, page);
Query query = sessionFactory.getCurrentSession().createQuery(hql);
setQueryParams(query, params);
query.setFirstResult(page.getFirstIndex());
query.setMaxResults(page.getPageSize());
return query.list();
}
/**
* 该方法会改变参数page的totalCount字段
*
* @param originHql
* 原始hql语句
* @param params
* 原始参数
* @param page
* 页面对象
*/
private void generatePageTotalCount(String originHql, Object[] params,
Page page) {
String generatedCountHql = "select count(*) " + originHql;
Query countQuery = sessionFactory.getCurrentSession().createQuery(
generatedCountHql);
setQueryParams(countQuery, params);
int totalCount = ((Long) countQuery.uniqueResult()).intValue();
page.setTotalCount(totalCount);
}
这段代码关键有2点
一个是调用Page对象的getFirstIndex()方法和getPageSize()方法,确定查询结果的范围
另一个是设置Page对象自身的totalCount字段,因为Action里持有该Page对象的引用,所以根据totalCount和pageSize计算出totalPage之后,就可以在前台显示出总页数
接下来是Action层的写法(中间的Service层只是起一个传递作用和事务控制作用,省略)
@Controller
@Scope("prototype")
public class BookAction extends ActionSupport {
private static final long serialVersionUID = -4400311497910666205L;
@Autowired
private IBookService bookService;
private Page page;// 分页组件
private List<Book> books;// 查询结果列表
public String list() {
if (null == page) {
page = new Page();// 如果page对象为空,说明不是通过点击页码跳转
}
books = bookService.getBooks(page);
return SUCCESS;
}
}
这里省略了与分页无关的方法和字段,以及getter、setter方法
这里重点是list()方法,如果是通过jsp页面点击“上一页”、“下一页”的链接进入此方法的,那么struts2框架就会自动初始化Page对象。如果这个时候page对象为空,那么说明是用户直接进入该页面,就需要初始化一个Page对象(currentPage=1,表示是第一页)
该Page对象此时的totalCount是0,在查询之后,才会根据查询到的记录总数,设置totalCount的值,由于Action持有此Page的引用,所以可以在前台显示出来
下面是前台页面的写法
<div id="page_area">
<s:if test="page.hasPrevious()">
<a href="list.action?page.currentPage=${page.currentPage-1}">上一页</a>
</s:if>
<span>第${page.currentPage}页</span>
<span>共${page.getTotalPage()}页</span>
<s:if test="page.hasNext()">
<a href="list.action?page.currentPage=${page.currentPage+1}">下一页</a>
</s:if>
</div>
里面用到了struts2的<s:if>标签,还有${}表达式。我感觉${]表达式还是很方便的,struts2封装的各种<s:>标签我倒是不喜欢用,自己用html标签开发,我觉得更灵活一点
这个分页组件在各个页面都可以用到,但是如果每个jsp都要拷贝这段代码,就不好了,所以需要把它封装成标签
封装后的效果是这样的:
<wfm:page page="${page}" />
下面就介绍下这个自定义标签的开发
首先需要在WEB-INF目录下创建一个.tld文件,只要放在WEB-INF目录下就可以了,所以一般会单独建一个子目录tld来保存
这个tld内容如下
<?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">
<description>Workforce Tag Lib</description>
<tlib-version>1.0</tlib-version>
<short-name>WorkforceTagLibrary</short-name>
<uri>/wfm-tags</uri>
<tag>
<description>generate page bar</description>
<name>page</name>
<tag-class>com.huawei.inoc.framework.tag.PageTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>page</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
上面比较重要的元素是<uri>,后面在jsp页面里使用这个标签的时候会用到,然后可以定义多个<tag>元素,每个都是一个标签,命名都很清晰,就不用解释了。其中<rtexprvalue>这个标签,设置为true之后,则此属性支持变量
下面是标签的实现类
public class PageTag extends SimpleTagSupport {
private Page page;
@Override
public void doTag() throws JspException, IOException {
String content = generateContent();
getJspContext().getOut().write(content);
}
private String generateContent() {
StringBuilder response = new StringBuilder();
response.append("<div id=\"page_area\">");
if (page.hasPrevious()) {
response.append("<a href=\"list.action?page.currentPage="
+ (page.getCurrentPage() - 1) + "\">上一页</a>");
}
response.append("<span>第" + page.getCurrentPage() + "页</span>");
response.append("<span>共" + page.getTotalPage() + "页</span>");
if (page.hasNext()) {
response.append("<a href=\"list.action?page.currentPage="
+ (page.getCurrentPage() + 1) + "\">下一页</a>");
}
response.append("</div>");
return response.toString();
}
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
}
上面的代码很简单,jsp2.0之后,要实现自定义标签是很容易的,继承SimpleTagSupport类,实现doTag()方法即可,如果需要设置一些属性的话,声明为字段,并添加getter和setter方法
最后是jsp页面的引用方法
<%@ taglib prefix="wfm" uri="/wfm-tags"%>
<wfm:page page="${page}" />
在比较早的版本里,还需要在web.xml里增加tag-lib的配置,从某个版本的servlet规范之后(好像是3.0),就不需要了,容器会自动到WEB-INF目录下加载所有的.tld文件
- 大小: 29.9 KB
- 大小: 3.9 KB
分享到:
相关推荐
本项目结合了Java、Hibernate、JSP以及TLD(Tag Library Descriptor)技术,实现了一个高效、易懂且实用的自定义标签分页解决方案。下面我们将详细探讨这些技术以及它们在分页中的应用。 首先,Java作为后端编程...
标题和描述中提到的"邮箱(hibernate+Servlet+自定义标签,内带hibernate配置,自定义标签分页)"是一个基于Java技术栈的Web应用项目,它利用Hibernate作为持久层框架,Servlet作为控制层,以及自定义标签来实现前端展示...
自定义标签是Java服务器页面(JSP)技术中一种强大的特性,它允许开发者创建可重用的组件,提高代码的可读性和维护性。在上述的描述中,我们看到一个自定义标签`PagerTag`的实现,用于分页功能。下面我们将详细探讨...
首先,JSP自定义标签(Custom Tags)是JavaServer Pages的一种扩展,允许开发者创建可重用的UI组件。在分页场景中,自定义标签可以封装分页逻辑,使视图层代码更加简洁、易读。开发者可以定义一个`<paging>`标签,...
在分页功能上,自定义标签是一种高效且灵活的方式。在Struts2框架中,我们可以创建一个自定义标签库,包含用于分页的TLD(Tag Library Descriptor)文件,定义标签的属性如当前页码、每页显示条数等。然后,编写对应...
Java 分页组件是Java开发中常见的一种工具,用于在Web应用程序中实现数据的分页显示。在大型系统中,由于数据量庞大,一次性加载所有数据不仅会影响页面加载速度,也会消耗大量的服务器资源。因此,分页技术应运而生...
SSH框架整合通用模板是开发人员为了提高开发效率和代码复用性而设计的一种架构模式,主要涉及Spring、Struts2和Hibernate三个核心组件。SSH框架的整合提供了模型-视图-控制器(MVC)的设计模式,使得业务逻辑、数据...
XC分页组件的核心在于其提供了一种便捷的方式来处理大量数据的分页显示。它支持多种数据库,包括但不限于MySQL、Oracle、SQL Server等,并且可以方便地与各种持久层框架如Hibernate、MyBatis等集成。在实际使用中,...
- **Hibernate的Criteria API分页**:Hibernate提供了一种基于Criteria的分页方式,通过设置FirstResult和MaxResults属性实现。 - **自定义分页实现**:对于没有特定分页库的情况,开发者也可以自己编写分页逻辑,...
5. **分页工具**:这里提到的“分页工具”可能是指一种库或者自定义组件,它可以简化分页的实现。这种工具可能会提供预定义的标签或辅助类,帮助开发者快速生成分页导航界面,处理分页逻辑。 在实际开发中,你可能...
SSH(Struts + Spring + Hibernate)是Java Web开发中常用的一种技术栈,它结合了三个强大的开源框架:Struts作为MVC(Model-View-Controller)框架,Spring提供依赖注入和事务管理,Hibernate则用于对象关系映射。...
在Java开发中,分页是数据展示不可或缺的一部分,特别是在处理大量数据时,为了提高用户体验和系统性能,分页组件显得尤为重要。"改进后的Java分页组件"是一个优化过的解决方案,旨在简化开发流程,提高代码的可读性...
在这个项目中,可能会使用Struts2的拦截器或自定义标签来实现前端页面的分页显示,同时在后台处理分页查询逻辑,如使用Spring Data JPA的Pageable接口或Hibernate的Criteria API。 集成这三个框架,可以实现松耦合...
4. **分页实现**:在Web应用中,当数据量较大时,分页是一种常见的用户界面优化手段,它可以避免一次性加载大量数据导致页面响应慢或内存溢出。在Struts、DAO和Hibernate中,实现分页通常包括以下步骤: - 计算总...
2. **Hibernate:** Hibernate 是一个对象关系映射(ORM)工具,它提供了一种机制,将Java对象映射到关系型数据库中的表。这大大简化了数据库访问代码的编写,使得开发者可以更加专注于业务逻辑而不是繁琐的SQL语句...
针对iBatis的这一局限,我们可以尝试在不修改iBatis源码的情况下,引入类似于Hibernate的物理分页机制。这个过程主要涉及对SQL执行流程的拦截和改造。首先,我们需要了解iBatis执行SQL的关键类——`...
在Web开发中,数据分页是一种常见的需求,它能够帮助用户更有效地浏览大量信息,提高用户体验。JPage是一款通用的分页组件,旨在简化Java Web开发中的分页实现,提供了灵活的配置和丰富的功能。下面我们将详细探讨...
这些组件协同工作,为开发者提供了一种高效、灵活的开发环境。下面将详细阐述SSH框架以及分页在其中的应用。 **Struts**: Struts是Apache软件基金会的一个开源项目,基于MVC设计模式,主要用于处理Web应用的业务...
这个"QQ菜单"可能是指一种定制的菜单组件,与JSP标签结合使用,以便在JSP页面上轻松创建具有QQ风格的菜单。 最后,JSP标签是JavaServer Pages(JSP)的一个强大特性,它允许开发者自定义可重用的代码块,类似于HTML...
SSH,全称Struts2 + Spring + Hibernate,是Java Web开发中常用的一种开源框架集合。这三个框架分别负责不同的职责:Struts2作为表现层框架,提供了MVC设计模式的实现;Spring作为应用上下文框架,管理着应用对象及...