发送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