以一个工作中编写的安全域信息同步为例进行描述;
安全域信息同步其实就是一个XML文件的传输,WEB SERVICE 本质上就是通过XML进行数据的传输.
传输的XML格式如下:
<?xml version="1.0" encoding="UTF-8" ?> - <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> - <SOAP-ENV:Body> - <simota:SynSecurityDomain xmlns:simota="http://www.chinamobile.com"> <simota:SeqNum>1111</simota:SeqNum> <simota:SessionID>1111</simota:SessionID> <simota:SynType>01</simota:SynType> - <simota:SecurityDomain> <simota:AppAID>123456789</simota:AppAID> <simota:InstallParams>222222</simota:InstallParams> <simota:MinAppSize>33</simota:MinAppSize> <simota:ManageMaxSize>44</simota:ManageMaxSize> <simota:ManageMinSize>55</simota:ManageMinSize> <simota:DomainType>66</simota:DomainType> <simota:DeleteRule>77</simota:DeleteRule> <simota:SIN>8</simota:SIN> <simota:TAR>99</simota:TAR> </simota:SecurityDomain> </simota:SynSecurityDomain> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
|
根据该XML需要编写响应的解析类来接收XML文件传输过来的数据:
解析类如下:
package com.watchdata.raadtinterface.common.syn;
import org.jdom.Element; import org.jdom.Namespace; import org.apache.commons.logging.*; import com.watchdata.raadtinterface.common.*;
public class SynSecurityDomainRequest implements BaseMsg { public SynSecurityDomainRequest() { }
private String seqNum; private String sessionID; private String synType; private SecurityDomainBean securityDomain;
/** * getObject * 安全域信息同步 * @param methodElement Element * @param nameSpace Namespace * @return BaseMsg */ public BaseMsg getObject(Element methodElement, Namespace nameSpace) { System.out.println("SynSecurityDomainRequest============"); Log log = LogFactory.getLog(getClass().getName()); SynSecurityDomainRequest syndomain = new SynSecurityDomainRequest();
Element SeqNum = methodElement.getChild("SeqNum", nameSpace); log.info("SeqNum==" + SeqNum.getText()); Element SessionID = methodElement.getChild("SessionID", nameSpace); log.info("SessionID==" + SessionID.getText()); Element SynType = methodElement.getChild("SynType", nameSpace); log.info("SynType==" + SynType.getText()); Element SecurityDomain = methodElement.getChild("SecurityDomain", nameSpace);
Element AppAID = SecurityDomain.getChild("AppAID", nameSpace); log.info("-------AppAID==" + AppAID.getText()); Element InstallParams = SecurityDomain.getChild("InstallParams", nameSpace); log.info("--InstallParams---" + InstallParams.getTextTrim()); Element MinAppSize = SecurityDomain.getChild("MinAppSize", nameSpace); log.info("MinAppSize==" + MinAppSize.getText()); Element ManageMaxSize = SecurityDomain.getChild("ManageMaxSize", nameSpace); log.info("ManageMaxSize=" + ManageMaxSize.getText()); Element ManageMinSize = SecurityDomain.getChild("ManageMinSize", nameSpace); log.info("ManageMinSize" + ManageMinSize.getText()); Element DomainType = SecurityDomain.getChild("DomainType", nameSpace); log.info("DomainType=" + DomainType.getText()); Element DeleteRule = SecurityDomain.getChild("DeleteRule", nameSpace); log.info("DeleteRule==" + DeleteRule.getText()); Element SIN = SecurityDomain.getChild("SIN", nameSpace); log.info("SIN=" + SIN.getText()); Element TAR = SecurityDomain.getChild("TAR", nameSpace); log.info("TAR==" + TAR.getText());
if (null == SeqNum || null == SessionID || null == SynType || null == AppAID || null == InstallParams || null == MinAppSize || null == ManageMaxSize || null == ManageMinSize || null == DomainType || null == DeleteRule || null == SIN || null == TAR ) { log.error("数据转换模块传的参数错误!"); return null; }
syndomain.setSeqNum(SeqNum.getTextTrim()); syndomain.setSessionID(SessionID.getTextTrim()); syndomain.setSynType(SynType.getTextTrim()); SecurityDomainBean sdbean = new SecurityDomainBean(); sdbean.setAppAID(AppAID.getTextTrim()); sdbean.setDeleteRule(DeleteRule.getTextTrim()); sdbean.setDomainType(DomainType.getTextTrim()); sdbean.setInstallParams(InstallParams.getTextTrim()); sdbean.setManageMaxSize(Long.parseLong(ManageMaxSize. getTextTrim())); sdbean.setManageMinSize(Long.parseLong(ManageMinSize. getTextTrim())); sdbean.setMinAppSize(Long.parseLong(MinAppSize. getTextTrim())); sdbean.setSin(SIN.getTextTrim()); sdbean.setTar(TAR.getTextTrim()); syndomain.setSecurityDomain(sdbean); return syndomain; }
public SecurityDomainBean getSecurityDomain() { return securityDomain; }
public String getSeqNum() { return seqNum; }
public String getSessionID() { return sessionID; }
public String getSynType() { return synType; }
public void setSecurityDomain(SecurityDomainBean securityDomain) { this.securityDomain = securityDomain; }
public void setSeqNum(String seqNum) { this.seqNum = seqNum; }
public void setSessionID(String sessionID) { this.sessionID = sessionID; }
public void setSynType(String synType) { this.synType = synType; } } |
其中类中实现的一个类BaseMsg 是一个接口:
package com.watchdata.raadtinterface.common;
import org.jdom.*;
public abstract interface BaseMsg {
public abstract BaseMsg getObject(Element methodElement, Namespace nameSpace); } |
每个解析类需要实现这个接口,然后通过接口中定义的方法getObject 来获得解析的结果数据BEAN
基本数据准备好后需要提供一个servlet,在这里我定义为InterfaceServiceServlet
package com.watchdata.raadtinterface.center;
import javax.servlet.*; import java.io.*; import javax.xml.messaging.JAXMServlet; import javax.xml.messaging.ReqRespListener; import javax.xml.soap.*; import java.util.*; import javax.servlet.*; import javax.xml.soap.*; import org.apache.commons.logging.*; import org.bouncycastle.crypto.*; import javax.xml.transform.stream.*; import org.apache.commons.logging.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
/** * * <p>Title:RAADataTrans作为服务器端的接口发布类,用JAXM实现 </p> * <p>Description: </p> * <p>Copyright: Copyright (c) 2007</p> * <p>Company: </p> * @author liwei 080912 * @version 1.0 */ public class InterfaceServiceServlet extends JAXMServlet implements ReqRespListener { public static final String ATTACH_SEPERATOR = ","; ServletConfig config; public void init(ServletConfig servletconfig) throws ServletException { super.init(servletconfig); config = servletconfig; }
* 接口入口,所有JAXM实现webservice的接口 * @param message SOAPMessage * @return SOAPMessage */ public SOAPMessage onMessage(SOAPMessage message) { Log log = LogFactory.getLog(getClass().getName()); /*获取接口信息*/ SOAPMessage resultSOAP = null; ReqDistribute reqdis = new ReqDistribute(); try { resultSOAP = reqdis.doRequest(message, config); } catch (Exception ex) { ex.printStackTrace(); log.error(ex.getMessage(), ex); }
return resultSOAP; } }
/** * 按照SOAP报文中要访问的不同方法,对数据进行分发 * @param soapMsg String * @throws CryptoException * @throws IOException * @return SOAPMessage */ public SOAPMessage doRequest(SOAPMessage message, ServletConfig servletconfig) throws CryptoException, IOException { Communal comm = new Communal(); Log log = LogFactory.getLog(getClass().getName()); ByteArrayOutputStream outStream = new ByteArrayOutputStream(); SOAPMessage resultSOAP = null; int result = -2;
try {
//获取附件 int attachmentCount = message.countAttachments(); log.info("获取附件--" + attachmentCount); Iterator it = message.getAttachments(); String filePath=”E://test”; //删除所有的附件 message.removeAllAttachments(); message.saveChanges(); message.writeTo(outStream); byte[] soapData = outStream.toByteArray(); outStream.close(); String soapMsg = new String(soapData, "UTF-8"); log.info(soapMsg);
/*有附件 处理附件吧附件存储起来*/ if (attachmentCount > 0) { log.info("deal .."); result = comm.dealAttachments(it, filePath); } } catch (Exception ex) { ex.printStackTrace(); log.error(ex.getMessage(), ex); }
String soapMsg = comm.sopeToString(message); InterfaceService interfaceS = new InterfaceService();
log.info("---begin----doRequest---"); String resultMsg = ""; if (soapMsg == null || soapMsg.length() < 10) { return null; } if (soapMsg.indexOf("SynSecurityDomain") != -1) { //安全域信息同步 resultMsg = new SynSDOper().SynSDserver(requestXml);//这里需要导入该类 //具体逻辑处理 } // else if (soapMsg.indexOf("LogoutServer") != -1) { //退出登录 // resultMsg = interfaceS.LogoutServer(soapMsg); // } // else if(soapMsg.indexOf("DataConvertRequest") != -1){ //数据转换模块到数据传输模块的请求数据 // resultMsg = interfaceS.DataConvertRequest(soapMsg); // }
//使用正则表达式 去掉> <中间的空格和所有的回车 resultMsg = comm.replaceUseReg(resultMsg, ">//s*<", "><"); resultMsg = comm.replaceUseReg(resultMsg, "//n", "");
SOAPMessage resultSoap = comm.strToSOAPMessage(resultMsg); log.info("----resultSoap-----" + resultSoap); log.info("--servletconfig--" + servletconfig.getServletName()); return resultSoap; }
/** * 处理文件,根据路径和文件名保存附件 处理附件,把附件保存某个路径下 * */ private boolean dealAttachments (Iterator it, String filePath) { Log log = LogFactory.getLog("处理附件"); // String fileNames[] = fileName.split(","); String tempName = "";
int i = 0; while (it.hasNext()) { try { int num = i++; File filedir = new File(filePath);
if (!filedir.exists()) { filedir.mkdirs(); filedir = null; }
AttachmentPart attachPart = (AttachmentPart) it.next(); tempName = attachPart.getContentId(); //如果有多个附件,附件的content_id 为文件名字 // if (fileNames.length > 1) { // fileNames[num] = tempName; // } InputStream inStream = attachPart.getDataHandler().getInputStream(); FileOutputStream fileOutStream = new FileOutputStream(filePath + tempName);
byte[] data = new byte[1024]; int length = 0; while ( (length = inStream.read(data)) != -1) { fileOutStream.write(data, 0, length); } fileOutStream.flush(); fileOutStream.close(); inStream.close(); } catch (SOAPException ex) { ex.printStackTrace(); return false; } catch (Exception ex) { log.error(ex.getMessage()); return false; } }
return true; } |
服务端共有三个JAXM Servlet,它们分别提供三种不同的查询服务。
由于使用了点对点的消息模型,故服务端需要实现javax.xml.messaging. ReqRespListener接口,并且需要继承javax.xml.messaging.JAXMServlet类。javax.xml.messaging.JAXMServlet是一个Servlet,它为开发消息服务的Servlet提供了一个框架。需要指出的是,javax.xml.messaging. ReqRespListener接口定义了一个
其中servlet中的onMessage方法就像servlet中定义的一个doGet() 或doPost()方法,当你请求该servlet时,系统会自动调用该方法,所以在的定义servlet时需要继承JAXMServlet并实现ReqRespListener,
安全域同步类:
package com.watchdata.raadtinterface.center;
import org.apache.commons.logging.*;
import java.io.*; import javax.xml.soap.*; import com.watchdata.raadtinterface.common.syn.*; import com.watchdata.raadtinterface.common.*;
/** * <p>Description: 安全域同步处理类 </p> * @ * @version 1.0 */
public class SynSDOper { public SynSDOper() { }
/** * */ Log log = LogFactory.getLog(getClass().getName()); public String SynSDserver(String requestXml) {
//对传来的xml信息解析,并封装为SynSecurityDomainRequest对象 SynSecurityDomainRequest requestObj = (SynSecurityDomainRequest) SOAPRequest.getMoRequest("SynSecurityDomain", requestXml, SOAPRequest.raaNameSpace, new SynSecurityDomainRequest());
// InterfaceConfig config = InterfaceConfig.getInstance(); StatusResponse response = new StatusResponse(); //到该处已经传递XML信息到此,通过getMoRequest即可获取同步过来的安全域信息BEAN //获取接口参数值 String SeqNum = requestObj.getSeqNum(); String SessionID = requestObj.getSessionID(); String SynType = requestObj.getSynType(); SecurityDomainBean sdbean = requestObj.getSecurityDomain();
try { //获取数据入库 System.out.println("SeqNum=" + SeqNum); System.out.println("sdbean==" + sdbean.getAppAID());
if (true) { //如果处理成功 response.setStatusCode("01"); response.setStatusDescription("success"); } } catch (Exception ex) { log.error("SysSDserver error", ex); ex.printStackTrace(); } //将封装为StatusResponse对象的信息以xml形式返回给RAADataConvert return SOAPRequest.getRespStrXml(Constants.RAA_PREFIX, "SynSecurityDomainResponse", response); }
/** *处理安全域同步响应报文 * @param soapmessage SOAPMessage server 返回的SOAPMessage * @return SynSecurityDomainResponse 返回一个安全域同步响应的对象 */ public SynSecurityDomainResponse SysSDResponse(SOAPMessage soapmessage) { SynSecurityDomainResponse synsdRes = new SynSecurityDomainResponse(); try { /** * 一下处理server返回的报文. */ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); soapmessage.writeTo(outStream); byte[] soapData = outStream.toByteArray(); outStream.close(); String soapMsg = new String(soapData, "UTF-8"); SynSecurityDomainResponse responseObj = (SynSecurityDomainResponse) SOAPRequest.getMoRequest("SynSecurityDomainResponse", soapMsg, SOAPRequest.raaNameSpace, new SynSecurityDomainResponse());
/** * 取得server返回的操作状态返回给sim卡应用管理平台 */ synsdRes = responseObj;
System.out.println(responseObj.getStatus().getStatusCode()); System.out.println("----sopamessage----=" + soapMsg);
} catch (Exception e) { log.error("get synsdResponse error", e); e.printStackTrace();
} return synsdRes;
}
} |
如果使用需要在web.xml中进行配置,具体配置如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>SOAPMonitorService</servlet-name> <display-name>SOAP Monitor Service</display-name> <servlet-class>org.apache.axis.monitor.SOAPMonitorService</servlet-class> <init-param> <param-name>SOAPMonitorPort</param-name> <param-value>5001</param-value> </init-param> <load-on-startup>100</load-on-startup> </servlet> <servlet> <servlet-name>AxisServlet</servlet-name> <display-name>Apache-Axis Servlet</display-name> <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class> </servlet> <servlet> <servlet-name>interfaceservice1</servlet-name> <servlet-class>com.watchdata.raadtinterface.center.InterfaceServiceServlet</servlet-class> </servlet> <servlet> <servlet-name>MSSPService</servlet-name> <servlet-class>com.watchdata.raadtinterface.center.DataSignatureServlet</servlet-class> </servlet> <servlet> <servlet-name>SimulatorInterface</servlet-name> <servlet-class>com.watchdata.raadtinterface.simulator.SimulatorServerServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SOAPMonitorService</servlet-name> <url-pattern>/SOAPMonitor</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/servlet/AxisServlet/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>*.jws</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>interfaceservice1</servlet-name> <url-pattern>/RAADTSOAP/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>MSSPService</servlet-name> <url-pattern>/MSSPSOAP/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>SimulatorInterface</servlet-name> <url-pattern>/RAADTTEST/*</url-pattern> </servlet-mapping>
</web-app> |
以上完成后部署到服务器,然后通过下面的测试类进行测试.
///测试的主方法 public static void main(String[] args) throws Exception { String simulatorXmlFile = null; //要模拟的XML请求报文 String method = null; //要调用的方法 String[] attachFileArr = null; //要发送的附件 String url = null; int length = args.length; method = "test"; simulatorXmlFile = "E://xml//SynSecurityDomain.xml"; attachFileArr = new String[] { "E://xml//01234567891100000000000101.cap"};
// if(length == 0){//方便开发时测试使用 // simulatorXmlFile = "E://xml//SynSecurityDomain.xml"; // method = "AddOrUpdateMsisdnSegment"; // attachFileArr = new String[]{"D://Simular//SEG_INC_20080804_0001.avl"}; // }else if (length >= 2) {//集成测试时使用 // simulatorXmlFile = args[0]; // method = args[1]; // if(length > 2){//有附件 // attachFileArr = new String[length-2]; // for(int i=0;i<length-2;i++){ // attachFileArr[i] = args[i+2]; // } // } // }else{ // System.out.println("启动参数错误,个数不够,请检查!"); // return; // } // url = InterfaceConfig.getInstance().getSimulatorPortalUrl(); url = "http://127.0.0.1:80/RAADTInterface/RAADTSOAP/i";
SimulatorClientTest sClient = new SimulatorClientTest(); if (method.equals("test")) { String xmlString = sClient.getStrXml(simulatorXmlFile); //使用正则表达式 去掉> <中间的空格和所有的回车 xmlString = sClient.replaceUseReg(xmlString, ">//s*<", "><"); xmlString = sClient.replaceUseReg(xmlString, "//n", ""); System.out.println(xmlString); SOAPMessage resultSoap = sClient.strToSOAPMessage(xmlString); //定向PUSH查询的返回报文可能需要添加附件 resultSoap = sClient.addAttachments(resultSoap, attachFileArr); SOAPMessage message= sClient.send(resultSoap, url); System.out.println("soapMessage=="+message); ByteArrayOutputStream outStream = new ByteArrayOutputStream(); //获取附件 int attachmentCount = message.countAttachments(); Iterator it = message.getAttachments();
//删除所有的附件 message.removeAllAttachments(); message.saveChanges(); message.writeTo(outStream); byte[] soapData = outStream.toByteArray(); String soapMsg = new String(soapData, "UTF-8");
SynSecurityDomainResponse responseObj = (SynSecurityDomainResponse) SOAPRequest.getMoRequest("SynSecurityDomainResponse", soapMsg, SOAPRequest.raaNameSpace, new SynSecurityDomainResponse());
outStream.close();
// SOAPMessage message= sClient.send(method,comm.sopeToString(resultSoap),url); // System.out.println("==message=="+comm.sopeToString(message)); } else { SOAPMessage message = sClient.send(method, sClient.getStrXml(simulatorXmlFile), url);
/
ByteArrayOutputStream outStream = new ByteArrayOutputStream(); SOAPMessage resultSOAP = null; int result = -2;
//获取附件 int attachmentCount = message.countAttachments(); Iterator it = message.getAttachments(); //删除所有的附件 message.removeAllAttachments(); message.saveChanges(); message.writeTo(outStream); byte[] soapData = outStream.toByteArray(); outStream.close();
//modified by wzguo 081006 修改SOAP协议中出现乱码的问题,可能要根据实际情况选择使用那一个 // soapMsg = new String(soapData,"GBK"); String soapMsg = new String(soapData, "UTF-8");
SynSecurityDomainResponse responseObj = (SynSecurityDomainResponse) SOAPRequest.getMoRequest("SynSecurityDomainResponse", soapMsg, SOAPRequest.raaNameSpace, new SynSecurityDomainResponse());
System.out.println(responseObj.getStatus().getStatusCode()); System.out.println("----sopamessage----=" + soapMsg); } }
//把符合SOAP报文的字符串转换成SOAPMessage public static SOAPMessage strToSOAPMessage(String soapMsg) { if (soapMsg == null || soapMsg.trim().length() < 10) { return null; } try { MessageFactory messageFac = MessageFactory.newInstance(); SOAPMessage soapMessage = messageFac.createMessage(); SOAPPart soapPart = soapMessage.getSOAPPart();
byte[] data = soapMsg.getBytes("UTF-8"); ByteArrayInputStream stream = new ByteArrayInputStream(data); StreamSource source = new StreamSource(stream);
soapPart.setContent(source); soapMessage.saveChanges(); stream.close();
return soapMessage; } catch (SOAPException ex) { System.out.println("把字符串转化成SOAPMessage出错"); } catch (IOException ex) { System.out.println("把字符串转化成SOAPMessage出错"); } return null; } 添加附件的方法 public SOAPMessage addAttachments(SOAPMessage message, String[] attachFileArr) { //添加SOAP附件 if (attachFileArr != null) { for (int i = 0; i < attachFileArr.length; i++) { String fileName = attachFileArr[i]; File file = new File(fileName); if (!file.exists()) { System.out.println("指定的附件不存在!"); return null; }
DataHandler dataHandler = new DataHandler(new FileDataSource(fileName)); AttachmentPart attach = message.createAttachmentPart(dataHandler); fileName = fileName.substring(fileName.lastIndexOf("//") + 1); attach.setContentId(fileName); message.addAttachmentPart(attach);
} } //更新SOAP消息 try { message.saveChanges(); } catch (SOAPException ex) { ex.printStackTrace(); } return message; }
/发送方法 // 访问WebService(会根据SOAPMessage中的方法自动去访问) public SOAPMessage send(SOAPMessage message, String url) throws SOAPException, IOException {
//创建SOAP连接 SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance(); SOAPConnection sc = scf.createConnection();
//发送SOAP消息到目的地,并返回一个消息 URLEndpoint urlEndpoint = new URLEndpoint(url); SOAPMessage response = sc.call(message, urlEndpoint); if (response != null) { //输出SOAP消息到控制台 System.out.println("Receive SOAP message from localhost:"); // response.writeTo(System.out); log.info("return response;---" + response); } else { System.err.println("No response received from partner!"); } sc.close(); return response; } |
备注:
开发web service 用到得相关jar包:
activation.jar
mail.jar
smtp.jar
commons-betwixt-0.6.jar
xml-apis.jar
resolver.jar