一个小案例 hibernate+struts2 对一个教室信息进行分页显示
只是对一个教室信息(教室名字,教室地址)在页面上进行简单分页,没有多加美工的前端处理,初学者学习javaee如果有不足的地方还请批评指正。
这里是学生管理系统项目的小分支,一些地方是默认作好的
:
1.这是教室模块的实现,在页面上显示了所提交到数据库表中的教室信息,要进行分页显示
2.这里前端对应着room.jsp,后端对应着RoomAction 和 RoomDAO
3.room.jsp是后台管理的页面,是通过访问action方法的方式访问 main方法跳转到教室管理页面。
4."roommain"是在struts.xml文件中配置的页面
5.整个action在配置文件中的配置是采用通配符的方式
基本效果:
一、编写一个类Pager来存放分页信息
类中的属性:当前页 pageNo
总页数 pageCount
每页的记录数 pageSize 初始化为4
分页按钮个数 btnCount 初始化为4
package model;
public class Pager {
private int pageNo;//当前页
private int pageSize=4;//每页有都少数据
private int pageCount;//总页数
private int btnCount=4;//分页按钮个数
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getBtnCount() {
return btnCount;
}
public void setBtnCount(int btnCount) {
this.btnCount = btnCount;
}
}
这里要写两个方法,一个是得到当页的数据的方法,一个是设置总页数的方法。
(1) 在得到当页数据这里注意query的两个方法:
A、query.setFirstResult(); 设置当前页上的第一条信息是数据库中的第几条记录。
这里分析:例如每页显示10条消息:
第一页 0-9 起始记录为(1-1)*10=0
第二页 10-19 起始记录为(2-1)*10=10
类推可得当前页 的起始记录为 (pageNo-1)*pageSize(当前是第pageNo页,每页显示pager.pageSize条数据,这里是初始化了每页多少条数据,pageNo是在Action中传来的当前页码)
B、query.setMaxResults(); 设置当前页显示最大数据量,与Pager类中pageSize属性对应
执行完这两个方法之后,query.list就是当前页的教室信息
//拿到当前页码所有教室信息的方法
@SuppressWarnings("unchecked")
public List<Room> getAllRoomsByPageNo(Pager pager)
{
String hql="from Room";
//这里要创建一个事务,否则后边删除的时候会在页面显示上出现错误
session=HibernateUtil.openSession();
session.beginTransaction();
Query query= session.createQuery(hql);
//设置list为当前页的教室数据
//(1)设置当前页起始数据是哪条数据
query.setFirstResult((pager.getPageNo()-1)*pager.getPageSize());
//(2)设置当前页的最大显示数据数量
query.setMaxResults(pager.getPageSize());
//这时候获得的list就是当前页的list
List<Room> list=query.list();
session.getTransaction().commit();
session.close();
return list;
}
//分页的时候计算总页数的方法
@SuppressWarnings("unchecked")
public void initPageCount(Pager pager)
{
String hql="from Room";
//这里要创建一个事务,否则后边删除的时候会在页面显示上出现错误
session=HibernateUtil.openSession();
session.beginTransaction();
Query query= session.createQuery(hql);
List<Room> list= query.list();//此时得到的是所有教室的信息
//设置总共有多少页,这里在定义Pager类的时候初始化了一下每页有4条数据
pager.setPageCount(list.size()/pager.getPageSize());
if(list.size()%pager.getPageSize()>0)
{
//如果总记录数和每页记录数不能整除,总页数加1
pager.setPageCount(pager.getPageCount()+1);
}
session.getTransaction().commit();
session.close();
}
三、在Action的main方法中写代码。
因为是访问这个方法跳转到room.jsp页面上,在这个方法中将前端传来的当前页码的这个对象注入到一个Pager实例化的对象中。DAO方法中参数都是这个实例变量,这样只要在Action中定义一个属性pageNo就可以使用类中其他变量的值。
(1)设计是点击页码导航栏中的页码数,传入到后端action中,当我们从主页面点后台管理的方式访问room.jsp时,并不像点击导航栏页码一样,会传入后台当前页cpage属性,这样会使cpage属性为0,这样去获得第0页的第一条数据时,算出的是负数,会出现错误。又因为这样访问页面是通过Action中的main方法访问的,可以在main方法中加入这个属性的判断,如果当前页是0,则设置为第一页,这样以后台管理的方式去访问页面显示的就是第一页的教室数据
if(cpage==0)
{
cpage=1
}
if(cpage==0)
{
cpage=1
}
(2)当拿到本页的数据之后,键值对方式存放在actioncontext中,这里因为访问action是容器内跳转,所以在页面上可以直接拿到这个当前页码下的数据信息(键:"ROOMS" 值:list)。前端页面可以用struts2 标签去拿到数据。这里标签中用的是EL表达式拿出数据,补充一下EL表达式在页面上拿数据所属范围对象的顺序:EL表达式取数据时的查找对象顺序: page--> request--> session--> application。
这里存放在ActionContext 中,相当于存放在request中
<s:if test="#ROOMS!=null">
<table class="bordered">
<tr><th>序号</th><th>教室名称</th><th>教室位置</th><th>删除</th><th>修改</th></tr>
<s:iterator value="#ROOMS" id="croom" status="st">
<tr><td>${st.index+1}</td><td>${croom.name}</td><td>${croom.address}</td>
<td><input type="button" value="删除" class="delete" lang="${croom.id}"/></td>
<td><input type="button" value="修改" class="modify" lang="${croom.id}"/></td>
</tr>
</s:iterator>
</table>
(3)在这里可以通过StringBulider的append方法去将导航栏做出来(字符串追加形成一个个超链接)。具体怎么设置详见代码。可以输出到控制台中看看自己写的标签对不对。 如果显示当前页的页码的时候也要有所区分。
这里Pager类中有一个属性分页按钮的个数。如果有很多页的话肯定要规定一下 一页 上显示多少个页码链接。
例如:百度中点到第八页的时候,规定页面上显示页码的个数,能点击的第一个为第三页
所以在设置导航栏的时候,要根据初始化的 页码标签个数 设置一下显示 当前页的数据时,下面页码导航栏的页码 起始和终止的页数,这里还要注意当点击的是第一页和最后一页的时候显示页码的情况。这里暂时来回判断比较麻烦,希望阅读本文的读者可以指出更好的设计页码导航栏的方法。
代码:
//在后台管理点击跳转到room.jsp页面的方法,这里面添加了分页和添加分页导航栏的内容
public String main()
{
//如果是从后台访问room.jsp页面,这里没有点击导航栏中的当前页码按钮,后台action中拿到当前页码为0,此时当做第一页处理
//这时在DAO方法中去计算第几条开始的时候,如果当前页码为0,计算本页第一条数据是第几条记录的时候,出现负数错误,这里设置为第一页
if(pageNo==0)
{
pageNo=1;
}
ActionContext ctx= ActionContext.getContext();
StringBuilder str=new StringBuilder();//为后边打印导航页码用
//拿到request对象,然后拿到根目录
String path=ServletActionContext.getRequest().getContextPath();
//这里应该得到的是分页之后的当前页教室数据,应该在DAO方法中加入参数pager。
//这里不加入action中定义的当前页属性,应该是把这个当前页属性设置到pager对象中,再传入pager,好使用这个类中的其他属性
Pager pager=new Pager();
//计算总页数
rdao.initPageCount(pager);
//将当前页这个属性(从前端传过来) 注入到一个Pager对象当中
pager.setPageNo(pageNo);
List<Room> list=rdao.getAllRoomsByPageNo(pager);//这里得到就是当前页的教室数据
if(list.size()>0)
{
//存放数据
ctx.put("ROOMS", list);
//设置页码导航栏
int btns=pager.getBtnCount();//btns是每页显示的页码按钮数
btns=btns/2;
int start=pageNo-btns;//每一页页码按钮的开始
int end=pageNo+btns;//每一页页码按钮结束
//对页码进行判断
if(start<1)
{
start=1;
end=start+btns*2;
}
if(end>pager.getPageCount())
{
end=pager.getPageCount();
start=end-btns*2;
}
if(start<1)
{
start=1;
}
//循环准备页码导航栏数据
for(int i=start;i<=end;i++)
{
str.append("<a href='"+ path +"/room/main?pageNo="+i+"'>");
//如果显示当前页,要区别显示
if(pageNo==i)
{
str.append("<font color='yellow'><b>");
str.append(i);
str.append("</b></font>");
}
else
{
str.append(i);
}
str.append("</a>");
str.append(" ");
}
str.append("<br>");
ctx.put("NAVBAR", str.toString());
//打印到输出台,看看是否输入错误
System.out.println(str.toString());
}
return "roommain";
}