下蝲本文源代?/u>
引言 文g的上传和下蝲?a class="bluekey" target="_blank">J2EE~程已经是一个非常古老的话题了,也许您马上就能掰着指头数出好几个著名的大gQ如SmartUpload?a class="bluekey" target="_blank">Apache的FileUpload。但如果您的目是构建在Struts Spring HibernateQ以下称SSHQ框架上的,q些大g显得笨重而桑了QSSH提供了一个简h便的文g上传下蝲的方案,我们只需要通过一些配|ƈ辅以量的代码就可以完好解决q个问题了?br /> 本文围lSSH文g上传下蝲的主题,向您详细讲述如何开发基于SSH的WebE序。SSH各框架的均ؓ当前最新版本: ?Struts 1.2 ?Spring 1.2.5 ?Hibernate 3.0 本文选用的数据库?a class="bluekey" target="_blank">Oracle 9iQ当然你可以在不改动代码的情况下Q通过配置文g的调整将其移植到MhBlob字段cd的数据库上,?a class="bluekey" target="_blank">MySQLQSQLServer{?br /> M实现 上传文g保存到T_FILE表中QT_FILE表结构如下:
其中Q?br /> ?FILE_IDQ文件IDQ?2个字W,用Hibernate的uuid.hex法生成?br /> ?FILE_NAMEQ文件名?br /> ?FILE_CONTENTQ文件内容,对应Oracle的Blobcd?br /> ?REMARKQ文件备注?br /> 文g数据存储在Blobcd的FILE_CONTENT表字D上Q在Spring中采用OracleLobHandler来处理Lob字段Q包括Clob和BlobQ,׃在程序中不需要引用到oracle数据驱动E序的具体类且屏蔽了不同数据库处理Lob字段Ҏ上的差别Q从而撤除程序在多数据库UL上的樊篱? 1Q首先数据表中的Blob字段在Java领域对象中声明ؓbyte[]cdQ而非java.sql.Blobcd?br /> 2Q数据表Blob字段在Hibernate持久化映文件中的type为org.springframework.orm.hibernate3.support.BlobByteArrayTypeQ即Spring所提供的用戯定义的类型,而非java.sql.Blob? 3Q在Spring中用org.springframework.jdbc.support.lob.OracleLobHandler处理Oracle数据库的Blobcd字段?br /> 通过q样的设|和配置Q我们就可以象持久化表的一般字D늱型一样处理Blob字段了?br /> 以上是SpringQHibernate文件二q制数据持久化到数据库的解决ҎQ而Struts通过表单中filecd的组件映ؓActionForm中类型ؓorg.apache.struts.upload. FormFile的属性来获取表单提交的文件数据?br /> lg所qͼ我们可以通过?2Q描l出SSH处理文g上传的方案:
文g上传的页面如?3所C:
文g下蝲的页面如?4所C:
该工E的资源l构如图 5所C:
工程的类按SSH的层ơ结构划分ؓ数据持久层、业务层和Web层;WEB-INF下的applicationContext.xml为Spring的配|文Ӟstruts-config.xml为Struts的配|文Ӟfile-upload.jsp为文件上传页面,file-list.jsp为文件列表页面?br /> 本文后面的章节将从数据持久层-Q业务层-QWeb层的开发顺序,逐层讲解文g上传下蝲的开发过E?br /> 数据持久?br /> 1、领域对象及映射文g 您可以用Hibernate Middlegen、HIbernate Tools、Hibernate Syhchronizer{工h手工的方式,~写Hibernate的领域对象和映射文g。其中对应T_FILE表的领域对象Tfile.java为: 代码 1 领域对象Tfile
特别需要注意的是:数据库表为Blobcd的字D在Tfile中的fileContentcd为byte[]。Tfile的Hibernate映射文gTfile.hbm.xml攑֜Tfile .javacL件的相同目录下: 代码 2 领域对象映射文g
fileContent字段映射为Spring所提供的BlobByteArrayTypecdQBlobByteArrayType是用戯定义的数据类型,它实CHibernate 的org.hibernate.usertype.UserType接口。BlobByteArrayType使用从sessionFactory获取的Lob操作句柄lobHandlerbyte[]的数据保存到Blob数据库字D中。这P我们再没有必要通过编码的方式Q先insert然后再update来完成Blobcd数据的持久化Q这个原来难伺候的老爷l于被^民化了。关于lobHandler的配|请见本文后面的内容?br /> 此外lazy="true"说明地返回整个Tfile对象Ӟq不q回fileContentq个字段的数据,只有在显式调用tfile.getFileContent()Ҏ时才真正从数据库中获取fileContent的数据。这是Hibernate3引入的新Ҏ,对于包含重量U大数据的表字段Q这U抽取方式提高了对大字段操作的灵zL,否则加蝲Tfile对象的结果集时如果Lq回fileContentQ这U批量的数据抽取可以引h据库?z泛效应"?br /> 2、DAO~写和配|?br /> Spring面向接口~程Q所以我们将所有对Tfile的数据操作的Ҏ定义在TfileDAO接口中,q些接口Ҏ分别是: ?findByFildId(String fileId) ?save(Tfile tfile) ?List findAll() TfileDAOHibernate提供了对TfileDAO接口ZHibernate的实玎ͼ如代?3所C: 代码 3 ZHibernate 的fileDAO实现c?br />
TfileDAOHibernate通过扩展Spring提供的Hibernate支持cHibernateDaoSupport而徏立,HibernateDaoSupport装了HibernateTemplateQ而HibernateTemplate装了Hibernate所提供几乎所有的的数据操作方法,如execute(HibernateCallback action)Qload(Class entityClass, Serializable id)Qsave(final Object entity){等?br /> 所以我们的DAO只需要简单地调用父类的HibernateTemplate可以完成几乎所有的数据库操作了?br /> ׃Spring通过代理Hibernate完成数据层的操作Q所以原Hibernate的配|文件hibernate.cfg.xml的信息也转移到Spring的配|文件中Q?br /> 代码 4 Spring中有关Hibernate的配|信?br />
W?~9行定义了一个数据源Q其实现cLapache的BasicDataSourceQ第11~25行定义了Hibernate的会话工厂,会话工厂cȝSpring提供的LocalSessionFactoryBeanl护Q它注入了数据源和资源映文Ӟ此外q通过一些键值对讄了Hibernate所需的属性?br /> 其中W?6行通过c\径的映射方式Q将sshfile.modelcd目录下的所有领域对象的映射文g装蝲q来Q在本文的例子里Q它装载进Tfile.hbm.xml映射文g。如果有多个映射文g需要声明,使用c\径映方式显然比直接单独指定映射文g名的方式要简ѝ? W?7~30行定义了Spring代理Hibernate数据操作的HibernateTemplate模板Q而第32~34行将该模板注入到tfileDAO中?br /> 需要指定的是Spring 1.2.5提供了两套Hibernate的支持包Q其中Hibernate 2相关的封装类位于org.springframework.orm.hibernate2.*包中Q而Hibernate 3.0的封装类位于org.springframework.orm.hibernate3.*包中Q需要根据您所选用Hibernate版本q行正确选择?br /> 3、Lob字段处理的配|?br /> 我们前面已经指出Oracle的Lob字段和一般类型的字段在操作上有一个明昄区别--那就是你必须首先通过Oracle的empty_blob()/empty_clob()初始化Lob字段Q然后获取该字段的引用,通过q个引用更改其倹{所以要完成对Lob字段的操作,Hibernate必须执行两步数据库访问操作,先Insert再Update?br /> 使用BlobByteArrayType字段cd后,Z么我们就可以象一般的字段cd一h作Blob字段呢?可以定的一ҎQBlobByteArrayType不可能逾越Blob天生的操作方式,原来是BlobByteArrayType数据cd本n具体数据讉K的功能,它通过LobHandler两ơ数据访问的动作隐藏hQBlob字段的操作在表现上和其他一般字D业cd无异Q所以LobHandlerx那个"苦了我一个,q福十亿?的那位幕后英雄?br /> LobHandler必须注入到Hibernate会话工厂sessionFactory中,因ؓsessionFactory负责产生与数据库交互的Session。LobHandler的配|如代码 5所C: 代码 5 Lob字段的处理句柄配|?br />
首先Q必d义一个能够从q接池中抽取出本地数据库JDBC对象Q如OracleConnectionQOracleResultSet{)的抽取器QnativeJdbcExtractorQ这h可以执行一些特定数据库的操作。对于那些仅装了Connection而未包括Statement的简单数据连接池QSimpleNativeJdbcExtractor是效率最高的抽取器实现类Q但具体到apache的BasicDataSourceq接池,它封装了所有JDBC的对象,q时需要用CommonsDbcpNativeJdbcExtractor了。Spring针对几个著名的Web服务器的数据源提供了相应的JDBC抽取器: ?WebLogicQWebLogicNativeJdbcExtractor ?WebSphereQWebSphereNativeJdbcExtractor ?JBossQJBossNativeJdbcExtractor 在定义了JDBC抽取器后Q再定义lobHandler。Spring 1.2.5提供了两个lobHandlerQ?br /> ?DefaultLobHandlerQ适用于大部分的数据库Q如SqlServerQMySQLQ对Oracle 10g也适用Q但不适用于Oracle 9iQ看来Oracle 9i实是个怪胎Q谁叫Oracle 公司自己都说Oracle 9i是一个过渡性的产品呢)?br /> ?OracleLobHandlerQ适用于Oracle 9i和Oracle 10g?br /> ׃我们的数据库是Oracle9iQ所以用OracleLobHandler?br /> 在配|完LobHandler后, q需要将其注入到sessionFactory的Bean中,下面是调用后的sessionFactory Bean的配|: 代码 6 lobHandler注入到sessionFactory中的配置
业务?br />
其中save(FileActionForm fileForm)ҎQ将装在fileForm中的上传文g保存到数据库中,q里我们使用FileActionForm作ؓҎ入参QFileActionForm是Web层的表单数据对象Q它装了提交表单的数据。将FileActionForm直接作ؓ业务层的接口入参Q相当于Web层传播到业务层中去,卛_业务层绑定在特定的Web层实现技术中Q按照分层模型学院派的观点,q是一U反模块化的设计Q但?一?的业务系lƈ无需提供多种UI界面Q系lWeb层将来切换到另一U实现技术的可能性也微乎其微Q所以笔者觉得没有必要ؓ了这个业务层完全独立于调用层的过高目标而去搞一个额外的隔离层,费了原材料不说Q还系l搞得过于复杂,相比于其它原则,"?始终是最大的一条原则?br /> getAllFile()负责获取T_FILE表所有记录,以便在网上昄出来?br /> 而getFileName(String fileId)和write(OutputStream os,String fileId)则用于下载某个特定的文g。具体的调用是将Web层将response.getOutputStream()传给write(OutputStream os,String fileId)接口Q业务层直接文件数据输出到q个响应中。具体实现请参见错误Q未扑ֈ引用源。节下蝲文g部分?br /> 2、业务层接口实现c?br /> FileService的实现类为FileServiceImplQ其中save(FileActionForm fileForm)的实现如下所C: 代码 8 业务接口实现cMsave()
在save(FileActionForm fileForm)Ҏ里,完成两个步骤Q?br /> 其一Q象在水桉倒水一PFileActionForm对象中的数据倒入到Tfile对象中; 其二Q调用TfileDAO保存数据?br /> 需要特别注意的是代码的W?1行,FileActionForm的fileContent属性ؓorg.apache.struts.upload.FormFilecdQFormFile提供了一个方便的ҎgetFileData()Q即可获取文件的二进制数据。通过解读FormFile接口实现cDiskFile的原码,我们可能知道FormFile本nq不~存文g的数据,只有实际调用getFileData()Ӟ才从盘文g输入中获取数据。由于FormFile使用读取方式获取数据,本n没有~存文g的所有数据,所以对于上传超大体U的文gQ也是没有问题的Q但是,׃数据持久层的Tfile使用byte[]来缓存文件的数据Q所以ƈ不适合处理大体积的文Ӟ?00MQ,对于大体积的文Ӟ依然需要用java.sql.Blobcd以常规流操作的方式来处理?br /> 此外Q通过FileForm的getFileName()Ҏ可以获得上传文件的文g名,如第21行代码所C?br /> write(OutputStream os,String fileId)Ҏ的实玎ͼ如代?9所C: 代码 9 业务接口实现cMwrite()
write(OutputStream os,String fileId)也简单地分ؓ两个操作步骤Q首先,ҎfileId加蝲表记录,然后fileContent写入到输出流中?br /> 3、Spring事务配置 下面Q我们来看如何在Spring配置文g中ؓFileService配置声明性的事务
Spring的事务配|包括两个部分: 其一Q定义事务管理器transactionManagerQ用HibernateTransactionManager实现事务理Q?br /> 其二Q对各个业务接口q行定义Q其实txProxyTemplate和fileService是父子节点的关系Q本来可以将txProxyTemplate定义的内容合q到fileService中一起定义,׃我们的系l仅有一个业务接口需要定义,所以将其定义的一部分抽象到父节点txProxyTemplate中意义确实不大,但是对于真实的系l,往往拥有为数众多的业务接口需要定义,这些业务接口定义内容的共同部分抽取C个父节点中,然后在子节点中通过parentq行兌Q就可以大大化业务接口的配置了?br /> 父节点txProxyTemplate注入了事务管理器Q此外还定义了业务接口事务管理的ҎQ允讔R过通配W的方式q行匚w声明Q如前两个接口方法)Q有些接口方法仅Ҏ据进行读操作Q而另一些接口方法需要涉及到数据的更攏V对于前者,可以通过readOnly标识出来Q这h利于操作性能的提高,需要注意的是由于父c节点定义的Bean仅是子节炚w|信息的抽象Qƈ不能具体实现化一个Bean对象Q所以需要特别标注ؓabstract="true"Q如W?行所C?br /> fileService作ؓ一个目标类被注入到事务代理器中Q而fileService实现cL需要的tfileDAO实例Q通过引用3.2节中定义的tfileDAO Bean注入?br /> Web层实?br /> 1、Web层的构g和交互流E?br /> Web层包括主?个功能: ?上传文g?br /> ?列出所有已l上传的文g列表Q以供点M载?br /> ?下蝲文g?br /> Web层实现构件包括与2个JSP面Q?个ActionForm及一个ActionQ?br /> ?file-upload.jspQ上传文件的面?br /> ?file-list.jspQ已l上传文件的列表面?br /> ?FileActionFormQfile-upload.jsp面表单对应的ActionForm?br /> ?FileActionQ承org.apache.struts.actions.DispatchAction的ActionQ这栯个Action可以通过一个URL参数区分中响应不同的h?br /> Web层的q些构g的交互流E如?6所C:
其中Q在执行文g上传的请求时QFileAction在执行文件上传后Qforward到loadAllFile出口中,loadAllFile加蝲数据库中所有已l上传的记录Q然后forward到名为fileListPage的出口中Q调用file-list.jsp面昄已经上传的记录?br /> 2、FileAction功能 Struts 1.0的Action有一个弱:一个Action只能处理一U请求,Struts 1.1中引入了一个DispatchActionQ允讔R过URL参数指定调用Action中的某个ҎQ如http://yourwebsite/fileAction.do?method=upload卌用FileAction中的uploadҎ。通过q种方式Q我们就可以一些相关的h集中C个Action当中~写Q而没有必要ؓ某个h操作~写一个ActioncR但是参数名是要在struts-config.xml中配|的Q?br />
W?行的parameter="method"指定了承载方法名的参敎ͼW?行中Q我们还配置了一个调用FileAction不同Ҏ的Action出口?br /> FileAction共有3个请求响应的ҎQ它们分别是Q?br /> ?upload(…)Q处理上传文件的h?br /> ?listAllFile(…)Q处理加载数据库表中所有记录的h?br /> ?downloadQ?#8230;Q:处理下蝲文g的请求?br /> 下面我们分别对这3个请求处理方法进行讲解?br /> 2.1 上传文g 上传文g的请求处理方法非常简单,之言之,是从Spring容器中获取业务层处理cFileServiceQ调用其save(FileActionForm form)Ҏ上传文gQ如下所C:
׃FileAction其它两个h处理Ҏ也需要从Spring容器中获取FileService实例Q所以我们特别提供了一个getFileService()ҎQ第15~21行)。重构的一条原则就是:"发现代码中有重复的表辑ּQ将其提取ؓ一个变量;发现cM有重复的代码D,其提取Z个方法;发现不同cM有相同的ҎQ将其提取ؓ一个类"。在真实的系l中Q往往拥有多个Action和多个Servicec,q时一个比较好的设|思\是,提供一个获取所有Service实现对象的工LQ这样就可以Spring 的Service配置信息屏蔽在一个类中,否则Service的配|名字散落在E序各处Q维护性是很差的?br /> 2.2 列出所有已l上传的文g listAllFileҎ调用Servie层方法加载T_FILE表中所有记录,q将其保存在Request域中Q然后forward到列表页面中Q?br />
file-list.jsp面使用Struts标签展示Z存在Request域中的记录:
展现面的每条记录挂接着一个链接地址QŞ如:fileAction.do?method=download&fileId=xxxQmethod参数指定了这个请求由FileAction的downloadҎ来响应,fileId指定了记录的主键?br /> ׃在FileActionForm中,我们定义了fileId的属性,所以在download响应Ҏ中,我们可以从FileActionForm中取得fileId的倹{这里涉及到一个处理多个请求Action所对应的ActionForm的设计问题,׃原来的Action只能对应一个请求,那么原来的ActionForm非常单,它仅需要将q个h的参数项作ؓ其属性就可以了,但现在一个Action对应多个hQ每个请求所对应的参数项是不一LQ此时的ActionForm的属性就必须是多h参数的q了。所以,除了文g上传h所对应的fileContent和remark属性外q包括文件下载的fileId属性:
当然q样会造成属性的冗余Q比如在文g上传的请求中Q只会用到fileContent和remark属性,而在文g下蝲的请求时Q只会用到fileId属性。但q种冗余是会带来好处?-它得一个Action可以处理多个h?br /> 2.3 下蝲文g 在列表页面中点击一个文件下载,其请求由FileAction的downloadҎ来响应,downloadҎ调用业务层的FileServiceҎQ获取文件数据ƈ写出到response的响应流中。通过合理讄HTTP响应头参敎ͼ响应流在客L表现Z个下载文件对话框Q其代码如下所C: 代码 10 业务接口实现cMdownload
W?5~18行,讄HTTP响应_响应类型设|ؓapplication/x-msdownload MIMEcdQ则响应在IE中将弹出一个文件下载的对话框,如图 4所C。IE所支持的MIMEcd多达26U,您可以通过q个|址查看其他的MIMEcdQ?br /> http://msdn.microsoft.com/workshop/networking/moniker/overview/appendix_a.asp?br /> 如果下蝲文g的文件名含有中文字符Q如果不对其q行编码,如第18行所C,客户文g下蝲对话框中出现的文件名会发生q?br /> W?9行代码获得response的输出流Q作为FileServie write(OutputStream os,String fileId)的入参,q样文g的内容将写到response的输出流中?br /> 3、web.xml文g的配|?br /> Spring容器在何时启动呢Q我可以在Web容器初始化来执行启动Spring容器的操作,Spring提供了两U方式启动的ҎQ?br /> ?通过org.springframework.web.context .ContextLoaderListener容器监听器,在Web容器初始化时触发初始化Spring容器Q在web.xml中通过QlistenerQ</listenerQ对其进行配|?br /> ?通过Servlet org.springframework.web.context.ContextLoaderServletQ将光|ؓ自动启动的ServletQ在Web容器初始化时Q通过q个Servlet启动Spring容器?br /> 在初始化Spring容器之前Q必d初始化log4J的引擎,Spring也提供了容器监听器和自动启动Servlet两种方式对log4J引擎q行初始化: ?org.springframework.web.util .Log4jConfigListener ?org.springframework.web.util.Log4jConfigServlet 下面我们来说明如何配|web.xml启动Spring容器Q?br /> 代码 11 web.xml中对应Spring的配|内?br />
启动Spring容器Ӟ需要得C个信息:Spring配置文g的地址和Log4J属性文Ӟq两上信息分别通过contextConfigLocationWeb和log4jConfigLocation容器参数指定Q如果有多个Spring配置文gQ则用逗号隔开Q如Q?br /> /WEB-INF/applicationContext_1.xml, /WEB-INF/applicationContext_1.xm2 ׃在启动ContextLoaderServlet之前Q必M先初始化Log4J的引擎,所以Log4jConfigServlet必须在ContextLoaderServlet之前启动Q这通过Qload-on-startupQ来指定它们启动的先后顺序?br /> q是开发Web应用E序一个比较老套又常见问题,׃不同Web应用服务器的默认~码是不一LQؓ了方便Web应用在不同的Web应用服务器上ULQ最好的做法是WebE序自n来处理编码{换的工作。经典的作法是在web.xml中配|一个编码{换过滤器QSpring提供了一个编码过滤器cCharacterEncodingFilterQ下面,我们为应用配|上q个qo器:
Spring的过滤器cLorg.springframework.web.filter.CharacterEncodingFilterQ通过encoding参数指定~码转换cd为GBKQ<filter-mappingQ的配置使该qo器截h有的L?br /> Struts的框架也需要在web.xml中配|,惛_读者朋友对Struts的配|都很熟悉,故在此不再提及,请参见本文所提供的源码?br /> ȝ 本文通过一个文件上传下载的Web应用Q讲解了如何构徏ZSSH的Web应用Q通过Struts和FormFileQSpring的LobHandler以及Spring为HibernateBlob处理所提供的用LBlobByteArrayType Q实C传和下蝲文g的功能仅需要廖廖数行的代码卛_完成。读者只需对程序作E许的调_卛_处理Clob字段Q?br /> ?领域对象对应Clob字段的属性声明ؓStringcdQ?br /> ?映射文g对应Clob字段的属性声明ؓorg.springframework.orm.hibernate3.support.ClobStringTypecd?br /> 本文通过SSHҎ件上传下载简捷完的实现得以中Hv了解SSH强强联合构徏Web应用的强大优ѝ在行文中,q穿插了一些分层的设计l验Q配|技巧和Spring所提供的方便类Q相信这些知识对您的开发都有所裨益?/p> |
上传代码Q?/font> UploadActionForm.java中内?/font> package com.seavision.OurSecond.action.knowledge; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionErrors; /** private FormFile file; private String cataID; private String cataName; private String parentID; private String parentName; private String fileName; private String digist; public String getCataID() { public void setCataID(String cataID) { public String getCataName() { public void setCataName(String cataName) { public String getDigist() { public void setDigist(String digist) { public String getFileName() { public void setFileName(String fileName) { public String getParentID() { public void setParentID(String parentID) { public String getParentName() { public void setParentName(String parentName) { public FormFile getFile() { public void setFile(FormFile file) { } UploadAction.java中内?/font> package com.seavision.OurSecond.action.knowledge; import java.io.File; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.Action; import com.seavision.OurSecond.beans.KnowDocInfoVO; /** // --------------------------------------------------------- Instance // --------------------------------------------------------- Methods /** public ActionForward execute(ActionMapping mapping, ActionForm form, // ׃q原因Q测试固定?br />
// if (parentName==null||parentName.equals("")){ return this.moveToSuccess("success", mapping); }
下蝲部分Q?nbsp; DownloadAction.java?/font> package com.seavision.OurSecond.action.knowledge; import java.io.BufferedInputStream; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionForm; import com.seavision.OurSecond.beans.KnowDocInfoVO; public class DownloadAction extends BaseAction { public ActionForward execute(ActionMapping mapping, ActionForm form, try { this.initializeAction(request, "DownloadAction"); return this.moveToError(e.getMessage(), "eroor", mapping); } } |
spring的版本是2.0.hibernate的版本是3.2.struts的版本是1.4
spring所依赖的包,有时候会与其它框架所依赖的包造成冲突,引vpȝ一些摸不清楚的问题 最q就遇到了两个这斚w的问?费了好大的劲才解? 1,spring与hibernate的冲H?两个框架都依赖asm.jar包spring的版本是asm-2.23.jar.hibernate依赖的是asm.jar 需要将asm-2.2.3.jar删除.没有删除的话会引赯L异常 "org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/classes/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError Caused by: java.lang.ExceptionInInitializerError at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.getProxyFactory(CGLIBLazyInitializer.java:117) at org.hibernate.proxy.pojo.cglib.CGLIBProxyFactory.postInstantiate(CGLIBProxyFactory.java:43) at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:162) at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:135) at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:55) at org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping.<init>(EntityEntityModeToTuplizerMapping.java:56) at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:295) at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:434) at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:109) at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:55) at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:226) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294) at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:805) at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:745) at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:134) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1202) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1172) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:428) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:284) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352) at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:244) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:187) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49) at com.wukol.listener.StartupListener.contextInitialized(StartupListener.java:27) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3830) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4337) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525) at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:626) at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488) at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) at org.apache.catalina.core.StandardHost.start(StandardHost.java:719) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443) at org.apache.catalina.core.StandardService.start(StandardService.java:516) at org.apache.catalina.core.StandardServer.start(StandardServer.java:710) at org.apache.catalina.startup.Catalina.start(Catalina.java:566) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413) Caused by: java.lang.SecurityException: class "org.objectweb.asm.CodeVisitor"'s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(ClassLoader.java:775) at java.lang.ClassLoader.preDefineClass(ClassLoader.java:487) at java.lang.ClassLoader.defineClass(ClassLoader.java:614) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1817) at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:872) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1325) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1204) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:165) at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145) at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:117) at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108) at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:104) at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:69) ... 52 more " 2,hibernate与struts的冲H?两个框架都依赖common-collections.jar.hibernate的是common-collections-2.1.1.jar,struts的是common-collections.jar.需要将hibernate所依赖的common-collections-2.1.1.jar删除.没有删除的话会引赯个异?br /> java.lang.SecurityException: class "org.apache.commons.collections.ArrayStack"'s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(ClassLoader.java:775) at java.lang.ClassLoader.preDefineClass(ClassLoader.java:487) at java.lang.ClassLoader.defineClass(ClassLoader.java:614) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1817) at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:872) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1325) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1204) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) at org.apache.commons.digester.Digester.<init>(Digester.java:142) at org.apache.struts.action.ActionServlet.initServlet(ActionServlet.java:1751) at org.apache.struts.action.ActionServlet.init(ActionServlet.java:349) at javax.servlet.GenericServlet.init(GenericServlet.java:212) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:981) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4045) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4351) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525) at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:626) at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488) at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) at org.apache.catalina.core.StandardHost.start(StandardHost.java:719) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443) at org.apache.catalina.core.StandardService.start(StandardService.java:516) at org.apache.catalina.core.StandardServer.start(StandardServer.java:710) at org.apache.catalina.startup.Catalina.start(Catalina.java:566) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413) " " |
说是struts分页,实际上这个分늱不局限在某个框架下用?br />
实现Ҏ是通过list?map 来封装数据结果集省了建立formbean和手动对formbean赋值的ȝQ?br />
用list?map 来封装后使用h和rs基本上一P有些地方比RS方便些?br />
本分늱中对查询参数已经作了处理Q所以不需要在自己在去拼URL参数了?br />
sql server分页使用存储q程要更高效?br />
下面q个存储q程是从SQL区找到的
-----------------------------------------------------------------------------------------------------------------------------------
CREATE Proc p_show
@QueryStr varchar(8000), --表名、视囑、查询语?br />
@PageSize int=10, --每页的大?行数)
@PageCurrent int=1, --要显C的?br />
@FdShow varchar (8000)='', --要显C的字段列表,如果查询l果有标识字D?需要指定此?且不包含标识字段
@FdOrder nvarchar (3000)='' --排序字段列表
as
declare @FdName nvarchar(550) --表中的主键或表、时表中的标识列名
,@Id1 varchar(80),@Id2 varchar(80) --开始和l束的记录号
,@Obj_ID int --对象ID
--表中有复合主键的处理
declare @strfd nvarchar(4000) --复合主键列表
,@strjoin varchar(8000) --q接字段
,@strwhere nvarchar(4000) --查询条g
select @Obj_ID=object_id(@QueryStr)
,@FdShow=case isnull(@FdShow,'') when '' then ' *' else ' '+@FdShow end
,@FdOrder=case isnull(@FdOrder,'') when '' then '' else ' order by '+@FdOrder end
,@QueryStr=case when @Obj_ID is not null then ' '+@QueryStr else ' ('+@QueryStr+') a' end
--如果昄W一,可以直接用top来完?br />
if @PageCurrent=1
begin
select @Id1=cast(@PageSize as varchar(50))
exec('select top '+@Id1+@FdShow+' from '+@QueryStr+@FdOrder)
return
end
--如果是表,则检查表中是否有标识更或主键
if @Obj_ID is not null and objectproperty(@Obj_ID,'IsTable')=1
begin
select @Id1=cast(@PageSize as varchar(50))
,@Id2=cast((@PageCurrent-1)*@PageSize as varchar(50))
select @FdName=name from syscolumns where id=@Obj_ID and status=0x80
if @@rowcount=0 --如果表中无标识列,则检查表中是否有主键
begin
if not exists(select 1 from sysobjects where parent_obj=@Obj_ID and xtype='PK')
goto lbusetemp --如果表中无主?则用临时表处?/p>
select @FdName=name from syscolumns where id=@Obj_ID and colid in(
select colid from sysindexkeys where @Obj_ID=id and indid in(
select indid from sysindexes where @Obj_ID=id and name in(
select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
)))
if @@rowcount>1 --查表中的主键是否为复合主?br />
begin
select @strfd='',@strjoin='',@strwhere=''
select @strfd=@strfd+',['+name+']'
,@strjoin=@strjoin+' and a.['+name+']=b.['+name+']'
,@strwhere=@strwhere+' and b.['+name+'] is null'
from syscolumns where id=@Obj_ID and colid in(
select colid from sysindexkeys where @Obj_ID=id and indid in(
select indid from sysindexes where @Obj_ID=id and name in(
select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
)))
select @strfd=substring(@strfd,2,2000)
,@strjoin=substring(@strjoin,5,4000)
,@strwhere=substring(@strwhere,5,4000)
goto lbusepk
end
end
end
else
goto lbusetemp
/*--使用标识列或主键为单一字段的处理方?-*/
lbuseidentity:
exec('select top '+@Id1+@FdShow+' from '+@QueryStr
+' where '+@FdName+' not in(select top '
+@Id2+''+@FdName+' from '+@QueryStr+@FdOrder
+')'+@FdOrder
)
return
/*--表中有复合主键的处理Ҏ--*/
lbusepk:
exec('select '+@FdShow+' from(select top '+@Id1+' a.* from
(select top 100 percent * from '+@QueryStr+@FdOrder+') a
left join (select top '+@Id2+''+@strfd+'
from '+@QueryStr+@FdOrder+') b on '+@strjoin+'
where '+@strwhere+') a'
)
return
/*--用时表处理的方?-*/
lbusetemp:
select @FdName='[ID_'+cast(newid() as varchar(80))+']'
,@Id1=cast(@PageSize*(@PageCurrent-1) as varchar(50))
,@Id2=cast(@PageSize*@PageCurrent-1 as varchar(50))
exec('select '+@FdName+'=identity(int,0,1),'+@FdShow+'
into #tb from'+@QueryStr+@FdOrder+'
select '+@FdShow+' from #tb where '+@FdName+' between '
+@Id1+' and '+@Id2
)
GO
--------------------------------------------------------------------------------------------------------------------------------
q里需要徏立一个分늱ResultGatherPro.java
相关说明在相应行的后?br />
--------------------------------------------------------------------------------------------------------------------------------
import conn.DBConnManager;//q个是连接池Q可以更换其他的?/p>
import javax.servlet.http.HttpServletRequest;
import java.sql.*;
import java.util.*;
public class ResultGatherPro {
private String sql;
private int intPageSize; //每页行数
private int intRowCount;
private int intPageCount;
private int intPage; //号
private String Counter;
DBConnManager conn = null;
Connection con = null;
CallableStatement stmt = null;
ResultSet rs = null;
Statement st = null;
ResultSet rsc = null;
private String defaultname = "default";
public ResultGatherPro() {
}
public ResultGatherPro(String sqlcom, int rownum, int pagenum, String counter) {
System.out.println(counter);
sql = sqlcom;
intPageSize = rownum;
intPage = pagenum;
Counter = counter;
System.out.println(sqlcom);
}
public void setUseDB(String dbname)
{
this.defaultname = dbname;
}
public List selectRS(String sqlcom, int rownum, int pagenum, String counter) {
System.out.println(counter);
this.sql = sqlcom;
this.intPageSize = rownum;
this.intPage = pagenum;
this.Counter = counter;
System.out.println(sqlcom);
return selectRS();
}
public List selectRS() {
List rsall = new ArrayList();
Map rsTree;
try {
conn = DBConnManager.getInstance();
con = conn.getConnection(defaultname);
st = con.createStatement();
rsc = st.executeQuery(Counter);
while (rsc.next()) {
intRowCount = rsc.getInt("allrow");
}
stmt = con.prepareCall("{call p_show('" + sql + "'," + intPageSize + "," + intPage + ")}");//如果用别的数据库把q个地方修改一?br />
rs = stmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
//Object[] aa = new Object[numberOfColumns-1];
intPageCount = (intRowCount + intPageSize - 1) / intPageSize;
while (rs.next()) {
rsTree = new HashMap(numberOfColumns);
for (int r = 1; r < numberOfColumns + 1; r++) {
rsTree.put(rsmd.getColumnName(r).toLowerCase(), rs.getObject(r));//toLowerCase()q个地方把列名{化ؓ写是ؓ了和oracle兼容
}
rsall.add(rsTree);
}
} catch (java.lang.Exception ex) {
System.out.println("db conn has a Exception !!!!");
if(ex.toString().indexOf("peer")>0||ex.toString().indexOf("reset")>0) //一般连接池都没有自动重q功能,q里是当数据库连接异常后Q进行重新初始化q接。不然即使网l正怺Q数据库q接也不会恢?br />
DBConnManager.reConnect();
ex.printStackTrace();
} finally {
try {
if (rsc != null)
rsc.close();
if (st != null)
st.close();
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (conn != null)
conn.releaseConnection(defaultname, con);
} catch (Exception e) {
System.out.println(e);
}
}
return rsall;
}
public String ChangePage(HttpServletRequest request) {
String urlchange = null;
String pagename = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1);
String url = getUrl(request);
String dol = "";
if (url != null && !url.equals(""))
dol = "&";
if (intPage > 1 && intPage < intPageCount) {
urlchange = "<a href=" + pagename + "?pagenum=" + (intPage - 1) + dol + url + ">上一?lt;/a> | <a href=" + pagename + "?pagenum=" + (intPage + 1) + dol + url + ">下一?lt;/a> | W? + intPage + "?| ? + intPageCount + "?| ? + intRowCount + "?;
} else if (intPage == 1 && intRowCount <= intPageSize) {
urlchange = "上一?| 下一?| W? + intPage + "?| ? + intPageCount + "?| ? + intRowCount + "?;
} else if (intPage == intPageCount && intPage != 1) {
urlchange = "<a href=" + pagename + "?pagenum=" + (intPage - 1) + dol + url + ">上一?lt;/a> 下一?| W? + intPage + "?| ? + intPageCount + "?| ? + intRowCount + "?;
} else if (intPage == 1 && intRowCount >= intPageSize) {
urlchange = "上一?| <a href=" + pagename + "?pagenum=" + (intPage + 1) + dol + url + ">下一?lt;/a> | W? + intPage + "?| ? + intPageCount + "?| ? + intRowCount + "?;
} else {
urlchange = "<a href=" + pagename + ">W一?lt;/a>";
}
return urlchange;
}
public String ChangeBar(HttpServletRequest request) {
String urlchange = null;
String pagename = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1);
String url = getUrl(request);
String dol = "";
if (url != null && !url.equals(""))
dol = "&";
if (intPage > 1 && intPage < intPageCount) {
urlchange = "<a href=" + pagename + "?pagenum=" + (intPage - 1) + dol + url + ">上一?lt;/a> | <a href=" + pagename + "?pagenum=" + (intPage + 1) + dol + url + ">下一?lt;/a> | W? + intPage + "?| ? + intPageCount + "?;
} else if (intPage == 1 && intRowCount <= intPageSize) {
urlchange = "上一?| 下一?| W? + intPage + "?| ? + intPageCount + "?;
} else if (intPage == intPageCount && intPage != 1) {
urlchange = "<a href=" + pagename + "?pagenum=" + (intPage - 1) + dol + url + ">上一?lt;/a> 下一?| W? + intPage + "?| ? + intPageCount + "?;
} else if (intPage == 1 && intRowCount >= intPageSize) {
urlchange = "上一?| <a href=" + pagename + "?pagenum=" + (intPage + 1) + dol + url + ">下一?lt;/a> | W? + intPage + "?| ? + intPageCount + "?;
} else {
urlchange = "<a href=" + pagename + ">W一?lt;/a>";
}
return urlchange;
}
public int getTotal() {
return intRowCount;
}
public int getPageCount() {
return intPageCount;
}
public String gotoPage(HttpServletRequest request) {
String url = getUrl(request);
String javascript = "<script>function checksearch(sform)\n{if(sform.pagenum.value==\"\" || sform.pagenum.value==\"0\"){alert('误正确入页敎ͼ');sform.pagenum.focus();return false;}\nif(isNaN(sform.pagenum.value)){alert('误入数字!');sform.pagenum.focus();return false;}}</script>";
String form = "<table border='0' cellpadding='0' cellspacing='0'>\n" + javascript;
form += "<form action='' onSubmit='return checksearch(this)'>\n<tr><td width='40' align='center'>\n<input name='pagenum' type='text' size='3' class='gotext'>\n ";
if (url != null) {
if (url.indexOf("&") > 0) {
String[] param = new String[(url.split("&")).length];
param = url.split("&");
for (int i = 0; i < param.length; i++) {
form += "<input type='hidden' name='" + param[i].substring(0, param[i].indexOf("=")) + "' value='" + param[i].substring(param[i].indexOf("=") + 1) + "'>\n";
}
} else {
if (url.indexOf("=") > 0) {
form += "<input type='hidden' name='" + url.substring(0, url.indexOf("=")) + "' value='" + url.substring(url.indexOf("=") + 1) + "'>\n";
}
}
}
form += "</td><td width='25' align='center'><input type='submit' name='Submit' value='GO' class='gobtn'>\n</td>\n</tr>\n</form>\n</table>";
return form;
}
private String getUrl(HttpServletRequest request) {
String url = "";
Enumeration param = request.getParameterNames();
while (param.hasMoreElements()) {
String pname = param.nextElement().toString();
if (!pname.equalsIgnoreCase("pagenum") && !pname.equalsIgnoreCase("submit"))
url += pname + "=" + request.getParameter(pname) + "&";
}
if (url.endsWith("&")) {
url = url.substring(0, url.lastIndexOf("&"));
}
return url;
}
public String intercept(String str, int num, String last) {
if (str.length() <= num)
return str;
else
return str.substring(0, num) + last;
}
}
--------------------------------------------------------------------------------------------------------
在action里可以这栯?br />
可以看到action里没有做对传递参数的处理Q只需要把request整个传到分页c里可以了
--------------------------------------------------------------------------------------------------------------
String sql = "select top 100 percent * from usertable";
String sqlcount = "select count(*) from usertable";//Z得到总行?br />
int pagesize= 18;
int pagenum = 1;
if(request.getParameter("pagenum")!=null)
{
pagenum = java.lang.Integer.parseInt(request.getParameter("pagenum"));
}
ResultGatherPro rs = new ResultGatherPro(sql,pagesize,pagenum,sqlcount);
request.setAttribute("liststill",rs.selectRS());
request.setAttribute("changepage",rs.ChangePage(request));
request.setAttribute("gotopage",rs.gotoPage(request));
-----------------------------------------------------------------------------------------------------------------------------------
最?jsp里可以这样写
-------------------------------------------------------------------------------------------------------------------------
<logic:iterate id="listuser" name="liststill" type="Map">
<bean:write name='listuser' property='username'/>
<bean:write name='listuser' property='useremail'/>
</logic:iterate>
<bean:write name='changepage' filter="false"/>
<bean:write name='gotopage' filter="false"/>
上面两个一定要讄filter="false" 不然会过滤html部分
如果用mysql数据?br />
分늱?br />
con.prepareCall("{call p_show('" + sql + "'," + intPageSize + "," + intPage + ")}");
Ҏ
con.prepareCall(sql+" limit "+(intPage-1)*intPageSize+","+intPageSize);
如果用oracle数据?br />
Ҏ
con.prepareCall("SELECT * FROM(SELECT A.*, rownum r FROM("+sql+") A WHERE rownum <= "+intPage*intPageSize+") B WHERE r > "+(intPage-1)
*intPageSize);
最好不要用把所有记录都d来然后在其中q行分页的方?/p>