1. 程式人生 > >Java動態呼叫Webservice,不生成客戶端,基於soapUI

Java動態呼叫Webservice,不生成客戶端,基於soapUI

近日專案一需求,需要實現動態解析Webservice滿足Webservice動態呼叫。參考過CXF、AXIS等非常成熟的相關框架技術,但在使用過程中發現,簡單物件(入參、出參)的時候很好用,當是複雜物件的時候很棘手!當然CXF、AXIS全然滿足,也支援物件,動態引數等,但構造過程是一個很複雜的過程。最後以XML方式去做,參考SOAP-UI,最終寫出了以下工具。

Java基於soapUI解析Webservice,以XML方式呼叫

package com.sonic.platform.soap;
/***
 * 
 * 
 * 
 * 
 * 
 */
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.xmlbeans.XmlException;

import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlImporter;
import com.eviware.soapui.model.iface.Operation;
import com.eviware.soapui.support.SoapUIException;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

import net.sf.json.xml.XMLSerializer;
/**
 * 
 * @author FishingGo
 *
 */
public class ConvertWSDL{
	private final static String password_key="soapui.loader.password";
	private final static String username_key="soapui.loader.username";
	/**
	 * 
	 * @return
	 * @throws XmlException
	 * @throws IOException
	 * @throws SoapUIException
	 */
	private static WsdlProject init() throws XmlException, IOException, SoapUIException{
			//new 會有一個守護程序???
		WsdlProject WSDL_PROJECT=new WsdlProject();
		return WSDL_PROJECT;
	}
	
	/**
	 * auth
	 * @param userName
	 * @param password
	 * @param auth
	 */
	private static void initAuth(String userName,String password,boolean auth){
		if(auth){
			Preconditions.checkArgument(StringUtils.isNotBlank(userName), "username can not be empty or null");
			Preconditions.checkArgument(StringUtils.isNotBlank(password), "password can not be empty or null");
			System.setProperty(password_key, password);
			System.setProperty(username_key, userName);
		}
	}
	
	/**
	 * 解析WSDL
	 * @param address
	 * @param method
	 * @param userName
	 * @param password
	 * @param auth
	 * @return
	 * @throws ConvertWSDLException
	 */
	private final static OperationMethodInfo operationMethodInfo(String address,String method,String userName,String password,boolean auth) throws ConvertWSDLException{
		Preconditions.checkArgument(StringUtils.isNotBlank(method), "method can not be empty or null");
		List<OperationMethodInfo> infos=convertOperation(address, userName, password, auth);
		for (OperationMethodInfo operationMethodInfo : infos) {
			if(method.equals(operationMethodInfo.getOperationName())) return operationMethodInfo;
		}
		return null;
	}
	
	public final static OperationMethodInfo operationMethodInfo(String address,String method) throws ConvertWSDLException{
		return operationMethodInfo(address, method,null,null,false);
	}
	
	public final static OperationMethodInfo operationMethodInfo(String address,String method,String userName,String password) throws ConvertWSDLException{
		return operationMethodInfo(address, method,userName,password,true);
	}
	
	
	/**
	 * 解析WSDL 返回SOAP協議引數XML
	 * @param address
	 * @param method
	 * @return
	 * @throws ConvertWSDLException
	 */
	public final static String soapRequestXML(String address,String method) throws ConvertWSDLException{
		OperationMethodInfo operationMethodInfo=operationMethodInfo(address, method);
		return null==operationMethodInfo?null:operationMethodInfo.getRequestXml();
	}
	
	public final static String soapRequestXML(String address,String method,String userName,String password) throws ConvertWSDLException{
		OperationMethodInfo operationMethodInfo=operationMethodInfo(address, method,userName,password);
		return null==operationMethodInfo?null:operationMethodInfo.getRequestXml();
	}
	
	/**
	 * convert WSDL Operation
	 * @param address
	 * @param charset
	 * @param userName
	 * @param password
	 * @param auth
	 * @return
	 * @throws ConvertWSDLException
	 */
	private static List<OperationMethodInfo> convertOperation(String address,String userName,String password,boolean auth) throws ConvertWSDLException{
		initAuth(userName, password, auth);
		WsdlInterface wsdlInterface=getWsdlInterface(address);
		return convertOperation(wsdlInterface);	
	}
	
	public final static List<OperationMethodInfo> convertOperation(String address) throws ConvertWSDLException{
		return convertOperation(address,null,null,false);	
	}
	
	public final static List<OperationMethodInfo> convertOperation(String address,String userName,String password) throws ConvertWSDLException{
		return convertOperation(address,userName, password, true);	
	}
	
	/**
	 * convert WSDL Operation
	 * @param wsdlInterface
	 * @return
	 */
	private static List<OperationMethodInfo> convertOperation(WsdlInterface wsdlInterface) {
		List<Operation> operationList = wsdlInterface.getOperationList();
		return new ArrayList<>(Lists.transform(operationList, action->{
			return new OperationMethodInfo((WsdlOperation) action);
		}));
	}
	
/**
 * getWsdlInterface
 * @param address
 * @return
 * @throws ConvertWSDLException
 */
	private static WsdlInterface getWsdlInterface(String address) throws ConvertWSDLException {
		Preconditions.checkArgument(StringUtils.isNotBlank(address), "address can not be empty or null");
		try {
			WsdlInterface[] wsdls = WsdlImporter.importWsdl(init(), address.endsWith("wsdl")?address:address+"?wsdl");
			return wsdls[0];
		} catch (XmlException e) {
			throw new ConvertWSDLException(e);
		} catch (IOException e) {
			throw new ConvertWSDLException(e);
		} catch (SoapUIException e) {
			throw new ConvertWSDLException(e);
		} catch (Exception e) {
			throw new ConvertWSDLException(e);
		}
	}
	
	final static String charset="UTF-8";
	
	private static final String xmlToJson(String responseXml){
		if (responseXml != null && !"".equals(responseXml)) {
			int beginIndex = responseXml.indexOf("<return>");
			int endIndex = responseXml.indexOf("</return>");
			responseXml = responseXml.substring(beginIndex, endIndex+9);
		}
		return StringUtils.isNotBlank(responseXml)?new XMLSerializer().read(responseXml).toString():null;
	}
	
	/**
	 * 
	 * @param address
	 * @param charset
	 * @param requestXml
	 * @throws MalformedURLException
	 * @throws IOException
	 */
	@SuppressWarnings("unused")
	@Deprecated
	private static String doPostSoap_(String address,String charset,String requestXml) throws MalformedURLException, IOException{
		HttpURLConnection httpURLConnection=null;
		try {
			httpURLConnection=(HttpURLConnection) new URL(address).openConnection();
			httpURLConnection.setRequestMethod("POST"); 
			httpURLConnection.setDoOutput(true); 
			httpURLConnection.setDoInput(true); 
			httpURLConnection.setRequestProperty("Content-Type","text/xml;charset="+charset); 
			OutputStream outputStream=httpURLConnection.getOutputStream();
			outputStream.write(requestXml.getBytes(charset));
			int responseCode = httpURLConnection.getResponseCode();
			StringBuffer stringBuffer=new StringBuffer();
			if(HttpStatus.SC_OK==responseCode){
				InputStream inputStream=httpURLConnection.getInputStream();
				byte[] buffer = new byte[1024]; 
				int len = 0; 
				while ((len = inputStream.read(buffer)) > 0) { 
			     stringBuffer.append(new String(buffer, 0, len));
				}
			}
			return xmlToJson(stringBuffer.toString());
		} finally {
			if(null!=httpURLConnection) httpURLConnection.disconnect();
		} 
	}
	
	public static String doPostSoap(String address,String requestXml) throws ParseException, IOException{
		return doPostSoap(address,requestXml,charset);
	}
	
	public static String doPostSoap(String address,String requestXml,String charset) throws ParseException, IOException{
		return doPostSoap(address,charset, requestXml,null,null,null,false);
	}
	
	public static String doPostSoap(String address,String requestXml,String charset,String username,String password) throws ParseException, IOException{
		return doPostSoap(address,charset, requestXml,null,username,password,true);
	}
	
	public static String doPostSoap(String address,String requestXml,String username,String password) throws ParseException, IOException{
		return doPostSoap(address,requestXml,charset,username,password);
	}
	/**
	 * 
	 * @param url
	 * @param charset
	 * @param requestXml
	 * @param methodName
	 * @param username
	 * @param password
	 * @param auth
	 * @return
	 * @throws ParseException
	 * @throws IOException
	 */
	private static String doPostSoap(String url, String charset, String requestXml, String methodName, String username,
			String password, boolean auth) throws ParseException, IOException {
		CloseableHttpClient httpClient = null;
		try {
			HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
			httpClient = httpClientBuilder.build();
			HttpPost httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60 * 1000)
					.setConnectTimeout(60 * 1000).build();
			httpPost.setConfig(requestConfig);
			httpPost.setHeader("Content-Type", "text/xml;charset=" + charset);
			//httpPost.setHeader("SOAPAction", methodName);
			if (auth)
				httpPost.setHeader("Authorization", authHeader(username, password, charset));
			StringEntity data = new StringEntity(requestXml, Charset.forName(charset));
			httpPost.setEntity(data);
			CloseableHttpResponse response = httpClient.execute(httpPost);
			if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
				HttpEntity httpEntity = response.getEntity();
				if (httpEntity != null) {
					return xmlToJson(EntityUtils.toString(httpEntity, charset));
				}
			}
		} finally {
			// 釋放資源
			httpClient.close();
		}
		return null;
	}
	 
	 
	 private static String authHeader(String userName, String password, String charset) {
			String auth = userName + ":" + password;
			byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName(charset)));
			String authHeader = "Basic " + new String(encodedAuth);
			return authHeader;
		}
}
			//new 會有一個守護程序???
		        WsdlProject WSDL_PROJECT=new WsdlProject();

疑惑點,拜讀soapUI原始碼研究中!

歡迎‘大牛’不吝賜教指正!