Apache CXF实现Web Service(5)—— GZIP使用


参考来源:

  • CXF WebService整合Spring
  • Apache CXF实现Web Service(1)——不借助重量级Web容器和Spring实现一个纯的JAX-WS web service
  • Apache CXF实现Web Service(4)——Tomcat容器和Spring实现JAX-RS(RESTful) web service

首先参照

Apache CXF实现Web Service(4) 创建一个WTP项目,并参照(1) 新建一个测试的Web Service:HelloWorld.java和其实现HelloWorldImpl.java

HelloWorld.java

package com.cnblog.richaaaard.cxftest.spring.ws.helloworld.services;import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;import org.apache.cxf.annotations.GZIP;//@GZIP(threshold=128)
@GZIP
@WebService
public interface HelloWorld {  @WebMethod  @WebResult String sayHi(@WebParam String text);
}

HelloWorldImpl.java

package com.cnblog.richaaaard.cxftest.spring.ws.helloworld.services;import javax.jws.WebService;@WebService(endpointInterface="com.cnblog.richaaaard.cxftest.spring.ws.helloworld.services.HelloWorld",serviceName="helloService")
public class HelloWorldImpl implements HelloWorld {  public String sayHi(String name) {  String msg = "Hello " + name + "!";  return msg;  }
}  

在Spring的配置中需要注意的是,我们需要引入jarws的schema

    http://cxf.apache.org/jaxwshttp://cxf.apache.org/schemas/jaxws.xsd

完整的配置文件如下:

<beans xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xmlns:jaxws="http://cxf.apache.org/jaxws"   xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"default-lazy-init="true">  <import resource="classpath:META-INF/cxf/cxf.xml"/>  <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>  <bean id="helloService"     class="com.cnblog.richaaaard.cxftest.spring.ws.helloworld.services.HelloWorldImpl">  </bean>  <jaxws:endpoint implementor="#helloService" address="/HelloService"/>
</beans>   

web.xml文件保持不变

<beans xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xmlns:jaxws="http://cxf.apache.org/jaxws"   xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"default-lazy-init="true">  <import resource="classpath:META-INF/cxf/cxf.xml"/>  <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>  <bean id="helloService" class="com.cnblog.richaaaard.cxftest.spring.ws.helloworld.services.HelloWorldImpl">  </bean>  <jaxws:endpoint implementor="#helloService" address="/HelloService"/>
</beans>   

项目结构如图

下面需要测试几个问题

  • @GZIP如何工作的?
  • @GZIP有两个属性 force 和 threshold 怎么用?
  • @GZIP加在接口上是否可行?(我们用Spring实例化bean是用的HelloWorldImpl)

测试

  • @GZIP如何工作的?

第一步

在Eclipse中Run As... -> Run on Server,然后在浏览器中验证是否发布成功:

我们Tomcat本地运行的端口是8080。

第二步

运行TCPMon,新建监听端口8081,目标端口8080:

第三步

新建客户端测试代码,并将address设置成"http://localhost:8081/cxf/services/HelloService"

package com.cnblog.richaaaard.cxftest.spring.ws.helloworld.client;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.common.gzip.GZIPInInterceptor;
import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;import com.cnblog.richaaaard.cxftest.spring.ws.helloworld.services.HelloWorld;public class Client {  public static void main(String[] args) {  JaxWsProxyFactoryBean client = new JaxWsProxyFactoryBean();
//        factory.getInInterceptors().add(new LoggingInInterceptor());
//        factory.getOutInterceptors().add(new LoggingOutInterceptor());
//        factory.getInInterceptors().add(new GZIPInInterceptor());
//        factory.getOutInterceptors().add(new GZIPOutInterceptor());client.setServiceClass(HelloWorld.class);  client.setAddress("http://localhost:8081/cxf/services/HelloService");  HelloWorld helloworld = (HelloWorld) client.create();  System.out.println(helloworld.sayHi("Richard"));  System.exit(0);  }
} 

第一个测试,运行Client.java

Run As... -> Java Application

在TCPMon(关于如何使用TCPMon请查看http://www.cnblogs.com/richaaaard/p/5019438.html)中查看结果

发现并没有像预料中的那样发生GZIP压缩

怀疑出现问题
  • 服务器不支持GZIP?
  • CXF有BUG?
  • 使用方式有问题?
打开@GZIP Annotation的源码查看
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
@Inherited
public @interface GZIP {int threshold() default -1;boolean force() default false;
}

这个标注有两个属性:threshold 与 force

然后查看Apache CXF 关于@GZIP的文档 (CXF Features http://cxf.apache.org/docs/featureslist.html) 与 (CXF Annotations http://cxf.apache.org/docs/annotations.html)

细心的同学会发现“CXF Features文档中关于GZIPFeature的说明中仍然出现了FastInfoset”这个错误


  • threshold - the threshold under which messages are not gzipped
  • force - force GZIP compression instead of negotiating via the Accept-Encoding header

GZIP is a negotiated enhancement. An initial request from a client will not be gzipped, but an Accept header will be added and if the server supports it, the response will be gzipped and any subsequent requests will be.

上面一段话的意思是:第一次请求不会发生GZIP,但是如果服务器支持,会加如到Accept头上,返回的消息会发生GZIP然后,后面发生的请求也会有GZIP。

关于threshold的定义:可以发现我们测试中的请求(request)长度(Content-Length)是232,返回(response)长度是259。

这里猜想

@GZIP应该有一个自己的默认threshold,如果修改默认实现,也就能发生GZIP了

我们将threshold修改成256介于232和259之间

@GZIP(threshold=256)
//@GZIP
@WebService
public interface HelloWorld {  @WebMethod  @WebResult String sayHi(@WebParam String text);
}  

重启服务器,运行程序

请求没有发生GZIP,而响应端有GZIP

再次运行Client(不重启服务器)

我们发现,请求(request)并没有像Apache官方文档那样说的,也会有GZIP。

这是为什么呢?是不是和我们的客户端有关?

将代码增加一次请求试试

发现连续的两次请求仍然没有发生GZIP。再仔细查看关于GZIP的解释,"...如果服务器支持..."

package com.cnblog.richaaaard.cxftest.spring.ws.helloworld.client;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.common.gzip.GZIPInInterceptor;
import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;import com.cnblog.richaaaard.cxftest.spring.ws.helloworld.services.HelloWorld;public class Client {  public static void main(String[] args) {  JaxWsProxyFactoryBean client = new JaxWsProxyFactoryBean();
//        factory.getInInterceptors().add(new LoggingInInterceptor());
//        factory.getOutInterceptors().add(new LoggingOutInterceptor());
//        factory.getInInterceptors().add(new GZIPInInterceptor());
//        factory.getOutInterceptors().add(new GZIPOutInterceptor());client.setServiceClass(HelloWorld.class);  client.setAddress("http://localhost:8081/cxf/services/HelloService");  HelloWorld helloworld = (HelloWorld) client.create();  System.out.println(helloworld.sayHi("Richard"));  System.out.println(helloworld.sayHi("Kobe Bryant")); System.exit(0);  }
} 

这里猜想

是不是我们服务器的设置问题,不支持GZIP呢?

修改Tomcat的Connector配置,增加

    compressionMinSize="256" compression="on" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml"

然后重启服务器,再运行客户端

发现请求(request)仍然没有发生GZIP

如何才能使请求也提交GZIP格式呢?

我们暂且放下这个问题,先将Tomcat配置文件关于compression的配置还原

来看看force如何工作的

在HelloWorld.java的头上修改@GZIP增加force属性,threshold仍然为256

@GZIP(force=true, threshold=256)
@WebService
public interface HelloWorld {  @WebMethod  @WebResult String sayHi(@WebParam String text);
}  

请求仍然没有被压缩
[](http://images2015.cnblogs.com/blog/613455/201512/613455-20151204175354393-824266017.png

修改成128呢?因为请求的Content-Length是232

在次运行,发现请求成功压缩了(这是请求压缩的一种情景)

好像漏了什么东西

之前我们反复测试,期望第二次请求(request)可以根据服务端返回的Accept-Encoding header 自行进行GZIP压缩,我们测试代码当时设置的threhold是256,而请求的Content-Length=232。我们将threshold调整到128,去掉force属性,重启服务器再试一下(这时的Tomcat没有配置compression相关属性)。

  • 当我们单次运行的时候(每次客户端运行结束,进程退出)

先后运行两次独立的请求,请求(request)没有发生GZIP,这是因为客户端是不同进程的缘故

  • 当我加入一行代码,在统一进程中连续两次请求服务器时,我们会发现第二次请求会自行GZIP压缩,而此时Tomcat上没有对compression进行特别配置

由此可见

  • Tomcat是内置支持GZIP的服务器
  • Tomcat上的compression是服务器自己独立的压缩机制,与Apache CXF无关,但是服务器级别的配置会影响我们使用的CXF Web Service

那么问题来了

Tomcat服务器配置的压缩机制是怎么工作的呢?


*扩展

StackOverflow上关于GZIPInInterceptor和GZIPOutInterceptor的回答是否正确?

通过上面的所有测试就能得出结论,这个Interceptor并不对服务端响应消息的GZIP起任何作用,读者可以自行测试

Apache CXF实现Web Service(5)—— GZIP使用相关推荐

  1. Apache CXF实现Web Service(3)——Tomcat容器和不借助Spring的普通Servlet实现JAX-RS(RESTful) web service...

    起步 参照这一系列的另外一篇文章: Apache CXF实现Web Service(2)--不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service 首先 ...

  2. Java使用Apache CXF开发Web Service

    转自:http://blog.csdn.net/hu_shengyang/article/details/38384597 以前工作中也用CXF,但都是用别人现成搭好的环境,这次自己重头搭建一遍环境. ...

  3. 基于Spring Boot应用Apache CXF发布Web Services服务

    记录:298 场景:使用Spring Boot应用Apache CXF发布Web Services服务,实现跨系统之间交互接口. 版本: JDK 1.8 Spring Boot 2.6.3 Apach ...

  4. apache-cxf 使用_使用Apache CXF进行Web服务学习

    apache-cxf 使用 在我的最后几个项目中,我使用了Web服务,在某些地方创建它们并在其他地方使用它们. 我认为标准任务(例如创建客户端,创建Web服务等)非常简单,如果遇到问题,有足够的资源. ...

  5. 使用Apache CXF进行Web服务学习

    在我的最后几个项目中,我使用了Web服务,在某些地方创建它们并在其他地方使用它们. 我觉得创建客户端,创建Web服务等标准任务非常简单,如果遇到问题,有足够的资源. 但是对于Web服务,这是一项琐碎的 ...

  6. CXF 生成Web Service Client(将WSDl 转化成 Java代码)

    CXF 是什么 Apache CXF一个开源的Service框架,它实现了JCP与Web Service中一些重要标准. CXF简化了构造,集成,面 向服务架构(SOA)业务组件与技术的灵活复用.在C ...

  7. cxf的web service服务,包含client端、service端

    1.下载需要的客户端.服务端Jar,客户端jar包链接:  https://github.com/zhangliqingyun/jarlist/tree/master/webserviceclient ...

  8. axis idea 设置apache_利用IDEA创建Web Service服务端和客户端的详细过程

    创建服务端 一.file–>new–>project 二.点击next后输入服务端名,点击finish,生成目录如下 三.在 HelloWorld.Java 文件中右击,选 WebServ ...

  9. Web Service (二) CXF自动发布Web Service(No Spring)

    Web Service实现目前流行的框架主要有两种,cxf和axis这两个框架,下面是这两个框架的优缺点,我们这个项目中使用的是cxf这个框架,首先看一下没有集成spring的时候是怎么实现远程调用的 ...

最新文章

  1. 071_html语言代码
  2. Leetcode409最长回文串 -字符哈希
  3. 【牛客 - 188D 】愤怒(01滚动数组优化dp,括号匹配方案个数,tricks)
  4. 【转】通过IRQL看NT内核
  5. 内置炊具行业调研报告 - 市场现状分析与发展前景预测
  6. metasploit联动beef启动
  7. 怎样取消计算机中镜像,win7系统,如何删除之前创建的镜像文件。 (不是在系统保护里头删除还原点,我试过了)...
  8. SDP的fmtp部分
  9. visio设置图片默认大小_visio怎么调整图片大小、间距-visio调整图片大小、间距的方法 - 河东软件园...
  10. powerdesigner制作数据字典
  11. 跨境电商亚马逊最新骗局揭秘:所谓的跨境电商亚马逊店铺真的能赚钱吗?真的靠谱?
  12. php执行fastlane,Fastlane使用说明 自动化打包
  13. GitHub 标星 120K+!这些神器仅需一行代码即可下载全网视频!
  14. Windows远程桌面出现Error code: 0xc07的解决方案
  15. 跳转到三方App ,三方App 是如何返回自己的App的
  16. 安卓 每日一题 2020年5-6月问题及答案
  17. MT4安卓版下载安装
  18. wince投屏苹果手机_全民最大党sjm:汽车上没有HDMI插口,怎么投屏?
  19. 2014 破旧立新,重新启程
  20. 智能化停车无线通信解决方案

热门文章

  1. 测试员,你该如何面对自己30岁后的下坡路?
  2. php 扩展库 开发环境,PHP 扩展开发环境搭建
  3. mysql单实例和多实例,MySQL单实例、多实例安装_MySQL
  4. lesson 6 threads synchronization
  5. 20复变函数的积分(六)
  6. 基于标记不确定性和类别不平衡的语义分割在植被制图中的应用(soybean+FCN_segNet+newloss)
  7. linux+gpio+嵌入式,嵌入式Linux系统中对GPIO操作的方法总结
  8. 动圈耳机振膜_动圈耳机和动铁耳机区别,以及选择
  9. web 导出文件时如何让用户选择路径_Visual Paradigm 教程[UML]:如何绘制动画UML活动图?...
  10. mysql 协议测试_mysqlslap压力测试mysql