泛微协同商务系统 Ecology 系统底层包开发指南
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
底层包开发指南
目录
1. 引言 (2)
1.1概述 (2)
1.2定义 ..................................... 错误!未定义书签。
2.底层包应用及范例 (2)
2.1最基本的继承类 (2)
2.2怎样记录日志 (3)
2.3怎样获取属性文件的值 (9)
2.4怎样获取系统的运行目录 (12)
2.5怎样访问和运行数据库脚本 (13)
2.6如何上传一个文件 (23)
2.7如何访问已经上传的文件 (31)
2.8如何使用缓存提高系统效率 (32)
2.9其它底层类基本方法 (61)
1.引言
1.1概述
本文档为泛微协同商务系统(Ecology)程序员开发指导文档,讲述了开发底层工具包的应用,常用功能的开发。
2.底层包应用及范例
本章对ecology系统的底层工具包进行讲解,开发人员可以从这里学到怎样利用底层的工具包进行开发
2.1最基本的继承类
系统中每一个java bean 都需要继承 weaver.general.BaseBean 类。
这个类实现了记录日志和获取属性文件值的方法。
继承这两个类的其它类可直接应用这些方法来记录日志,获取属性文件某一个属性的值。
方法的实现见后面的例子。
继承的例子如下:
java bean 的继承
public class ResourceComInfo extends BaseBean {
public void doSomething() { //某一个方法
方法的处理………
writeLog(s) ; // 写日志
}
}
2.2怎样记录日志
继承了weaver.general.BaseBean ,可以直接使用 writeLog方法记录日志信息。
注意这里是使用,而不是调用,因为这个方法是这两个被继承类中的方法。
注意writeLog 方法的使用:
/**
* 将某个对象写入Log文件
* @param obj 被写入的对象
*/
public void writeLog(Object obj)
我们看到,可以被记入日志的是任意一个java对象。
这些java对象将被自动转换成字符串对象(String)记入到日志文件中。
日志文件将每天生成一个,以日志文件名称中的日期来区别,比如:ecology_20030812.log,代表2003年8月12日的日志。
当天的日志为ecology.log。
每一条日志的记录格式为:
YYYY.MM.DD-HH:MM:SS 记录日志的类名–日志信息
比如:
2003.03.11-06:52:05 weaver.datacenter.OutReportResult - sql is select ROUND(sum(F_sksr),5) from T_yyrb A , CRM_CustomerInfo where
CRM_CustomerInfo.id=A.crmid and CRM_CustomerInfo.id in(5) and
A.reportdate >= '2004-01-10' and A.reportdate <= '2004-03-10' and
A.inputstatus >= '0' and A.inputstatus<>'9' and A.modtype='0'
日志的记录有两种模式,第一种为调试模式,第二种为在线模式。
在第一种模式下,所有的java对象都会记录到日志文件中,包括调试信息,在第二种模式下,只有为Exception (异常)的对象才会记录到日志文件中。
模式的设置在/ecology/WEB-INF/ log4jinit.properties 属性文件中的log4j.rootLogger 属性来指定,如下:
log4j.rootLogger = INFO,A2
#if you want to open the trace from open source,just add # ahead of line = ERROR
= ERROR
log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A2.DatePattern='_'yyyyMMdd'.log'
#don't modify the file property
log4j.appender.A2.File=@ecology
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=%d{yyyy-MM-dd
HH:mm:ss,SSS} %-5p %c - %m%n
上面的日志表明将所有的信息答应到文件日志文件中,其中日志的模式为:#FATAL 0
#ERROR 3
#WARN 4 只有WARN,ERROR,FATAL输出
#INFO 6 所有的log都输出
#DEBUG 7
记录日志的例子如下:
public class ResourceComInfo extends BaseBean {
private void setResourceInfo() throws Exception{
try{
业务处理过程……….
String debugInfo = "This is test" ;
// 在调试模式下将会记入日志文件
writeLog("debug info is "+ debugInfo) ;
}
catch(Exception e) {
// 在任何模式下出现异常,都将会记入日志文件
writeLog(e) ;
throw e ;
}
}
}
记录的日志文件形式为:
2007-10-15 16:51:50,125 DEBUG weaver.hrm.resource. ResourceComInfo - debug info is This is test
如果有异常,将会记录为:
2007-10-15 16:51:50,125 ERROR weaver.hrm.resource. ResourceComInfo - java.sql.SQLException: [Microsoft][SQLServer JDBC Driver][SQLServer]形式参数 '@id_1' 定义为 OUTPUT,但实际参数却未声明为 OUTPUT。
at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source) at
com.microsoft.jdbc.sqlserver.tds.TDSRequest.processErrorToken(Unknown Source)
at
com.microsoft.jdbc.sqlserver.tds.TDSRequest.processReplyToken(Unknown Source)
at
com.microsoft.jdbc.sqlserver.tds.TDSRPCRequest.processReplyToken(Unknown Source)
at com.microsoft.jdbc.sqlserver.tds.TDSRequest.processReply(Unknown Source)
com.microsoft.jdbc.sqlserver.SQLServerImplStatement.getNextResultType(Un known Source)
at monExecute(Unknown Source) at com.microsoft.jdbc.base.BaseStatement.executeInternal(Unknown Source)
at com.microsoft.jdbc.base.BasePreparedStatement.execute(Unknown Source)
at weaver.conn.RecordSet.executeProc(RecordSet.java:155)
at weaver.conn.RecordSet.executeProc(RecordSet.java:109)
at weaver.hrm.resource. ResourceComInfo (ResourceComInfo.java:59)
at com.caucho.jsp.JavaPage.service(JavaPage.java:87)
at com.caucho.jsp.JavaPage.subservice(JavaPage.java:81)
at com.caucho.jsp.Page.service(Page.java:410)
at com.caucho.server.http.Invocation.service(Invocation.java:319)
com.caucho.server.http.RunnerRequest.handleRequest(RunnerRequest.java:33 3)
at
com.caucho.server.http.RunnerRequest.handleConnection(RunnerRequest.java :266)
at com.caucho.server.TcpConnection.run(TcpConnection.java:140)
at ng.Thread.run(Thread.java:484)
从上面的日志信息,可以看到ResourceComInfo类的59行代码运行的时候出现错误,这个错误是执行数据库操作的脚本错误,具体的错误信息是:形式参数 '@id_1' 定义为 OUTPUT,但实际参数却未声明为 OUTPUT。
说明调用数据库脚本的时候参数的数量有出入。
开发过程中请将日志级别设置为INFO,通过日志可检查程序在哪里出错了。
2.3怎样获取属性文件的值
继承了weaver.general.BaseBean 的类,可以直接使用getPropValue方法获取属性文件的值。
注意这里是使用,而不是调用,因为这个方法是这两个被继承类中的方法。
注意getPropValue方法的使用:
/**
* 从配置文件中获取某个属性的值
* @param fname 属性文件名称
* @param key 值
* @return String 属性值
*/
public String getPropValue(String fname , String key)
getPropValue 方法指定了从某一个属性文件fname 中获取键值key 的值。
这里的属性文件必须存放在系统运行目录下的WEB-INF/prop 目录下,文件名称为参数fname指定的文件名,不包括属性文件的后缀名,属性文件的后缀名必须
为 .properties。
比如:
系统的运行目录为 d:\ecology\,那么属性文件必须放在
d:\ecology\WEB-INF\prop\ 目录下,取名为 thefilename.properties ,其中thefilename是任意的。
在属性文件中某一个键值的值用等号来赋值,等号后面的值必须放在一行,如果一行不够写(或者为了查看的方便),可以用 \ 来链接多行。
否则其它行的值不能被键值取得。
等号左右都可以有空格,对键值和键值的值没有影响。
比如:
thekeyname = thevalue
将键值的值放到多行:
thekeyname = thevalue1 \
thevalue2 \
thevalue3
thevalue4
这时候thekeyname 的值为thevalue1thevalue2thevalue3 ,thevalue4 取不到,因为thevalue3后面没有 \
在程序中要取得上述属性文件中键值thekeyname的值,使用方法:getPropValue(“thefilename” , “thekeyname”) ;
获取属性文件的值的例子如下:
public class ResourceComInfo extends BaseBean {
private void setResourceInfo() throws Exception{
业务处理过程……….
String keyValue = getPropValue(“thefilename” ,
“thekeyname”) ;
// 将键值thekeyname的值keyValue记入日志文件
writeLog("keyvalue is "+ keyValue) ;
}
}
系统的主属性文件 weaver.properties 的文件名“weaver”作为系统常量放在weaver.general.GCONST 类中,可以使用getConfigFile() 方法来返回“weaver ”,在编程的过程中,如果需要用到weaver.properties属性文件中的键值,请用GCONST. getConfigFile() 来获取,当主属性文件名称因为需要改变得时候,不必改变所有
用到这个属性文件的类,只需要改变GCONST类中常量的值
2.4怎样获取系统的运行目录
weaver.general.GCONST 类提供了一个静态方法getRootPath() ,返回系统的运行目录,比如系统的运行目录为d 盘的ecology目录,将返回d:\ecology\
获取系统的运行目录的例子如下:
public class TestBean extends BaseBean {
import weaver.general.GCONST ;
public void getSysRunPath(){
String sysRunPath = GCONST. GetRootPath() ;
// 将系统的运行目录sysRunPath的值记入日志文件
writeLog("sysRunPath is "+ sysRunPath) ;
}
}
2.5怎样访问和运行数据库脚本
在ecology系统中,大量的数据库访问,链接的建立和持续性,事务的处理,链接池的维护等问题都被封装在weaver.conn 包下面的各个类中,应用程序的实现者不需要去关心这些问题,而只需要调用weaver.conn.RecordSet 类来执行各种数据库操作。
weaver.conn.RecordSet 类实现了从数据库链接池中获取链接,执行指定的数据库脚本或者存储过程,并在脚本或者存储过程执行完毕后将链接及时地归还到链接池中。
Ecology系统的链接池管理请参见 weaver.conn.ConnectionPool ,
weaver.conn.DBConnectionPool ,weaver.conn.ConnCheckerTimer 类的API 文档,weaver.conn.ConnectionPool 用于管理ecology系统中的所有数据库链接池(ecology系统可以同时链接多个数据库,每一个数据库均有一个对应的数据库链接池,由weaver.conn.DBConnectionPool负责管理,而weaver.conn.ConnectionPool 则是这些链接池的大管家,负责所有链接池的协调和统一对外接口),
weaver.conn.DBConnectionPool用于建立和管理对某一个数据库的链接池,weaver.conn.ConnCheckerTimer用于监控各个链接池的状况,定期对数据库链接池中不符合要求的链接进行清理,并监视是否需要在某一链接池中建立新的链接。
调用weaver.conn.RecordSet,实现对数据的操作,下面进行详细的说明:weaver.conn.RecordSet类采用 java.sql 中的 CallableStatement 和 Statement 执行数据库操作。
客户端直接调用该类进行数据库操作。
不需要考虑数据库链接的建立。
其中客户端指所有调用该类进行数据库操作的应用程序,不特指用户的客户端。
RecordSet 执行数据库操作有两种形式,一种为调用存储过程,另一种为直接执行SQL语句。
与ConnStatement不同,RecordSet 执行SQL语句不分查询和修改,都在一条语句中执行。
RecordSet执行脚本的方式如下:
1、使用默认的链接池执行SQL语句:
RecordSet rs = new RecordSet() ;
rs.executeSql(" select * from TB_Example ") ;
while( rs.next() ) {
String thename = rs.getString("name") ;
其它处理代码....……
}
2、使用指定的链接池ecologytest执行SQL语句
RecordSet rs = new RecordSet() ;
rs.executeSql(" update TB_Example set name = 'the new value' " , "ecologytest" ) ;
3、使用指定的链接池ecologytest执行存储过程 PD_Example_UpdateById 存储过程PD_Example_UpdateById 如下:
CREATE PROCEDURE [PD_Example_UpdateById]
(@name varchar(100),
@id int,
@flag integer output,
@msg varchar(80) output)
AS
update TB_Example set name = @name where id = @id GO
RecordSet rs = new RecordSet() ;
String newname = ....... ;
String id = ...... ;
String procpara = newname + Util.getSeparator() + id ;
rs.executeProc( "PD_Example_UpdateById" , procpara , "ecologytest" ) ; procpara 是存储过程的参数值组成的字符串变量,多个参数值之间用
weaver.general.Util.getSeparator() 分开
4、在一个客户程序多个执行之间,查询结果可以保留到下一次查询
RecordSet rs = new RecordSet() ;
rs.executeSql(" select * from TB_Example ") ;
rs.executeSql(" update TB_Example set name = 'the new value '") ;
while( rs.next() ) {
String thename = rs.getString("name") ; //得到修改前查询的值其它处理代码....…….
}
rs.executeSql(" select * from TB_Example ") ;
while( rs.next() ) {
String thename = rs.getString("name") ; //得到修改后查询的值其它处理代码....……
}
访问和运行数据库脚本的例子:
public class ResourceComInfo extends BaseBean {
private void setResourceInfo() throws Exception{
业务处理过程……….
String sqlStr = “select * from Hrmresorce” ;
RecordSet rt = new RecordSet() ;
rt.executeSql(sqlStr) ;
while(rt.next()){
String id = Util.null2String(rt.getString("id"));
String loginid =
Util.null2String(rt.getString("loginid"));
String lastname =
Util.null2String(rt.getString("lastname"));
// 将数据库的值记入日志文件
writeLog("id is "+ id) ;
writeLog("loginid is "+ loginid) ;
writeLog("lastname is "+ lastname) ;
}
}
}
其它关于系统数据库信息的管理
a)、weaver.conn.ConnectionPool 类的管理和设置:
所有的数据库链接池的集合,用链接池名称区别每一个链接池.支持对一个或多个由属性文件定义的数据库连接池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例。
对于一个链接池集合来说,可以有多个链接池,分别链接不同的数据库。
应用程序指定链接池的名称来调用不同的链接池。
如果应用程序没有指定链接池的名称,将使用默认的链接池。
默认链接池的指定有两种方式:
1、在Application Server设置的初始参数serverName的值,以Resin 为例:<servlet servlet-name='InitServer'
servlet-class='weaver.general.InitServer'>
<init-param serverName='ecology'/>
<load-on-startup/>
</servlet>
2、如果Application Server没有相应设置,则系统使用属性文件
(weaver.properties)中设置的默认链接池名称:
DefaultPoolName = ecology
对于所有的链接池,系统需要加载相应的 JDBC Driver来建立与相应数据库的链接。
这些 Driver 在属性文件(weaver.properties)中指定,多个Driver中间用空格
隔开:
DriverClasses = com.microsoft.jdbc.sqlserver.SQLServerDriver
对于每一个链接池需要用到的参数在属性文件(weaver.properties)中指定,属性
文件中参数的名称以链接池的名称开头,中间加入小数点,比如链接池 ecology 的
参数指定为:
ecology.url =
jdbc:microsoft:sqlserver://10.1.1.205:1433;DatabaseName=ecology //db
url
er = sa
//db user name
ecology.password = 123456 //db user password
ecology.charset = ISO_1 //db encode
ecology.maxconn = 10 //max conn in conn pool
//min conn in conn pool
ecology.maxusecount = 30 //the max use times of a conn
ecology.maxidletime = 30 //the max unuse time of a conn (分)
ecology.maxalivetime = 2 //一个链接被调用后的最大未归回时间(分)ecology.checktime = 500 //检查的频率(秒)
b)、weaver.conn. DBConnectionPool类的管理和设置:
数据库链接池,所有创建的链接存放在链接池中,在客户端链接数据库时从链接池
中取出链接,客户端在完成数据库操作后将链接返回链接池。
链接池创建链接需要用到的参数在属性文件(weaver.properties)中指定,属性文
件中参数的名称以链接池的名称开头,中间加入小数点,比如链接池 ecology 的参
数指定为:
ecology.url =
jdbc:microsoft:sqlserver://10.1.1.205:1433;DatabaseName=AIS2002 //db
url
//db user name
ecology.password = 123456 //db user password
ecology.charset = ISO_1 //db encode
ecology.maxconn = 10 //max conn in conn pool
ecology.minconn = 2 //min conn in conn pool
ecology.maxusecount = 30 //the max use times of a conn
ecology.maxidletime = 30 //the max unuse time of a conn (分)
ecology.maxalivetime = 2 //一个链接被调用后的最大未归回时间(分)ecology.checktime = 500 //检查的频率(秒)
2.6如何上传一个文件
上传一个文件只需要调用weaver.file.FileUpload 类。
weaver.file.FileUpload 类支持各种文件格式的上传,也支持多文件的上传。
B/S 架构的文件上传采用的是multipart/form-data 协议,而不是HTTP协议,采用这种协议上传的数据必须通过特殊的处理,而不能用常规的方法来获取,否则不能得到数据。
weaver.file.FileUpload 封装了底层处理的代码,应用程序的实现者不需要关心这些细节!
weaver.file.FileUpload上传数据的方法有:
/**
* 进行上传一个文件的操作
* @param uploadname 需要上传的文件字段名称
* @return String 返回保存文件信息的imagefileid
*/
public String uploadFiles(String uploadname)
/**
* 进行上传一个文件的操作
* @param uploadnames需要上传的多个文件字段名称
* @return String[] 返回保存多个文件信息的imagefileid数组
*/
public String[] uploadFiles(String[] uploadnames)
这里,需要注意两点,一个是传给uploadFiles 方法的参数,是上传文件字段的名称,而不是文件的名称(这个时候你并不知道文件的名称)。
比如在jsp 或者html 页面中文件浏览的字段代码为:
<input type=file size=70 name="accessory1">
那么这里的文件字段的名称为"accessory1"。
第二点是这个方法返回的信息是保存在数据库表 ImageFile 中关于这个文件信息的键值imagefileid ,这个表的结构如下:
从表结构可以看出,我们得到了某一个文件信息的imagefileid,就可以从该表中
得到相应的文件名称(这里指文件的实际名称,比如test.doc), 文件MIME类型(比如 txt,doc,gif等) ,文件存放目录(这里指在服务器中存放的实际路径信息,包括实际存放的文件名称,比如 e:\ecologyfilesystem\2003\08\A\23143567.zip)。
通过这些信息,可以对文件进行操作,当然weaver.file.FileUpload 还提供了其
它很多方法来获取文件相关的信息,不需要通过数据表的查询就能得到这些信息。
存放在数据表中的信息只是供今后文件处理的时候使用!
上传文件的例子:
首先,我们要创建一个提交数据的页面,可以是jsp 的页面,也可以是html 的页面,我们将数据提交给 weaver.test.MutiFileUpload 的servlet 类来处理:
<HTML>
<HEAD>
<TITLE>文件上传</TITLE>
</HEAD>
<BODY>
<P>这是一个文件上传的例子</P>
<FORM id=weaver name=weaver action="/weaver/weaver.test.MutiFileUpload" method=post enctype="multipart/form-data"><!—注意,这里需要用
enctype="multipart/form-data" 表明使用multipart/form-data 协议 -->
<input type="text" size="70" name="filedesc">
<input type="file" size="70" name="accessory1">
<input type="file" size="70" name="accessory2">
<input type="submit" name="提交">
</FORM>
</BODY>
</HTML>
将上面这段代码保存为一个html 文件FileUploadTest.htm,放在ecology运行目录下的/test/目录下。
在这个页面中,有一个输入框和两个文件框可以输入信息。
注意,在环境的配置中,需要告诉web服务器将 /weaver/ 的请求转给应用服务器作为servlet处理,关于配置的信息,请参考Apache 和Resin的配置文档。
下面我们来编写weaver.test.MutiFileUpload
package weaver.test;
/**
* Title: 多文件上传处理类
* Description: 多文件上传测试
* Copyright: Copyright (c) 2001
* Company: weaver
* @author liuyu
* @version 1.0
*/
import javax.servlet.http.HttpServletRequest;
import weaver.general.DynamicServlet;
import weaver.file. FileUpload;
public class MutiFileUpload extends DynamicServlet {
public void doProcess(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException { FileUpload fu = new FileUpload(request) ;
String fileDesc = fu.getParameter("filedesc") ; /* 1*/
String[] fileFieldNames = {" accessory1"," accessory2"} ;
String[] fileIds = fu.uploadFiles(fileFieldNames) ; /*2*/
String[] fileNames = fu.getFileNames() ; /*3*/
// 将请求信息记入日志文件
writeLog("fileDesc is "+ fileDesc) ;
for (int i=0; i< fileIds.length; i++) {
String fileId = fileIds[i] ;
If(fileId == null) continue ;
String fileName = fileNames[i] ;
writeLog("fileId is "+ fileId) ;
writeLog("fileName is "+ fileName) ;
}
response.sendRedirect("/test/FileUploadTest.htm");
}
}
以上代码需要注意的几个地方:
注释1:由于使用了multipart/form-data协议,这里获取请求中的信息必须使用fu. getParameter() 方法,而不能使用 request.getParameter() 方法,否则不能得到filedesc的值!
注释2:使用uploadFiles方法上传accessory1和accessory2中的文件,同时返回保存在ImageFile 表中的文件基本信息的键值imagefileid,可以将这个imagefileid记录到其它地方以便今后调用。
注释3:使用getFileNames方法获取上传文件的真实名称(包括后缀名)
将代码保存到 /src/weaver/test/MutiFileUpload.java 文件中。
访问FileUploadTest.htm 来测试一下,看看日志文件中的记录是否正确。
页面提交,文
件上传完毕后将再次返回FileUploadTest.htm页面。
你可以查看ImageFile表来检查文件的具体存放位置等信息。
文件的存放位置在系统设置模块中设置,如果没有设置,将存放在系统运行目录下的 filesystem 目录下。
2.7如何访问已经上传的文件
在jsp页面或者html页面中访问已经上传的文件非常简单,只需要调用
weaver.file.FileDownload类,并传递需要访问的文件id ,这个文件id,就是在文件上传中返回的 imagefileid。
访问上传的文件有两种方式,一种是非下载方式,这种方式如果浏览器能够显示访问的文件类型,那么就会在浏览器中直接显示。
另一种是下载方式,无论访问的文件是什么类型,都使用弹出下载窗口的形式下载。
对非下载方式的链接访问
<A href= "/weaver/weaver.file.FileDownload?fileid=<%=fileid%>">文件1</A>对下载方式的链接访问
<A href= "/weaver/weaver.file.FileDownload?fileid=<%=fileid%>&download=1">文件1</A>
如果知道要访问的文件是图片,并需要在浏览页面中直接显示这个图片,可以使用下面的代码访问
<IMG SRC="/weaver/weaver.file.FileDownload?fileid=<%=fileid%>">
当然如果对于对应的文档,你没有权限,那么这个地址会让你返回到登录页面
2.8如何通过EXCEL导入数据
我们可以通过EXCEL导入一些数据实现系统的初始化,导入一个EXCEL需要用到weaver.file. ExcelParse,在ECOLOGY中导入一个EXCEL很简单,weaver.file. ExcelParse进行了封装,通过调用其中的方法:init(String filename)和getValue(String sheetname , String rownum , String columnnum)就可以实现实例
<HTML>
<HEAD>
<TITLE>EXCEL导入</TITLE>
</HEAD>
<BODY>
<P>这是一个EXCEL导入的例子</P>
<FORM id=weaver name=weaver action="export.jsp" method=post
enctype="multipart/form-data"><!—注意,这里需要用
enctype="multipart/form-data" 表明使用multipart/form-data 协议 -->
<input type="text" size="70" name="filedesc">
<input type="file" size="70" name="accessory1">
<input type="file" size="70" name="accessory2">
<input type="submit" name="提交">
</FORM>
</BODY>
</HTML>
下面是export.jsp的例子
<%@ page import="weaver.general.Util,weaver.file.*,java.util.*" %>
<jsp:useBean id="ExcelParse" class="weaver.file.ExcelParse" scope="page" />
FileUploadToPath fu = new FileUploadToPath(request) ; // 上传EXCEL文件
String filename = fu.uploadFiles("excelfile") ; //获取EXCEL路径ExcelParse.init( filename ) ; //进行EXCEL文件初始化
int recordercount = 0 ;
while( true ) {
recordercount ++ ;
//以下一行一行按列读取EXCEL中的数据getValue方法中的第一个参数不要变化,固定为1,第二个参数是行号,第三个参数是列号
String workcode = Util.null2String( ExcelParse.getValue("1",
""+recordercount , "1" ) ).trim() ;
String lastname = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "2" ) ).trim() ;
String sex = Util.null2String( ExcelParse.getValue("1",
""+recordercount , "3" ) ).trim() ;
String department = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "4" ) ).trim() ;
String subcompany = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "5" ) ).trim() ;
String jobtitle = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "6" ) ).trim() ;
String manager = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "7" ) ).trim() ;
String status = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "8" ) ).trim() ;
String location = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "9" ) ).trim() ;
String loginid = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "10" ) ).trim() ;
String password = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "11" ) ).trim() ;
String seclevel = Util.null2String( ExcelParse.getValue("1", ""+recordercount , "12" ) ).trim() ;
if( recordercount == 1 ) continue ; //第一行为标题,一般不处理 if( lastname.equals("") ) break ; //表示已经是最后一行,处理结束
导入数据业务处理过程……….
}
//以上取出EXCEL文件中
2.9导出EXCEL文件
在实际应用在我们常常会把一些系统统计数据导出成EXCEL供进一步的分析,在ECOLOGY系统中提供了导出EXCEL文件的方法,weaver.file.ExcelFile,weaver.file.ExcelOut,weaver.file. ExcelSheet,weaver.file. ExcelRow进行了封装
实例
ExportExcelTest.jsp
<%@ page language="java" contentType="text/html; charset=GBK" %>
<%@ page import="weaver.file.*," %>
<jsp:useBean id="ExcelFile" class="weaver.file.ExcelFile"
scope="session"/>
<iframe id="ExcelOut" name="ExcelOut" border=0 frameborder=no
noresize=NORESIZE height="0%" width="0%"></iframe>
<%
ExcelSheet es = new ExcelSheet() ; // 初始化一个EXCEL的sheet对象 ExcelRow er = es.newExcelRow () ; //准备新增EXCEL中的一行
//以下为EXCEL添加多个列
er.addStringValue(“EXCEL第1列的值”) ;
er.addStringValue(“EXCEL第2列的值”) ;
……….
er.addStringValue(“EXCEL第n列的值”) ;
es.addExcelRow(er) ; //加入一行
ExcelFile.init() ;
ExcelFile.setFilename(“导出EXCEL文件的名字”) ;
ExcelFile.addSheet(“sheet的名字”, es) ; //为EXCEL文件插入一个SHEET %>
<a href=”/weaver/weaver.file.ExcelOut”>到处EXCEL文件</a>
2.10如何使用缓存提高系统效率
对于一些常用的信息,比如人员的名称,如果每次访问的时候都查询数据库来获取,将极大的影响系统的性能。
我们可以将这些信息放到系统的缓存中,在用到的时候,从系统缓存中获取。
(使用缓存是典型的用空间换时间的系统优化方式)
系统提供了 weaver.general.StaticObj 类来保存这些信息。
weaver.general.StaticObj 类使用 HashTable 来管理缓存信息,其主要的方法如下:
StaticObj将数据库中常用的数据放入缓存中,以加快系统的反应速度。
客户程序可以调用getInstance()方法访问本类的唯一实例。
StaticObj有两层缓存,分别为 mainKey - value 和 mainKey - subkey –value,由 mainKey 可以取得第一层的对象,由 mainKey - subkey 可以取得第二层的值,在第二层的值存在的情况下,第一层的值为 Hashtable。
/**
* 返回唯一实例.如果是第一次调用此方法,则创建实例
*
* @return StaticObj 唯一实例
*/
public static StaticObj getInstance()
/**
* 获取 mainKey 对应的第一层对象值
*
* @param key 主键名称
* @return Object 对于的第一层对象值
*/
public Object getObject(String key)
/**
* 设置 mainKey 对应的第一层对象值
*
* @param key 主键名称
* @param obj mainKey 对应的第一层对象值
*/
public void putObject(String key, Object obj)
/**
* 从缓存中清除 mainKey 对应的第一层对象值
*
* @param key 主键名称
*/
public void removeObject(String key)
/**
* 获取 mainKey - subkey 对应的第二层对象值
*
* @param HashKey 主键名称
* @param RecKey 子主键名称
* @return Object 对于的第二层对象值
*/
public Object getRecordFromObj (String HashKey, String RecKey) /**
* 设置 mainKey - subkey 对应的第二层对象值
*
* @param HashKey 主键名称
* @param RecKey 子主键名称
* @param obj mainKey - subkey对于的第二层对象值
*/
public void putRecordToObj (String HashKey, String RecKey, Object obj) /**
* 从缓存中清除 mainKey - subkey 对应的第二层对象值
*
* @param HashKey 主键名称
* @param RecKey 子主键名称
*/
public void removeRecordFromObj (String HashKey, String RecKey)
/**
* 从缓存中清除所有对象值
*
*/
public void clearRecord()
运用这些方法,我们可以构造所需要的缓存类,使用这些缓存类来对其它模块和功能提供缓存信息的接口,这些缓存类在系统中的命名为 XXXComInfo,其中XXX为相应缓存信息的名称。
参考如下的人力资源缓存类:
weaver.hrm.resource.ResourceComInfo。
ResourceComInfo 类主要提供人力资源信息中常用的一些信息的缓存,比如人员名称,所在部门。
对于这些信息,都需要一个键值。
常见的键值是这些信息在数据库表中的Primary Key,比如人力资源ID,其它模块和功能在关联人力资源信息的时候,只记录人力资源的ID,当需要获取人力资源的其它信息,如人员名称,所在部门的时候,从ResourceComInfo类提供的统一接口中获取。
weaver.hrm.resource.ResourceComInfo 的代码:
package weaver.hrm.resource;
import java.util.*;
import weaver.conn.*;
import weaver.general.*;
/**
* Title: 人力资源缓存信息接口类
* Description: 对其它模块和功能提供统一的获取人力资源信息的接口
* Copyright: Copyright (c) 2002
* Company: weaver
* @author liuyu
* @version 1.0
*/
public class ResourceComInfo extends BaseBean {
/* 1 */
private ArrayList ids = null; // 保存人力资源键值 ID 队列
private ArrayList loginids = null; // 保存人力资源登录名队列
private ArrayList lastnames = null; // 保存人力资源名称队列
private ArrayList departmentids = null; // 保存人力资源部门队列 private ArrayList seclevels = null; // 保存人力资源安全级别队列
private ArrayList statuses = null; // 保存人力资源状态队列 private StaticObj staticobj = null; // 公共缓存类
/* 2 */
private int current_index = -1; // 当前人力资源记录的指针 private int array_size = 0; // 人力资源记录的数量
/**
* 人力资源缓存信息接口类构造方法
* 构造方法中将获取公共缓存类的唯一实例,并调用getResourceInfo 方法获取缓存信息,
* 同时赋值人力资源记录的数量
*
*/
public ResourceComInfo() throws Exception{
staticobj = StaticObj.getInstance();
getResourceInfo() ;
array_size = ids.size();
}
/**
* 获取人力资源缓存信息方法
* 检查是否有人力资源缓存信息,如果没有,将调用setResourceInfo 方法从数据库中获取人力资源信息并放入缓存中
* 将缓存中的信息赋予相应的队列
*
*/
private void getResourceInfo() throws Exception{
/* 3 */
if(staticobj.getObject("ResourceInfo") == null)
setResourceInfo();
// 将缓存中的信息赋予相应的队列
ids = (ArrayList)(staticobj.getRecordFromObj("ResourceInfo", "ids"));
loginids = (ArrayList)(staticobj.getRecordFromObj("ResourceInfo", "loginids"));
lastnames = (ArrayList)(staticobj.getRecordFromObj("ResourceInfo", "lastnames"));
departmentids =
(ArrayList)(staticobj.getRecordFromObj("ResourceInfo", "departmentids"));
seclevels = (ArrayList)(staticobj.getRecordFromObj("ResourceInfo", "seclevels"));
statuses = (ArrayList)(staticobj.getRecordFromObj("ResourceInfo", "statuses"));
}
/**
* 从数据库获取人力资源信息并放入缓存方法
* 从数据库获取所需要的人力资源信息(该类所提供的人力资源信息) * 将获取的信息放入缓存中
*
*/
private void setResourceInfo() throws Exception{
// 生成队列实例
ids = new ArrayList();
loginids = new ArrayList();
lastnames = new ArrayList();
departmentids = new ArrayList();
seclevels = new ArrayList();
statuses = new ArrayList();
// 查询数据库并赋值队列
RecordSet rt = new RecordSet() ;
rt.executeProc("HrmResource_SelectAll","") ;
while(rt.next()){
ids.add(Util.null2String(rt.getString("id")));
loginids.add(Util.null2String(rt.getString("loginid")));
lastnames.add(Util.null2String(rt.getString("lastname"))); departmentids.add(""+Util.getIntValue(rt.getString("departmentid"),0)); seclevels.add(Util.null2String(rt.getString("seclevel")));
statuses.add(Util.null2String(rt.getString("status")));
}
/* 3 */
// 将获取的信息放入缓存中, 缓存中的一级键值为 "ResourceInfo" ,二级键值为人力资源对应的队列名称
staticobj.putRecordToObj("ResourceInfo", "ids", ids);
staticobj.putRecordToObj("ResourceInfo", "loginids", loginids); staticobj.putRecordToObj("ResourceInfo", "lastnames", lastnames);
staticobj.putRecordToObj("ResourceInfo", "departmentids", departmentids);
staticobj.putRecordToObj("ResourceInfo", "seclevels", seclevels); staticobj.putRecordToObj("ResourceInfo", "statuses", statuses); }
/**
* 获取人力资源信息数量方法
*
* @return int 人力资源信息数量
*
*/
public int getResourceNum() {
return array_size;
}
/* 2 */。