Posted on 2006-09-09 11:24
誰伴我闖蕩 阅读(3175)
评论(0) 编辑 收藏
我曾经介绍过自己构建的分页程序,在那个程序中,我们把分页显示的数据放到了Action的成员中,而没有放在execute函数中,如果把他放到execute函数中会产生什么效果呢?由于我们没有采用页码来确定数据,而是单纯的调用下一页来完成的,所以当变量放到execute中时我们每次访问到的都只会是第一页,这就是Struts的诟病,单用户每次访问都会为用户创建一个新的线程,而非Servlet为每用户单独开辟一个线程,所以才会产生以上的问题?
那问题该如何解决呢?
1.用页码来区分需要显示的数据更有效
2.Spring可以解决这个诟病
合二为一来介绍一下吧:
/**
* Page.java
* @author baputista
* Email: baputista@hotmail.com
* 2006-8-26 0:05:36
*/
package subject.bean;
import java.util.ArrayList;
import java.util.List;
public class Page
{
private int current = 1; //当前页码
private int nextPage = 0; //下一页码
private int previousPage = 0;//上一页码
private int total = 0;//总的数据
private int pages = 0;//总页数
private int each = 5;//每页数据
private int start = 0;//当前页的起始数据
private int end = 0;//当前页的结束数据
private boolean next = false;//是否存在下一页
private boolean previous = false;//是否存在上一页
private List list = null;
//需要显示的数据
public Page( List list, int each )//以需要显示的数据和每页要显示的数据为参数进行初始化
{
this.list = list;
this.each = each;
total = list.size();//总的数据等于List的大小
if ( total % each == 0 )//总页数和没页显示的数据可以整除,则为总页数
pages = total / each;
else
pages = total / each + 1;//否则就需要加上一页了
if ( current >= pages )
{
next = false;//判断是否有下一页
}
else
{
next = true;
nextPage = current + 1;//有,还得算出来下一页是多少呢!
}
if ( total < each )
{
start = 0;//这页显示多少数据啊?如果是最后一页,只显示整除后的余数了
end = total;
}
else
{
start = 0;//否则要显示每页需要显示的数据数
end = each;
}
}
public int getCurrent()
{
return current;
}
public boolean isNext()
{
return next;
}
public boolean isPrevious()
{
return previous;
}
public int getPages()
{
return pages;
}
public int getTotal()
{
return total;
}
public int getNextPage()
{
return nextPage;
}
public int getPreviousPage()
{
return previousPage;
}
@SuppressWarnings ( "unchecked" )
public List get( int page )//获取指定页码的List
{
if ( page > 0 && page <= pages )
{
current = page;//page在有效范围内则为当前页
}
if ( ( current - 1 ) > 0 )//计算上一页是否存在以及值
{
previous = true;
previousPage = current - 1;
}
else
{
previous = false;
}
if ( current >= pages )//计算下一页是否存在以及值
{
next = false;
}
else
{
next = true;
nextPage = current + 1;
}
if ( page * each < total )//计算显示的记录在List中的位置
{
end = current * each;
start = end - each;
}
else
{
end = total;
start = each * ( pages - 1 );
}
List gets = new ArrayList();//把显示的数据放到一个新的List里
for ( int i = start; i < end; i++ )
{
gets.add( list.get( i ) );
}
return gets;
}
}
上面的Page Bean比那个就简略的很多,我们再来看看Action怎么来做?
public class AdminAction extends BaseAction
{
private AdminManager mgr;
public void setAdminManager( AdminManager mgr )
{
this.mgr = mgr;
}
public ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response )
throws Exception
{
Integer pageId = getInt( request, "page" );
Page page = null;
List rs =mgr.getStudents();
if ( rs != null && rs.size() != 0 )
{
page = new Page( rs, 10 );
request.setAttribute( "students", page.get( pageId ) );
}
request.setAttribute( "search", Select.studentSearch() );
}
request.setAttribute( "page", page );
return mapping.findForward("student");
}
}
这样我们就可以把分页对象和List放到Execute中了,在这里我们把业务逻辑对象AdminManager的实例mgr声明成了bean的形式,这样可以在Spring中利用ioc来注入:
Struts的声明:
<action path="/admin" type="org.springframework.web.struts.DelegatingActionProxy" />
Spring中的声明:
<!-- 业务逻辑 -->
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="adminManager" parent="txProxyTemplate">
<property name="target">
<bean class="subject.service.impl.AdminManagerImpl">
<property name="dao" ref="dao" />
</bean>
</property>
</bean>
<bean name="/admin/admin" class="subject.web.action.AdminAction" singleton="false">
<property name="adminManager">
<ref bean="adminManager" />
</property>
</bean>
从而实现了Struts和Spring的完美暇接,singleton="false"从而可以解决单例的诟病!