監(jiān)理公司管理系統 | 工程企業(yè)管理系統 | OA系統 | ERP系統 | 造價咨詢管理系統 | 工程設計管理系統 | 甲方項目管理系統 | 簽約案例 | 客戶案例 | 在線試用
X 關閉
OA系統二次開發(fā)

當前位置:工程項目OA系統 > 泛普服務體系 > OA系統二次開發(fā)

泛普協同OA辦公底層包開發(fā)指南

申請免費試用、咨詢電話:400-8352-114

 
1.     引言... 4
1.1       概述... 4
1.2       定義... 4
2.     底層包應用及范例... 4
2.1       最基本的繼承類... 4
2.2       怎樣記錄日志... 5
2.3       怎樣獲取屬性文件的值... 8
2.4       怎樣獲取系統的運行目錄... 10
2.5       怎樣訪問和運行數據庫腳本... 11
2.6       如何上傳一個文件... 15
2.7       如何訪問已經上傳的文件... 19
2.8       如何使用緩存提高系統效率... 20
2.9       其它底層類基本方法... 29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

1.    引言

 

1.1      概述

 
本文檔為泛普協同OA商務系統(泛普OA系統)程序員開發(fā)指導文檔,講述了開發(fā)底層工具包的應用,常用功能的開發(fā)。
 
 

2.    底層包應用及范例

 
本章對泛普OA系統   OA系統的底層工具包進行講解,開發(fā)人員可以從這里學到怎樣利用底層的工具包進行開發(fā)
 
 

2.1      最基本的繼承類

 
泛普OA管理系統中每一個java bean 都需要繼承 泛普OA系統.general.BaseBean 類 。這個類實現了記錄日志和獲取屬性文件值的方法。繼承這兩個類的其它類可直接應用這些方法來記錄日志,獲取屬性文件某一個屬性的值。方法的實現見后面的例子。
繼承的例子如下:
 
java bean 的繼承
 
public class ResourceComInfo extends BaseBean {
 
       public void doSomething() {          //某一個方法
              方法的處理………
              writeLog(s) ;       // 寫日志
       }
}
 
 
 
 
 
 
 
 

2.2      泛普OA辦公系統怎樣記錄日志

 
繼承了泛普OA系統.general.BaseBean  ,可以直接使用 writeLog方法記錄日志信息。注意這里是使用,而不是調用,因為這個方法是這兩個被繼承類中的方法。
 
注意writeLog 方法的使用:
/**
* 將某個對象寫入Log文件
* @param obj 被寫入的對象
*/
  public void writeLog(Object obj)
 
我們看到,可以被記入日志的是任意一個java對象。這些java對象將被自動轉換成字符串對象(String)記入到日志文件中。日志文件將每天生成一個,以日志文件名稱中的日期來區(qū)別,比如:泛普OA系統_20030812.log,代表2003年8月12日的日志。當天的日志為泛普OA系統.log。每一條日志的記錄格式為 :
YYYY.MM.DD-HH:MM:SS 記錄日志的類名 – 日志信息
比如:
2003.03.11-06:52:05 泛普OA系統.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 (異常)的對象才會記錄到日志文件中。模式的設置在/泛普OA系統/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
log4j.logger.org = ERROR
log4j.logger.uk = ERROR
 
 
log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A2.DatePattern='_'yyyyMMdd'.log'
#don't modify the file property
log4j.appender.A2.File=@泛普OA系統
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.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{
   
業(yè)務處理過程……….
 
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  泛普OA系統.hrm.resource. ResourceComInfo - debug info is This is test
 
如果有異常,將會記錄為:
2007-10-15 16:51:50,125  ERROR  泛普OA系統.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)
       at com.microsoft.jdbc.sqlserver.SQLServerImplStatement.getNextResultType(Unknown Source)
       at com.microsoft.jdbc.base.BaseStatement.commonExecute(Unknown Source)
       at com.microsoft.jdbc.base.BaseStatement.executeInternal(Unknown Source)
       at com.microsoft.jdbc.base.BasePreparedStatement.execute(Unknown Source)
       at 泛普OA系統.conn.RecordSet.executeProc(RecordSet.java:155)
       at 泛普OA系統.conn.RecordSet.executeProc(RecordSet.java:109)
       at 泛普OA系統.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)
       at com.caucho.server.http.RunnerRequest.handleRequest(RunnerRequest.java:333)
       at com.caucho.server.http.RunnerRequest.handleConnection(RunnerRequest.java:266)
       at com.caucho.server.TcpConnection.run(TcpConnection.java:140)
       at java.lang.Thread.run(Thread.java:484)
 
從上面的日志信息,可以看到ResourceComInfo類的59行代碼運行的時候出現錯誤,這個錯誤是執(zhí)行數據庫操作的腳本錯誤,具體的錯誤信息是:形式參數 '@id_1' 定義為 OUTPUT,但實際參數卻未聲明為 OUTPUT。說明調用數據庫腳本的時候參數的數量有出入。
 開發(fā)過程中請將日志級別設置為INFO,通過日志可檢查程序在哪里出錯了。

2.3      泛普辦公平臺怎樣獲取屬性文件的值

 
繼承了泛普OA系統.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:泛普OA系統,那么屬性文件必須放在d:泛普OA系統WEB-INFprop 目錄下,取名為 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{
   
業(yè)務處理過程……….
 
String keyValue = getPropValue(“thefilename” , “thekeyname”) ;
 
// 將鍵值thekeyname的值keyValue記入日志文件
                writeLog("keyvalue is "+ keyValue) ;          
                
}
}
 
系統的主屬性文件 泛普OA系統.properties 的文件名“泛普OA系統” 作為系統常量放在泛普OA系統.general.GCONST 類中,可以使用getConfigFile() 方法來返回 “泛普OA系統 ”,在編程的過程中,如果需要用到泛普OA系統.properties屬性文件中的鍵值,請用GCONST. getConfigFile() 來獲取,當主屬性文件名稱因為需要改變得時候,不必改變所有用到這個屬性文件的類,只需要改變GCONST類中常量的值
 
 

2.4      泛普OA系統怎樣獲取系統的運行目錄

 
泛普OA系統.general.GCONST 類提供了一個靜態(tài)方法getRootPath() ,返回系統的運行目錄,比如系統的運行目錄為d 盤的泛普OA系統目錄,將返回d:泛普OA系統
 
獲取系統的運行目錄的例子如下:
 
public class TestBean extends BaseBean {
      
       import 泛普OA系統.general.GCONST ;
 
public void getSysRunPath(){
   
String sysRunPath = GCONST. GetRootPath() ;
 
// 將系統的運行目錄sysRunPath的值記入日志文件
                writeLog("sysRunPath is "+ sysRunPath) ;        
                
}
}

2.5      泛普OA軟件怎樣訪問和運行數據庫腳本

 
在泛普OA系統系統中,大量的數據庫訪問,鏈接的建立和持續(xù)性,事務的處理,鏈接池的維護等問題都被封裝在泛普OA系統.conn 包下面的各個類中,應用程序的實現者不需要去關心這些問題,而只需要調用泛普OA系統.conn.RecordSet 類來執(zhí)行各種數據庫操作。
 
泛普OA系統.conn.RecordSet 類實現了從數據庫鏈接池中獲取鏈接,執(zhí)行指定的數據庫腳本或者存儲過程,并在腳本或者存儲過程執(zhí)行完畢后將鏈接及時地歸還到鏈接池中。
 
泛普OA系統系統的鏈接池管理請參見 泛普OA系統.conn.ConnectionPool , 泛普OA系統.conn.DBConnectionPool ,泛普OA系統.conn.ConnCheckerTimer 類的API 文檔,泛普OA系統.conn.ConnectionPool 用于管理泛普OA系統系統中的所有數據庫鏈接池(泛普OA系統系統可以同時鏈接多個數據庫,每一個數據庫均有一個對應的數據庫鏈接池,由泛普OA系統.conn.DBConnectionPool負責管理,而泛普OA系統.conn.ConnectionPool則是這些鏈接池的大管家,負責所有鏈接池的協調和統一對外接口),泛普OA系統.conn.DBConnectionPool用于建立和管理對某一個數據庫的鏈接池,泛普OA系統.conn.ConnCheckerTimer用于監(jiān)控各個鏈接池的狀況,定期對數據庫鏈接池中不符合要求的鏈接進行清理,并監(jiān)視是否需要在某一鏈接池中建立新的鏈接。
 
調用泛普OA系統.conn.RecordSet,實現對數據的操作,下面進行詳細的說明:
 
泛普OA系統.conn.RecordSet類采用 java.sql 中的 CallableStatement 和 Statement 執(zhí)行數據庫操作??蛻舳酥苯诱{用該類進行數據庫操作。不需要考慮數據庫鏈接的建立。其中客戶端指所有調用該類進行數據庫操作的應用程序,不特指用戶的客戶端。
 
RecordSet 執(zhí)行數據庫操作有兩種形式,一種為調用存儲過程,另一種為直接執(zhí)行SQL語句。與ConnStatement不同 ,RecordSet 執(zhí)行SQL語句不分查詢和修改,都在一條語句中執(zhí)行。RecordSet執(zhí)行腳本的方式如下:
 
1、使用默認的鏈接池執(zhí)行SQL語句:  
RecordSet rs = new RecordSet() ;
rs.executeSql(" select * from TB_Example ") ;
while( rs.next() ) {
String thename = rs.getString("name") ;
其它處理代碼....……
}
在JSP頁面中,可以通過以下方式應用
<%@ page import="泛普OA系統.general.Util" %>
<%@ page import="泛普OA系統.conn.*" %>
<%@ page import="java.util.*,java.sql.Timestamp" %>
<%@ page language="java" contentType="text/html; charset=GBK" %>
<%@ include file="/systeminfo/init.jsp" %>
<jsp:useBean id="rs" class="泛普OA系統.conn.RecordSet" scope="page" />
<%rs.execute(“”);   //執(zhí)行SQL語句
while( rs.next() ) {
String thename = rs.getString("name") ;
其它處理代碼....……
}
 
rs. executeProc (“存儲過程名稱”,para);   //執(zhí)行存儲過程
while( rs.next() ) {
String thename = rs.getString("name") ;
其它處理代碼....……
}
 
 
%>
 
2、使用指定的鏈接池泛普OA系統test執(zhí)行SQL語句
RecordSet rs = new RecordSet() ;
rs.executeSql(" update TB_Example set name = 'the new value' " , "泛普OA系統test" ) ;
 
 
 3、使用指定的鏈接池泛普OA系統test執(zhí)行存儲過程 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 , "泛普OA系統test" ) ;
 
procpara 是存儲過程的參數值組成的字符串變量,多個參數值之間用 泛普OA系統.general.Util.getSeparator() 分開
 
 
4、在一個客戶程序多個執(zhí)行之間,查詢結果可以保留到下一次查詢
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{
   
業(yè)務處理過程……….
 
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)、泛普OA系統.conn.ConnectionPool 類的管理和設置:
 
所有的數據庫鏈接池的集合,用鏈接池名稱區(qū)別每一個鏈接池.支持對一個或多個由屬性文件定義的數據庫連接池的訪問.客戶程序可以調用getInstance()方法訪問本類的唯一實例。
 
對于一個鏈接池集合來說,可以有多個鏈接池,分別鏈接不同的數據庫。應用程序指定鏈接池的名稱來調用不同的鏈接池。如果應用程序沒有指定鏈接池的名稱,將使用默認的鏈接池。默認鏈接池的指定有兩種方式:
 
1、在Application Server設置的初始參數serverName的值 ,以Resin 為例:
<servlet servlet-name='InitServer' servlet-class='泛普OA系統.general.InitServer'>
      <init-param serverName='泛普OA系統'/>
<load-on-startup/>
</servlet>
 
2、如果Application Server沒有相應設置,則系統使用屬性文件(泛普OA系統.properties)中設置的默認鏈接池名稱:
DefaultPoolName = 泛普OA系統
 
對于所有的鏈接池,系統需要加載相應的 JDBC Driver來建立與相應數據庫的鏈接。這些 Driver 在屬性文件(泛普OA系統.properties)中指定,多個Driver中間用空格隔開:
DriverClasses = com.microsoft.jdbc.sqlserver.SQLServerDriver
 
對于每一個鏈接池需要用到的參數在屬性文件(泛普OA系統.properties)中指定,屬性文件中參數的名稱以鏈接池的名稱開頭,中間加入小數點,比如鏈接池 泛普OA系統 的參數指定為 :
 
泛普OA系統.url = jdbc:microsoft:sqlserver://10.1.1.205:1433;DatabaseName=泛普OA系統    //db url
泛普OA系統.user = sa                                                                     //db user name       
泛普OA系統.password = 123456                                                        //db user password
泛普OA系統.charset = ISO_1                                                          //db encode          
泛普OA系統.maxconn = 10                                                             //max conn in conn pool
泛普OA系統.minconn = 2                                                              //min conn in conn pool
泛普OA系統.maxusecount = 30              //the max use times of a conn           
泛普OA系統.maxidletime = 30            //the max unuse time of a conn (分)
泛普OA系統.maxalivetime = 2            //一個鏈接被調用后的最大未歸回時間 (分)
泛普OA系統.checktime = 500                                                          //檢查的頻率 (秒)
 
 
 
b)、泛普OA系統.conn. DBConnectionPool類的管理和設置:
 
數據庫鏈接池,所有創(chuàng)建的鏈接存放在鏈接池中,在客戶端鏈接數據庫時從鏈接池中取出鏈接,客戶端在完成數據庫操作后將鏈接返回鏈接池。
 
               
鏈接池創(chuàng)建鏈接需要用到的參數在屬性文件(泛普OA系統.properties)中指定,屬性文件中參數的名稱以鏈接池的名稱開頭,中間加入小數點,比如鏈接池 泛普OA系統 的參數指定為 :
 
泛普OA系統.url = jdbc:microsoft:sqlserver://10.1.1.205:1433;DatabaseName=AIS2002    //db url
泛普OA系統.user = sa                                                                     //db user name       
泛普OA系統.password = 123456                                                        //db user password
泛普OA系統.charset = ISO_1                                                          //db encode          
泛普OA系統.maxconn = 10                                                             //max conn in conn pool
泛普OA系統.minconn = 2                                                              //min conn in conn pool
泛普OA系統.maxusecount = 30              //the max use times of a conn           
泛普OA系統.maxidletime = 30            //the max unuse time of a conn (分)
泛普OA系統.maxalivetime = 2            //一個鏈接被調用后的最大未歸回時間 (分)
泛普OA系統.checktime = 500                                                          //檢查的頻率 (秒)
 
 
 

2.6      泛普OA辦公如何上傳一個文件

 
上傳一個文件只需要調用泛普OA系統.file.FileUpload 類。泛普OA系統.file.FileUpload 類支持各種文件格式的上傳,也支持多文件的上傳。
 
B/S 架構的文件上傳采用的是multipart/form-data 協議,而不是HTTP協議,采用這種協議上傳的數據必須通過特殊的處理,而不能用常規(guī)的方法來獲取,否則不能得到數據。泛普OA系統.file.FileUpload 封裝了底層處理的代碼,應用程序的實現者不需要關心這些細節(jié)!
 
泛普OA系統.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 ,這個表的結構如下:
Column(s) of "ImageFile" Table
Name Datatype Null Option Comment
imagefileid int NOT NULL 文件id
imagefilename varchar(200) NULL 文件名稱
imagefiletype varchar(50) NULL 文件MIME類型
filerealpath varchar(255) NULL 文件存放目錄
imagefileused int NULL 文件使用次數
iszip char(1) NULL 是否壓縮
0:否
1:是
isencrypt char(1) NULL 是否加密
0:否
1:是
imagefile image NULL 文件(存在在數據庫中的文件內容,現已不使用)
 
從表結構可以看出,我們得到了某一個文件信息的imagefileid,就可以從該表中得到相應的文件名稱(這里指文件的實際名稱,比如test.doc), 文件MIME類型(比如 txt,doc,gif等) ,文件存放目錄(這里指在服務器中存放的實際路徑信息,包括實際存放的文件名稱,比如 e:泛普OA系統filesystem2003