(六) CXF 客户端调用--GZIP压缩

来源:互联网 发布:数控车床编程g代码 编辑:程序博客网 时间:2024/05/18 06:20

【1. 简介】

      WebService 其实就是HTTP + XML + Scheme , 而CXF 是WebService 的一个框架, 所以WebService 遵守HTTP协议。 HTTP 协议有GZIP 压缩,可以减少数据传输量,增加传输效率,CXF 对此也提供了支持,CXF Feature 特性。

    关于HTTP 的GZIP 压缩,请参考《Tomcat 启用GZIP 压缩》


【2. 使用CXF 发布带有GZIP 特性的WS服务】

        Test_server_publish.java

package org.zgf.cxf.test.o4;import org.apache.cxf.jaxws.JaxWsServerFactoryBean;import org.apache.cxf.transport.common.gzip.GZIPFeature;import org.zgf.cxf.server.HelloWordWS;/** * 测试 ws 服务器发布 */public class Test_server_publish {public static void main(String[] args) {// 1. 设置发布地址:ip 需要为本机ip, 端口号为本机未被占用的端口号String address = "http://172.22.12.85:8180/ws/hellowordws";//创建CXF 的GZIP 特性GZIPFeature gzip = new GZIPFeature();gzip.setThreshold(1);//2. 使用JaxWsServerFactoryBean 发布服务JaxWsServerFactoryBean server = new JaxWsServerFactoryBean();server.setAddress(address);//设置接口发布地址server.setServiceBean(new HelloWordWS()); //设置接口实现类server.getFeatures().add(gzip);//添加GZIP 特性server.create();//发布接口System.out.println("web service 接口发布成功... ");}}

【3. CXF 客户端访问】

        使用CXF 客户端请求,客户端需要设置两个地方,第一 JaxWsProxyFactoryBean 添加Gzip Feature, 第二,Http 请求头添加 gzip,deflate 。 设置之后,在请求的时候,从输出结果并不能看到有什么变化,因为CXF 会自动做转换,读者可以尝试使用HttpClient 访问接口,可以清晰地看出使用GZIP 特性之后CXF服务端返回的结果; 当然了也可以做以下尝试 :

        1. 注释掉:factory.getFeatures().add(gzip);   进行调用会报异常

        2. 注释掉:httpClientPolicy.setAcceptEncoding("gzip,deflate");  能正常运行,但是返回结果并没有进行压缩,从控制台可以看出。

Test_client_cxf.java

package org.zgf.cxf.test.o4;import org.apache.cxf.endpoint.Client;import org.apache.cxf.frontend.ClientProxy;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;import org.apache.cxf.transport.common.gzip.GZIPFeature;import org.apache.cxf.transport.http.HTTPConduit;import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;import org.zgf.cxf.client.IHelloWorldWS;public class Test_client_cxf {public static void main(String[] args) {//WS 服务地址 String address = "http://172.22.12.85:8180/ws/hellowordws";//1. 创建CXF GZIP 特性, 设置阈值GZIPFeature gzip = new GZIPFeature();gzip.setThreshold(1); //通常设置跳过1个字节之后进行压缩//2. 创建JaxWsProxyFactoryBean 对象JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();factory.setServiceClass(IHelloWorldWS.class);//参数是要用的方法所在类的class对象factory.setAddress(address);factory.getFeatures().add(gzip);//3. 创建WS 服务接口代理IHelloWorldWS hws = (IHelloWorldWS) factory.create();//4. 获取Client 对象,设置请求头:gzip,deflateClient client = ClientProxy.getClient(hws);HTTPConduit confuit = (HTTPConduit) client.getConduit();HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();//设置发送请求时携带gzip,deflatehttpClientPolicy.setAcceptEncoding("gzip,deflate");confuit.setClient(httpClientPolicy);//5. 调用WS 接口方法String result = hws.sayHello("zong");System.out.println("result:" + result);}}

【4. HttpClient 客户端访问】

       使用CXF 访问开启GZIP 特性的CXF 服务, 效果不直观,我们可以尝试使用HttpClient 访问WebService 服务。

        HttpClient 是Apache 提供的工具包, 不同的版本使用方式差异性比较大,笔者使用的是4.2.x 系列。

      

【1. 引入jar包】

      

【2. HttpClientUtil.java】

package org.zgf.cxf.test.o4;import java.io.IOException;import java.io.InputStream;import org.apache.commons.io.IOUtils;import org.apache.commons.lang3.StringUtils;import org.apache.http.HttpHost;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.params.ConnRouteParams;import org.apache.http.entity.ByteArrayEntity;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.params.CoreConnectionPNames;public class HttpClientUtil {private static final String CONTENT_TYPE_KEY = "Content-Type";private static final String CONTENT_TYPE_VALUE = "text/xml;charset=UTF-8";private static final String USER_AGENT_KEY = "User-Agent";private static final String USER_AGENT_VALUE = "Apache-HttpClient/4.1.1";private static final String ACCEPT_KEY = "Accept";private static final String ACCEPT_VALUE = "*/*";private static final String ACCEPT_LANGUAGE_KEY = "Accept-Language";private static final String ACCEPT_LANGUAGE_VALUE = "zh-cn";private static final String ACCEPT_ENCODING_KEY = "Accept-Encoding";private static final String ACCEPT_ENCODING_VALUE = "gzip, deflate";// 设置代理private static final String PROXYHOSTNAME = "172.17.18.80";private static final int PROXYPORT = 8080;// 默认编码private static final String DEFAULT_ENCODING = "UTF-8";/** 获取http Post 对象  */private static HttpPost getHttpPost(String serviceWsdl, String requestXml){try {HttpPost httpPost = new HttpPost(serviceWsdl);httpPost.setHeader(CONTENT_TYPE_KEY, CONTENT_TYPE_VALUE);httpPost.setHeader(ACCEPT_LANGUAGE_KEY, ACCEPT_LANGUAGE_VALUE);httpPost.setHeader(ACCEPT_KEY, ACCEPT_VALUE);httpPost.setHeader(USER_AGENT_KEY, USER_AGENT_VALUE);httpPost.setHeader(ACCEPT_ENCODING_KEY, ACCEPT_ENCODING_VALUE);//设置请求参数byte[] bytes = requestXml.getBytes(DEFAULT_ENCODING);ByteArrayEntity byteArrayEntity = new ByteArrayEntity(bytes, 0, bytes.length);httpPost.setEntity(byteArrayEntity);return httpPost;} catch (Exception e) {e.printStackTrace();}return null;}/** 获取httpclient 对象 */private static DefaultHttpClient getProxyHttpClient(){DefaultHttpClient httpClient = new DefaultHttpClient();// 设置请求链接超时httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 600000);// 设置请求读取超时httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 600000);// 设置socket链接时间httpClient.getParams().setParameter(CoreConnectionPNames.SO_KEEPALIVE, 600000);//设置网络代理HttpHost proxy = new HttpHost(PROXYHOSTNAME, PROXYPORT);httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);return httpClient;}/** 解析响应结果  */private static String parseHttpResponse(HttpResponse httpResponse){try {InputStream is = httpResponse.getEntity().getContent();byte[] byteArray = IOUtils.toByteArray(is);System.out.println("解压前的返回结果:\n" + new String(byteArray));if(null != byteArray){//将响应结果解码成字符串String uncompressResult = GZipUtil.unGZip(byteArray);System.out.println("解压后的返回结果:\n" + uncompressResult);//将字符串中的特殊字符做替换uncompressResult = uncompressResult.replace("lt;", "<");uncompressResult = uncompressResult.replace("gt;", ">");//去除包裹响应结果的标签 uncompressResult =  removeSoapTag(uncompressResult);System.out.println("去除SOAP 标签的结果:\n" + uncompressResult);return uncompressResult;}} catch (IllegalStateException | IOException e) {e.printStackTrace();}return null;}/** * @Description请求XML 包裹SOAP 标签, 每个 webservice 服务的包裹方式不一定一样, 具体包裹方式如何,可以通过SOAPUI 软件进行查看 * @param rquestXML请求XML 片段 * @return SOAP 标签包裹的XML 片段 */private static String  wrapSoapTag(String rquestXML){StringBuilder sb = new StringBuilder();sb.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">");sb.append("<soapenv:Header/>");sb.append("<soapenv:Body>");sb.append("<ns2:sayByeBye xmlns:ns2=\"http://server.cxf.zgf.org/\">");sb.append("<arg0>");sb.append("<![CDATA[");sb.append(rquestXML.trim());sb.append("]]>");sb.append("</arg0>");sb.append("</ns2:sayByeBye>");sb.append("</soapenv:Body>");sb.append("</soapenv:Envelope>");return sb.toString();}/** * @Description去掉响应 结果中最外层包裹的SOAP 标签 * @param responseXML * @return 响应结果字符串 */private static String removeSoapTag(String responseXML){if(null == responseXML || "".equals(responseXML)){return responseXML;}String beginTag = "<return>";String endTag = "</return>";return StringUtils.substringBetween(responseXML, beginTag, endTag);}/** 发送web service 请求*/public static String sendPostRequest(String serviceWsdl, String requestXml){//包裹SOAP 标签requestXml = wrapSoapTag(requestXml);HttpPost httpPost = getHttpPost(serviceWsdl, requestXml);HttpClient httpClient = getProxyHttpClient();HttpResponse httpResponse  = null;try {httpResponse = httpClient.execute(httpPost);System.out.println(httpResponse.getStatusLine().getStatusCode());if(httpResponse.getStatusLine().getStatusCode() == 200){return parseHttpResponse(httpResponse);}} catch (IOException e) {e.printStackTrace();}return null;}}

【3. 测试类】

package org.zgf.cxf.test.o4;public class Test_client_http {public static void main(String[] args) {String requestXml = "hello,world";String serviceWsdl = "http://172.22.12.85:8180/ws/hellowordws?wsdl";HttpClientUtil.sendPostRequest(serviceWsdl, requestXml);}}

【4. 输出结果】



【5. 总结】

    1. 如果使用new 的方式创建WS 服务代理,而且不涉及到设置延时,拦截器,GZIP Feature 等,那么客户端应用是不需要导入CXF jar 包的

    2. 如果使用JaxWsProxyFactoryBean 设置GZIP feature , 使用 Client 设置拦截器,延时,那么客户端应用需要导入以下jar 包

    3. 源码下载: WS-CXF.zip


0 0
原创粉丝点击