引?? 言?
??? 醫(yī)院信息系統(tǒng)(Hospital Information System 簡(jiǎn)稱(chēng)HIS)是醫(yī)療機(jī)構(gòu)信息化的產(chǎn)物,在一些發(fā)達(dá)國(guó)家(如美國(guó)、日本)中,對(duì)HIS的研究和運(yùn)用已有幾十年的歷史。隨著計(jì)算機(jī)信息網(wǎng)絡(luò)技術(shù)的提高,人們對(duì)信息需求的數(shù)量、質(zhì)量、速度也越來(lái)越高,加上國(guó)際醫(yī)學(xué)信息標(biāo)準(zhǔn)化、電子化的推進(jìn),促使人們?cè)贖IS的基礎(chǔ)上開(kāi)始嘗試由現(xiàn)在的紙張醫(yī)療信息管理向電子化(電子病歷系統(tǒng)Computer-based Patient Record systems簡(jiǎn)稱(chēng)CPRs)邁進(jìn)。它不是簡(jiǎn)單地將現(xiàn)有病歷計(jì)算機(jī)存儲(chǔ),而是一個(gè)多對(duì)多的,在Internet上通過(guò)Web Services實(shí)現(xiàn)各醫(yī)療機(jī)構(gòu)信息共享與交互,具有一定智能化的跨平臺(tái)系統(tǒng)。CPR將是醫(yī)院計(jì)算機(jī)網(wǎng)絡(luò)化管理的核心。
??? 對(duì)于這樣一個(gè)系統(tǒng),必須要求它具有良好的通用性和共享性。JAVA 從誕生到現(xiàn)在其跨平臺(tái)優(yōu)越性及其在網(wǎng)絡(luò)編程的出色表現(xiàn)得到了實(shí)踐的證明,以Java 2為核心的J2EE提供了一個(gè)企業(yè)級(jí)的計(jì)算模型和運(yùn)行環(huán)境用于開(kāi)發(fā)和部署瘦客戶(hù)端,多層體系結(jié)構(gòu)的應(yīng)用,滿(mǎn)足了用一種健壯的、安全的、事務(wù)性的方法在 Web 上提供現(xiàn)有的應(yīng)用程序和業(yè)務(wù)流程的需要,因此稱(chēng)霸企業(yè)信息化平臺(tái);使用XML作為數(shù)據(jù)交換格式,Web Services通過(guò)一系列標(biāo)準(zhǔn)和協(xié)議(如SOAP,UDDI,WSDL)來(lái)保證程序之間的動(dòng)態(tài)連接,允許應(yīng)用程序可跨編程語(yǔ)言和操作系統(tǒng)進(jìn)行交互的優(yōu)越性非常明顯。兩者的結(jié)合能使開(kāi)發(fā)人員輕松構(gòu)架復(fù)雜強(qiáng)大的Web Services應(yīng)用。本文介紹的電子病歷系統(tǒng)正是采用了J2EE架構(gòu)和Web Services技術(shù)。?
需求分析和系統(tǒng)設(shè)計(jì)?
??? 電子病歷系統(tǒng)并不是簡(jiǎn)單的紙張病歷”電子化”,它至少應(yīng)該具備:1. 信息資源共享:醫(yī)院各個(gè)科室的醫(yī)生在任何地方、任何時(shí)候只要有聯(lián)網(wǎng)的計(jì)算機(jī),就能調(diào)閱到本醫(yī)院的全部病歷記錄, 會(huì)診的醫(yī)院之間能查到在任何一個(gè)醫(yī)院的病人病歷;2. 強(qiáng)大的提示系統(tǒng):病人能看到醫(yī)生對(duì)自己診斷開(kāi)出的臨時(shí)或長(zhǎng)期醫(yī)囑,能及時(shí)向醫(yī)生反饋用藥情況;對(duì)醫(yī)務(wù)工作人員有藥物配伍禁忌,醫(yī)療方法不正當(dāng)?shù)奶崾?是智能化醫(yī)療的一種體現(xiàn);3. 支持醫(yī)療信息資料庫(kù):有電子信息可供學(xué)習(xí),以及關(guān)于病例治療最新方法供醫(yī)療人員在工作時(shí)查詢(xún)使用。

這樣的設(shè)計(jì)完全符合了MVC(Model -view-controller)模式。
當(dāng)J2EE映射到MVC各部分時(shí): 模型(Model)是數(shù)據(jù)源,是鏈接數(shù)據(jù)庫(kù)
獲得數(shù)據(jù)的EJB或JavaBean;視圖(View)是JSP或是Servlets;控制
(Controller)它連接選定的視圖到數(shù)據(jù),就是數(shù)據(jù)表。核心業(yè)務(wù)過(guò)程應(yīng)
該完全不依賴(lài)于特定的客戶(hù)端程序。業(yè)務(wù)邏輯和視圖元素之間的數(shù)據(jù)交互分配
給控制器完成,J2EE的業(yè)務(wù)邏輯組件獲得相當(dāng)高的可重用性。
系統(tǒng)實(shí)現(xiàn)關(guān)鍵技術(shù)
1) 本系統(tǒng)的一個(gè)EJB----實(shí)現(xiàn)病歷管理
??? 一般一個(gè)EJB是由Home接口、遠(yuǎn)程接口和Bean類(lèi),以及輔助的類(lèi)組成。Remote接口定義EJB組件中提供的可供用戶(hù)調(diào)用的方法,及實(shí)現(xiàn)商業(yè)邏輯的函數(shù)或過(guò)程,以供遠(yuǎn)程客戶(hù)端調(diào)用;Home接口定義一組方法來(lái)創(chuàng)建新的EJB對(duì)象,查找,定位和清除已有的EJB對(duì)象; EJB Object為網(wǎng)絡(luò)可視對(duì)象,包含Stub和Skeleton作為Bean的代理。這樣的結(jié)構(gòu)使得訪(fǎng)問(wèn)遠(yuǎn)程對(duì)象就像訪(fǎng)問(wèn)本地對(duì)象一樣,保證分布式的應(yīng)用,增加各組件互操作性。本系統(tǒng)中所有數(shù)據(jù)都封裝到實(shí)體Bean中。下面介紹本系統(tǒng)中一個(gè)EJB接口,DiagnosisOpr(病歷管理):
import java.util.*;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import com..diagnosis.tool.*;
public interface DiagnosisOpr extends EJBObject{
?/** 往病歷表中增加病歷信息? *@param ht 保存病歷的字段名稱(chēng)和值? */
?public void addDiagnosis(Hashtable ht) throws Dexception,RemoteException;
/** 根據(jù)病人id 刪除病歷信息 ?*/
?public void delDiagnosis(String strSufferer Id) throws Dexception,RemoteException;
/** 根據(jù)病人id 得到病歷信息?*/
?public Hashtable getDiagnosis(String strSufferer Id) throws Dexception,RemoteException;
??。。。。。。}
??? 假如醫(yī)生想在查看病人的以往的病歷信息,那么程序就是調(diào)用getDiagnosis()方法,得到病人的病歷信息。在DiagnosisOpr類(lèi)中,就是:
public Hashtable getDiagnosis(String strSufferer Id) throws Dexception,RemoteException
{?if(找不到病人的ID)
throw new Dexception???????????? //拋出異常
else{? 根據(jù)病人的ID,從數(shù)據(jù)庫(kù)中讀取指定的病人的病歷信息,然后按照一定的算法把這些信息壓到Hashtable中。}
}
??? 在頁(yè)面展現(xiàn)的時(shí)候,jsp頁(yè)面得到的是一個(gè)Hashtable對(duì)象,這樣訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的處理交給EJB來(lái)完成的,jsp只是負(fù)責(zé)展現(xiàn)。EJB體現(xiàn)了將商業(yè)邏輯與底層的系統(tǒng)邏輯分開(kāi),使開(kāi)發(fā)者只需關(guān)心商業(yè)邏輯,而由EJB容器實(shí)現(xiàn)目錄服務(wù),事務(wù)處理等底層系統(tǒng)邏輯核心思想。
2)?SOAP協(xié)議中傳輸醫(yī)療圖片
??? SOAP協(xié)議是Web Services中的關(guān)鍵技術(shù),它是一種使用XML編碼數(shù)據(jù)的以文本為基礎(chǔ)的關(guān)于消息傳遞的有線(xiàn)協(xié)議,它規(guī)定了Web Services之間是怎樣傳遞信息的。為Java的平臺(tái)無(wú)關(guān)性,可移植性帶來(lái)了更高層次的協(xié)同操作能力。
在電子病歷系統(tǒng)中保存了病人的照片,X光片,以及CT光片等等輔助治療的圖片。當(dāng)其他系統(tǒng)如診斷系統(tǒng)需要這些圖片的時(shí)候,就可以通過(guò)SOAP協(xié)議傳送這些圖片。實(shí)現(xiàn)方法是SOAP消息與一個(gè)或多個(gè)圖片聯(lián)系起來(lái),并保留圖片的原始格式,作為一個(gè)多組分MIME結(jié)構(gòu)來(lái)傳輸。這種實(shí)現(xiàn)方法是將多組分MIME結(jié)構(gòu)作為傳輸協(xié)議綁定的一個(gè)基本組成部分,也就是說(shuō),對(duì)于SOAP消息而言,它等同于傳輸協(xié)議報(bào)頭。下面的例子是帶一個(gè)圖片的SOAP1.1消息,其中圖片的內(nèi)容是病人的X光片(username_x1.jpg)。
MIME-Version: 1.0
Content-Type:Multipart/Related;
boundary=MIME_boundary;
type=text/xml;
start="< username_x1.xml@sina.com >"
Content-Description: 病人的X光片
--MIME_boundary?
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: < username_x1.xml@sina.com>
…
…
--MIME_boundary
Content-Type: image/jpg
Content-Transfer-Encoding: binary
Content-ID:
...二進(jìn)制jpg圖片...
--MIME_boundary--
??? 后端服務(wù)實(shí)現(xiàn):后端服務(wù)實(shí)現(xiàn)是在類(lèi) PicManagementImpl 中使用公共可訪(fǎng)問(wèn)的服務(wù)方法如 SubmitArrayOfPics 和 FetchPics 處理的。這里的 SubmitArrayOfPics 服務(wù),是一個(gè)基于 RPC 的 SOAP 服務(wù)方法,參數(shù)包括 SOAPContext(用來(lái)處理圖片)、User(用戶(hù)信息,用來(lái)認(rèn)證訪(fǎng)問(wèn)者的信息)和一個(gè) PicInfo 數(shù)組(提交到服務(wù)器的圖片)。FetchPics 方法是一個(gè)基于 RPC 的服務(wù),用戶(hù)信息和文檔引用對(duì)象都作為其參數(shù)。文檔引用對(duì)象包含有關(guān)已經(jīng)提交給服務(wù)器并保存在服務(wù)器中的文檔的信息(picRefId)。?程序片斷如下:
/*apache soap*/? import org.apache.soap.*;???? import org.apache.soap.rpc.*;
import org.apache.soap.util.xml.XMLParserUtils;??? import org.apache.soap.encoding.SOAPMappingRegistry;
/* MIME*/ import javax.activation.*;?? import javax.mail.*;? import javax.mail.internet.*;
/* java*/ import java.util.*;????????? import java.io.*;
public class PicManagementImpl implements PicManagement{
/** 發(fā)送一段圖片數(shù)組,圖片數(shù)據(jù)必須從SOAPContext中返回,一旦數(shù)據(jù)返回就保存到數(shù)據(jù)庫(kù)中,并給用戶(hù)返回圖片的reference */
?public PicReference[] SubmitArrayOfPics(SOAPContext requestContext, User user,
PicInfo[] localPicInfo) ? ?throws Dexception ,Exception?{}
??? /** 根據(jù)PicReference返回服務(wù)器上的圖片信息(數(shù)據(jù)庫(kù)中的圖片信息),所有
的圖片信息作為附件返回給用戶(hù) */
public void FetchPics (PicReference[] picRef) throws Dexception ,Exception{}
??? /** 在服務(wù)器上保存圖片,并返回操作結(jié)果(PicReference)*/
private synchronized PicReference savePic(User user, PicInfo userDefinedPicName,
Object content)??? throws Dexception ,Exception{}?
?。。。。。。}
??? 如上面服務(wù)代碼中所示,使用 SOAPContext 請(qǐng)求對(duì)象來(lái)獲取附件信息。這個(gè)對(duì)象包含主體部件,主體部件是一組 MIME 部件,其中根部件包含 SOAP 信封。接受到這個(gè)MIME消息后,可以從 MIME 主體部件抽取許多信息,包括內(nèi)容標(biāo)識(shí)、內(nèi)容類(lèi)型和位置。
????客戶(hù)機(jī)服務(wù)實(shí)現(xiàn):客戶(hù)機(jī)代碼在 SOAPMappingRegistry 中創(chuàng)建類(lèi)型映射信息來(lái)組織和解組 Java 技術(shù)類(lèi)如 User(用戶(hù)信息類(lèi))、PictInfo(圖片信息類(lèi)) 和 PicReference(圖片的引用) 并將其和請(qǐng)求對(duì)象綁定在一起,代碼如下所示:
?BeanSerializer beanSer = new BeanSerializer();? // 以下為設(shè)置 SOAP mapping registry
?SOAPMappingRegistry smr = new SOAPMappingRegistry();
?smr.mapTypes(Constants.NS_URI_SOAP_ENC,new QName
?("urn:xml-docmanger-webservice", "user"),User.class, beanSer, beanSer);?
request.setSoapMappingRegistry(smr);?????? // 設(shè)置 mapping registry
?? 如上代碼使用 bean 序列化器類(lèi)(BeanSerializer)對(duì)類(lèi)(如 User,遵守 JavaBean 的設(shè)計(jì)模式)進(jìn)行序列化和反序列化。
?? 下面是發(fā)送圖片的部分代碼:byteStream 是從數(shù)據(jù)庫(kù)中讀出來(lái)的圖片字節(jié)流
?DataSource ds = new ByteArrayDataSource(byteStream.toByteArray(), null);
DataHandler dh = new DataHandler(ds);
??? MimeBodyPart mbp = new MimeBodyPart();
??? mbp.setDataHandler(dh);
request.addAttachment(mbp);????????????? // 把圖片加入到服務(wù)請(qǐng)求上
3)?連接數(shù)據(jù)庫(kù)
??? Java中連接數(shù)據(jù)庫(kù)的技術(shù)是JDBC,本系統(tǒng)采用JDBC2.0標(biāo)準(zhǔn),通過(guò)使用 DataSource 接口(javax.sql.ConnectionPoolDataSource該接口充當(dāng)合用的 java.sql.Connection 對(duì)象的資源管理器連接 factory),J2EE 組件可以獲得物理數(shù)據(jù)庫(kù)連接對(duì)象:
Context?ctx?=?new?InitialContext();
DataSource?ds?=?(DataSource)?ctx.lookup("jdbc/UserDB");//用UserDB對(duì)應(yīng)DataSource對(duì)象Connection?conn?=?ds.getConnection("password","username");? //獲得Connection對(duì)象
JDBC2.0的另一個(gè)新規(guī)范是Connection?Pooling,( javax.sql.PooledConnection)每一個(gè)連接
池對(duì)象管理一組JDBC連接對(duì)象,每一個(gè)連接對(duì)象可以被任意數(shù)量的Servlet共享。finally{if(con?!=?null)?con.close();}保證了連接的循環(huán)利用,減小建立連接開(kāi)銷(xiāo)。為了減少與服務(wù)器以及數(shù)據(jù)庫(kù)之間的連接次數(shù),可把從數(shù)據(jù)庫(kù)中讀取的內(nèi)容存到一個(gè)HashTable或者一個(gè)XML文件中以備使用。本系統(tǒng)創(chuàng)建一個(gè)公用的JavaBean,封裝與數(shù)據(jù)庫(kù)的連接操作。
結(jié)束語(yǔ)
??? 早在1994年第6屆醫(yī)藥信息學(xué)大會(huì)上,國(guó)家衛(wèi)生部提出“希望到本世紀(jì)末,全國(guó)將有若干家醫(yī)院能夠真正實(shí)現(xiàn)完整的CPR系統(tǒng)”,足以證明CPR的重要地位。如今,J2EE已成為眾多企業(yè)平臺(tái)架構(gòu)的標(biāo)準(zhǔn),而Web Services被認(rèn)為是下一代的web應(yīng)用開(kāi)發(fā),前景良好。本文只是對(duì)用基于J2EE架構(gòu)的Web Services實(shí)現(xiàn)電子病歷系統(tǒng)有一個(gè)初步的探索,相信基于Web Services的電子病歷系統(tǒng)必定會(huì)有一個(gè)美好的未來(lái),期待國(guó)內(nèi)醫(yī)院早日實(shí)現(xiàn)CPR!
參考文獻(xiàn)
1.陳文彬主編.診斷學(xué)(第五版).人民衛(wèi)生出版社,
2.http://java.sun.com/j2ee?????????????
3.http://www.w3.org/TR/SOAP/
4.http://www-900.ibm.com/developerWorks/cn/index.shtml
