webService接口调用各种方法总结

转自:https://thewangzl.iteye.com/blog/2326075

方法一:使用JaxWsDynamicClientFactory调用WebService
public static Object call(String wsdl,String method,String requestStr){  
    JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();  
    Client client = factory.createClient(wsdl);  
    HTTPConduit conduit = (HTTPConduit) client.getConduit();  
    HTTPClientPolicy policy = new HTTPClientPolicy();  
    long timeout = 10 * 60 * 1000;//  
    policy.setConnectionTimeout(timeout);  
    policy.setReceiveTimeout(timeout);  
    conduit.setClient(policy);  
    //动态invoke方法  
    Object[] os =client.invoke(method,requestStr);  
    return os[0];  
    }  
方法二:使用JaxWsProxyFactoryBean调用WebService

原理:使用JaxWsProxyFactoryBean类生成本地的代理类。
首先创建接口,然后通过JaxWsProxyFactoryBean调用。

@WebService  
public interface IDataService {  
  
    @WebMethod  
    @WebResult  
    String getData(@WebParam String requestData);  
}  
  
public static String call(String wsdl, String requestStr) {  
    JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();  
    factory.setServiceClass(IDataService.class);  
    factory.setAddress(wsdl);  
    IDataService service = (IDataService) factory.create();  
    // 设置超时时间  
    org.apache.cxf.endpoint.Client proxy = ClientProxy.getClient(service);  
    HTTPConduit conduit = (HTTPConduit) proxy.getConduit();  
    HTTPClientPolicy policy = new HTTPClientPolicy();  
    long timeout = 10 * 60 * 1000;//  
    policy.setConnectionTimeout(timeout);  
    policy.setReceiveTimeout(timeout);  
    conduit.setClient(policy);  
    // 发出请求  
    return service.getData(requestStr);  
}  
方法三:使用wsimport命令构建WebService客户端

首先使用wsimport命令构建客户端,然后用下面的方法调用。

public static String call(String requestData) {  
    // 构建的客户端代码  
    IDataService_Service factory = new IDataService_Service();  
    IDataService service = factory.getDataSharedWebService();  
    long timeout = 30 * 60 * 1000;// 30分钟  
    // 设置超时时间  
    // 当前起作用的配置  
    ((BindingProvider) service).getRequestContext().put("javax.xml.ws.client.connectionTimeout", timeout);  
    ((BindingProvider) service).getRequestContext().put("javax.xml.ws.client.receiveTimeout", timeout);  
    // 网上搜到的其他设置超时的方法,当前项目没有起作用  
    ((BindingProvider) service).getRequestContext().put("com.sun.xml.ws.connect.timeout", timeout);  
    ((BindingProvider) service).getRequestContext().put("com.sun.xml.ws.request.timeout", timeout);  
    ((BindingProvider) service).getRequestContext().put("com.sun.xml.internal.ws.connect.timeout", timeout);  
    ((BindingProvider) service).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", timeout);  
    ((BindingProvider) service).getRequestContext().put("sun.net.client.defaultConnectTimeout", timeout);  
    ((BindingProvider) service).getRequestContext().put("sun.net.client.defaultReadTimeout", timeout);  
    try {  
        // 调用WebService  
        return service.getData(requestData);  
    } catch (Exception e) {  
        log.error(e.getMessage());  
    }  
    return null;  
}  

也可以用cxf的wsdl2java命令构建客户端,调用方式一样,但是如何设置超时时间没有试。

方法四:使用HttpClient调用WebService

使用commons-httpclient-3.1,依赖jar包(commons-codec.jar、commons-logging.jar)。

public String call(String wsdl, String requestData) {  
    try {  
        // requestData可以直接用soapui中请求的数据,注意<![CDATA[]]>的使用  
        PostMethod postMethod = new PostMethod(wsdl);  
        byte[] b = requestData.getBytes("UTF-8");  
        InputStream in = new ByteArrayInputStream(b, 0, b.length);  
        RequestEntity re = new InputStreamRequestEntity(in,  
                "text/xml; charset=utf-8");  
        postMethod.setRequestEntity(re);  
        // 设置header SOAPAction,不设置的话,会报异常:no SOAPAction  
        // header,但是SOAPAction的好像任意值都可以  
        String soapAction = "XX";  
        postMethod.setRequestHeader("SOAPAction", soapAction);  
        HttpClient client = new HttpClient();  
        // 设置超时(不知道默认是多久,没有设置的时候,也没有报错,设置下保险些)  
        int timeout = 10 * 60 * 1000;  
        client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout);  
        client.getHttpConnectionManager().getParams().setSoTimeout(timeout);  
        //  
        int status = client.executeMethod(postMethod);  
        if (status == 200) {// 成功  
            InputStream is = postMethod.getResponseBodyAsStream();  
            /** 
             * 获取的结果可以参考用soapui调用时的返回值, 
             * 如果约定的返回值是XML,并不会像soapui一样把xml用<![CDATA[]]>包含起来,要注意解析的方法, 
             * 不知道soapui如何处理的,暂时没时间研究。 
             */  
            return getResponseXML(is);  
        } else {  
            log.error("调用Webservice出错;错误代码为:" + status);  
        }  
    } catch (Exception e) {  
        log.error(e.getMessage());  
    }  
    return null;  
}  
  
public String getResponseXML(InputStream response) throws Exception {  
    // 根据具体的返回值写的解析  
    SAXReader reader = new SAXReader();  
    Document document = reader.read(response);  
    Element root = document.getRootElement();  
    List<Element> childElements = root.elements();  
    for (Element child : childElements) {  
        List<Element> datas = child.selectNodes("getOrgInfoResponse/getOrgInfoResponse");  
        for (Element node : datas) {  
            // 返回约定的xml  
            return node.getText();  
        }  
    }  
    return null;  
}  

总结下这次遇到的问题:
1.异常:java.lang.NoSuchFieldError: QUALIFIED
jar包冲突,删除jar包(如果可以的话,不能删除就用HttpClient的方式)。由于项目中第三方工具需要XmlSchema-1.3.x.jar,而cxf-2.5作为客户端时需要用到xmlschema-core-2.0.1.jar导致前三种方式都不能用。
2.超时
由于接收数据较大,时间较长,必须设置超时时间。
3.异常:javax.xml.bind.UnmarshalException:unexpected element (uri:"", local:“getDataResponse”).Expected elements are <{http://xxx/xx}getOrgInfoResponse>
是namespace的问题,如果用JaxWsProxyFactoryBean的方式,要修改@WebResult中targetNamespace;如果用wsimport命令的方式,需要修改类GetDataResponse中属性getDataResponse的注解中namespace的值。
4.异常:no SOAPAction header
没有设置SOAPAction,设置方式:postMethod.setRequestHeader(“SOAPAction”, soapAction),soapAction的值是什么好像并不影响结果。

附加:

添加一个webserivice调用的工具类,

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.springframework.stereotype.Component;
import java.util.ResourceBundle;

@Component
public class WebServiceUtil {
	
	public static final int CXF_CLIENT_CONNECT_TIMEOUT = 20 * 1000; 
	public static final int CXF_CLIENT_RECEIVE_TIMEOUT = 20 * 1000;
	
	/**
	 * 
	 * @param clazz  接口客户端类
	 * @param url	接口地址
	 * @param timeout	超时时间
	 * @return
	 */
	public <T> T  getWebService(Class<T> clazz, String url,Integer...timeout){
		

		
		return getWebServiceByUrl(clazz,url,CXF_CLIENT_RECEIVE_TIMEOUT,CXF_CLIENT_RECEIVE_TIMEOUT);
	}

	public <T> T  getWebServiceByUrl(Class<T> clazz, String url){
		return getWebServiceByUrl(clazz,url,CXF_CLIENT_CONNECT_TIMEOUT,CXF_CLIENT_RECEIVE_TIMEOUT);
	}

	private <T> T  getWebServiceByUrl(Class<T> clazz, String url,Integer connetTimeout,Integer receiveTimeout){
		
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
		factory.setServiceClass(clazz);
		factory.setAddress(url);
		@SuppressWarnings("unchecked")
		T webService = (T) factory.create();
		
		//设置接口 连接超时和请求超时
		Client proxy = ClientProxy.getClient(webService);
		HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
		HTTPClientPolicy policy = new HTTPClientPolicy();
		policy.setConnectionTimeout(connetTimeout);
		policy.setReceiveTimeout(receiveTimeout);
		conduit.setClient(policy);
		return webService;
	}
}

使用方式如下:
首先生成客户端接口:

//注入WebServiceUtil
//XXXX.class代表生成的接口类
// webServiceUrl 接口地址
// getWebService() 后可以点出可用的接口方法.
webServiceUtil.getWebService(XXXX.class, webServiceUrl).方法
要使用C#调用Web服务接口,可以按照以下步骤进行操作: 1. 引用WebService:首先,需要引用WebService的命名空间,例如using System.Web.Services;。 2. 创建代理类:使用Visual Studio或者通过命令行工具生成代理类,通过生成的代理类可以直接调用Web服务中的方法。可以使用命令行工具wsdl.exe来生成代理类,命令示例如下:wsdl /language:c# /out:生成的代理类路径 /url:WebService的URL或者WSDL文件路径。 3. 创建WebService对象:在代码中创建WebService对象,并设置其属性,例如WebClient对象的Credentials属性可以设置身份验证信息。 4. 调用Web服务方法:通过创建的代理类对象,调用Web服务中的方法。可以将方法的输入参数传递给Web服务方法,并接收返回值。 5. 解析返回结果:根据Web服务方法的返回类型,解析返回结果,可以使用XmlReader或者XmlDocument来解析返回的XML数据,也可以使用DataContractSerializer或者XmlSerializer进行反序列化。 6. 处理异常:在调用Web服务方法时,可能会抛出异常,需要进行异常处理。可以使用try-catch语句捕获异常,并根据具体情况进行处理。 总结: 要使用C#调用Web服务接口,首先引用WebService的命名空间,然后生成代理类,创建WebService对象并调用方法,最后解析返回结果和处理异常。这样就可以实现C#对Web服务接口调用了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C#动态webservice调用接口](https://download.csdn.net/download/weixin_38657139/13786952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [c# 三种方法调用WebService接口](https://download.csdn.net/download/weixin_38567956/13708848)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C#调用webservice接口的最新方法教程](https://download.csdn.net/download/weixin_38556189/13999366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值