分享

调用WebService 设置超时

 一本正经地胡闹 2020-07-17
    最近项目上要调用其他系统的WebService(Axis搭建),由于接收数据较大耗时4分钟左右,所以要设置超时时间,而且系统中已有jar包的原因,导致许多方法都不能用,最终用HttpClient。
方法一:使用JaxWsDynamicClientFactory调用WebService

Java代码  收藏代码

  1. public static Object call(String wsdl,String method,String requestStr){  

  2.     JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();  

  3.     Client client = factory.createClient(wsdl);  

  4.     HTTPConduit conduit = (HTTPConduit) client.getConduit();  

  5.     HTTPClientPolicy policy = new HTTPClientPolicy();  

  6.     long timeout = 10 * 60 * 1000;//  

  7.     policy.setConnectionTimeout(timeout);  

  8.     policy.setReceiveTimeout(timeout);  

  9.     conduit.setClient(policy);  

  10.     //动态invoke方法  

  11.     Object[] os =client.invoke(method,requestStr);  

  12.     return os[0];  

  13.     }  

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

Java代码  收藏代码

  1. @WebService  

  2. public interface IDataService {  

  3.     @WebMethod  

  4.     @WebResult  

  5.     String getData(@WebParam String requestData);  

  6. }  

  7. public static String call(String wsdl, String requestStr) {  

  8.     JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();  

  9.     factory.setServiceClass(IDataService.class);  

  10.     factory.setAddress(wsdl);  

  11.     IDataService service = (IDataService) factory.create();  

  12.     // 设置超时时间  

  13.     org.apache.cxf.endpoint.Client proxy = ClientProxy.getClient(service);  

  14.     HTTPConduit conduit = (HTTPConduit) proxy.getConduit();  

  15.     HTTPClientPolicy policy = new HTTPClientPolicy();  

  16.     long timeout = 10 * 60 * 1000;//  

  17.     policy.setConnectionTimeout(timeout);  

  18.     policy.setReceiveTimeout(timeout);  

  19.     conduit.setClient(policy);  

  20.     // 发出请求  

  21.     return service.getData(requestStr);  

  22. }  

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

Java代码  收藏代码

  1. public static String call(String requestData) {  

  2.     // 构建的客户端代码  

  3.     IDataService_Service factory = new IDataService_Service();  

  4.     IDataService service = factory.getDataSharedWebService();  

  5.     long timeout = 30 * 60 * 1000;// 30分钟  

  6.     // 设置超时时间  

  7.     // 当前起作用的配置  

  8.     ((BindingProvider) service).getRequestContext().put("javax.xml.ws.client.connectionTimeout", timeout);  

  9.     ((BindingProvider) service).getRequestContext().put("javax.xml.ws.client.receiveTimeout", timeout);  

  10.     // 网上搜到的其他设置超时的方法,当前项目没有起作用  

  11.     ((BindingProvider) service).getRequestContext().put("com.sun.xml.ws.connect.timeout", timeout);  

  12.     ((BindingProvider) service).getRequestContext().put("com.sun.xml.ws.request.timeout", timeout);  

  13.     ((BindingProvider) service).getRequestContext().put("com.sun.xml.internal.ws.connect.timeout", timeout);  

  14.     ((BindingProvider) service).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", timeout);  

  15.     ((BindingProvider) service).getRequestContext().put("sun.net.client.defaultConnectTimeout", timeout);  

  16.     ((BindingProvider) service).getRequestContext().put("sun.net.client.defaultReadTimeout", timeout);  

  17.     try {  

  18.         // 调用WebService  

  19.         return service.getData(requestData);  

  20.     } catch (Exception e) {  

  21.         log.error(e.getMessage());  

  22.     }  

  23.     return null;  

  24. }  

     也可以用cxf的wsdl2java命令构建客户端,调用方式一样,但是如何设置超时时间没有试。
 
方法四:使用HttpClient调用WebService
      使用commons-httpclient-3.1,依赖jar包(commons-codec.jar、commons-logging.jar)。

Java代码  收藏代码

  1. public String call(String wsdl, String requestData) {  

  2.     try {  

  3.         // requestData可以直接用soapui中请求的数据,注意<![CDATA[]]>的使用  

  4.         PostMethod postMethod = new PostMethod(wsdl);  

  5.         byte[] b = requestData.getBytes("UTF-8");  

  6.         InputStream in = new ByteArrayInputStream(b, 0, b.length);  

  7.         RequestEntity re = new InputStreamRequestEntity(in,  

  8.                 "text/xml; charset=utf-8");  

  9.         postMethod.setRequestEntity(re);  

  10.         // 设置header SOAPAction,不设置的话,会报异常:no SOAPAction  

  11.         // header,但是SOAPAction的好像任意值都可以  

  12.         String soapAction = "XX";  

  13.         postMethod.setRequestHeader("SOAPAction", soapAction);  

  14.         HttpClient client = new HttpClient();  

  15.         // 设置超时(不知道默认是多久,没有设置的时候,也没有报错,设置下保险些)  

  16.         int timeout = 10 * 60 * 1000;  

  17.         client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout);  

  18.         client.getHttpConnectionManager().getParams().setSoTimeout(timeout);  

  19.         //  

  20.         int status = client.executeMethod(postMethod);  

  21.         if (status == 200) {// 成功  

  22.             InputStream is = postMethod.getResponseBodyAsStream();  

  23.             /** 

  24.              * 获取的结果可以参考用soapui调用时的返回值, 

  25.              * 如果约定的返回值是XML,并不会像soapui一样把xml用<![CDATA[]]>包含起来,要注意解析的方法, 

  26.              * 不知道soapui如何处理的,暂时没时间研究。 

  27.              */  

  28.             return getResponseXML(is);  

  29.         } else {  

  30.             log.error("调用Webservice出错;错误代码为:" + status);  

  31.         }  

  32.     } catch (Exception e) {  

  33.         log.error(e.getMessage());  

  34.     }  

  35.     return null;  

  36. }  

  37. public String getResponseXML(InputStream response) throws Exception {  

  38.     // 根据具体的返回值写的解析  

  39.     SAXReader reader = new SAXReader();  

  40.     Document document = reader.read(response);  

  41.     Element root = document.getRootElement();  

  42.     List<Element> childElements = root.elements();  

  43.     for (Element child : childElements) {  

  44.         List<Element> datas = child.selectNodes("getOrgInfoResponse/getOrgInfoResponse");  

  45.         for (Element node : datas) {  

  46.             // 返回约定的xml  

  47.             return node.getText();  

  48.         }  

  49.     }  

  50.     return null;  

  51. }  

  
 总结下这次遇到的问题:
     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的值是什么好像并不影响结果。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约