发送Soap消息并获取响应

来源:互联网 发布:分镜头软件 安卓 编辑:程序博客网 时间:2024/06/15 02:12

SOAP

 

如下:

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.HttpURLConnection;import java.net.URL;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 该类可以将一个soap消息发送至服务端,并获取响应的soap消息 *  */public class SoapUtil {public static String invokeSrv(String endpoint,String action, String soapXml) throws IOException{StringBuilder sb = new StringBuilder();String method = "POST";String contentType = "text/xml;charset=UTF-8";URL url = new URL(endpoint);HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();// POST请求urlConn.setRequestMethod(method);// 设置要发送消息urlConn.setDoOutput(true);// 设置要读取响应消息urlConn.setDoInput(true);// POST不能使用cacheurlConn.setUseCaches(false);urlConn.setInstanceFollowRedirects(true);urlConn.setRequestProperty("SOAPAction", action);urlConn.setRequestProperty("Content-Type", contentType);urlConn.setRequestProperty("@test_flag", "Y");urlConn.connect();// 向输出流写出数据,这些数据将存到内存缓冲区中 PrintWriter pw = new PrintWriter(urlConn.getOutputStream());pw.write(soapXml);// 刷新对象输出流,将任何字节都写入潜在的流中pw.flush();// 关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中,   // 在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器  pw.close();// 接收返回消息// 解析返回值编码格式String charset = "UTF-8";String ct = urlConn.getContentType();Pattern p = Pattern.compile("charset=.*;?");Matcher m = p.matcher(ct);if(m.find()){charset = m.group();// 去除charset=和;,如果有的话if(charset.endsWith(";")){charset = charset.substring(charset.indexOf("=") + 1, charset.indexOf(";"));}else{charset = charset.substring(charset.indexOf("=") + 1);}// charset = "\"UTF-8\"";// 去除引号 ,如果有的话if(charset.contains("\"")){charset = charset.substring(1, charset.length() - 1);}charset = charset.trim();}// 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。   // <===注意,实际发送请求的代码段就在这里InputStream inStream = urlConn.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(inStream,charset));String line;while((line = br.readLine()) != null){sb.append(line);}br.close();urlConn.disconnect();return sb.toString();}public static void main(String[] args) {String endpoint = "http://localhost:8088/ESB_YS_YS_InquiryEventsReferralsInfoSrv/ESBYSYSInquiryEventsReferralsInfoSrvImpl";StringBuffer sb = new StringBuffer();InputStream in = null;BufferedReader bf = null;try {in = SoapUtil.class.getClassLoader().getResourceAsStream("soapRequest.xml");bf = new BufferedReader(new InputStreamReader(in));String line = "";while( (line = bf.readLine()) != null){sb.append(line).append("\n");}//输入请求System.out.println(sb.toString());System.out.println("------------------------------------------");//返回请求System.out.println(invokeSrv(endpoint,"process",sb.toString()));} catch (IOException e) {e.printStackTrace();}}}

总结:
a:) HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。

    无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
       
b:) 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,
    对connection对象的一切配置(那一堆set函数)都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。
    这些顺序实际上是由http请求的格式决定的。
    如果inputStream读操作在outputStream的写操作之前,会抛出例外:
    java.net.ProtocolException: Cannot write output after reading input.......
       
c:) http请求实际上由两部分组成,
    一个是http头,所有关于此次http请求的配置都在http头里面定义,一个是正文content。
    connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,
    就必须把所有的配置准备好。
       
d:) 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)都是没有意义的了,执行这些操作会导致异常的发生。

 

XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:esb="http://ucloud.unicom.com/ESB_YS_YS_InquiryEventsReferralsInfoSrv" xmlns:msg="http://ucloud.unicom.com/MsgHeader">   <soapenv:Header/>   <soapenv:Body>      <esb:ESB_YS_YS_InquiryEventsReferralsInfoSrvRequest>         <esb:MsgHeader>            <msg:SOURCE_APP_ID>1</msg:SOURCE_APP_ID>            <msg:SOURCE_APP_NAME>1</msg:SOURCE_APP_NAME>            <msg:SOURCE_MOD_ID>1</msg:SOURCE_MOD_ID>            <msg:SOURCE_MOD_NAME>1</msg:SOURCE_MOD_NAME>            <msg:TARGET_MOD_ID>1</msg:TARGET_MOD_ID>            <msg:TARGET_MOD_NAME>1</msg:TARGET_MOD_NAME>            <msg:TOKEN>1</msg:TOKEN>            <msg:USERID>1</msg:USERID>            <msg:USERNAME>1</msg:USERNAME>            <msg:SUBMITDATE>2012-03-12T12:12:12</msg:SUBMITDATE>            <msg:PAGE_SIZE>1</msg:PAGE_SIZE>            <msg:CURRENT_PAGE>1</msg:CURRENT_PAGE>            <msg:TOTAL_RECORD>1</msg:TOTAL_RECORD>            <msg:PROVINCE_CODE>1</msg:PROVINCE_CODE>            <msg:ENVIRONMENT_NAME>1</msg:ENVIRONMENT_NAME>         </esb:MsgHeader>         <esb:TIME_FROM>20121212121212</esb:TIME_FROM>         <esb:TIME_TO>20121212121212</esb:TIME_TO>         <esb:USER_CODE>1</esb:USER_CODE>         <esb:ATTRIBUTE1>1</esb:ATTRIBUTE1>         <esb:ATTRIBUTE2>1</esb:ATTRIBUTE2>         <esb:ATTRIBUTE3>1</esb:ATTRIBUTE3>         <esb:ATTRIBUTE4>1</esb:ATTRIBUTE4>      </esb:ESB_YS_YS_InquiryEventsReferralsInfoSrvRequest>   </soapenv:Body></soapenv:Envelope>

 

获取错误消息可以通过异常流urlConn.getErrorStream()。

 

详细参考:http://www.cnblogs.com/guodongli/archive/2011/04/05/2005930.html

 

 

原创粉丝点击