Apache CXF实现Web Service(5)—— GZIP使用
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使用相关推荐
- 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 首先 ...
- Java使用Apache CXF开发Web Service
转自:http://blog.csdn.net/hu_shengyang/article/details/38384597 以前工作中也用CXF,但都是用别人现成搭好的环境,这次自己重头搭建一遍环境. ...
- 基于Spring Boot应用Apache CXF发布Web Services服务
记录:298 场景:使用Spring Boot应用Apache CXF发布Web Services服务,实现跨系统之间交互接口. 版本: JDK 1.8 Spring Boot 2.6.3 Apach ...
- apache-cxf 使用_使用Apache CXF进行Web服务学习
apache-cxf 使用 在我的最后几个项目中,我使用了Web服务,在某些地方创建它们并在其他地方使用它们. 我认为标准任务(例如创建客户端,创建Web服务等)非常简单,如果遇到问题,有足够的资源. ...
- 使用Apache CXF进行Web服务学习
在我的最后几个项目中,我使用了Web服务,在某些地方创建它们并在其他地方使用它们. 我觉得创建客户端,创建Web服务等标准任务非常简单,如果遇到问题,有足够的资源. 但是对于Web服务,这是一项琐碎的 ...
- CXF 生成Web Service Client(将WSDl 转化成 Java代码)
CXF 是什么 Apache CXF一个开源的Service框架,它实现了JCP与Web Service中一些重要标准. CXF简化了构造,集成,面 向服务架构(SOA)业务组件与技术的灵活复用.在C ...
- cxf的web service服务,包含client端、service端
1.下载需要的客户端.服务端Jar,客户端jar包链接: https://github.com/zhangliqingyun/jarlist/tree/master/webserviceclient ...
- axis idea 设置apache_利用IDEA创建Web Service服务端和客户端的详细过程
创建服务端 一.file–>new–>project 二.点击next后输入服务端名,点击finish,生成目录如下 三.在 HelloWorld.Java 文件中右击,选 WebServ ...
- Web Service (二) CXF自动发布Web Service(No Spring)
Web Service实现目前流行的框架主要有两种,cxf和axis这两个框架,下面是这两个框架的优缺点,我们这个项目中使用的是cxf这个框架,首先看一下没有集成spring的时候是怎么实现远程调用的 ...
最新文章
- 071_html语言代码
- Leetcode409最长回文串 -字符哈希
- 【牛客 - 188D 】愤怒(01滚动数组优化dp,括号匹配方案个数,tricks)
- 【转】通过IRQL看NT内核
- 内置炊具行业调研报告 - 市场现状分析与发展前景预测
- metasploit联动beef启动
- 怎样取消计算机中镜像,win7系统,如何删除之前创建的镜像文件。 (不是在系统保护里头删除还原点,我试过了)...
- SDP的fmtp部分
- visio设置图片默认大小_visio怎么调整图片大小、间距-visio调整图片大小、间距的方法 - 河东软件园...
- powerdesigner制作数据字典
- 跨境电商亚马逊最新骗局揭秘:所谓的跨境电商亚马逊店铺真的能赚钱吗?真的靠谱?
- php执行fastlane,Fastlane使用说明 自动化打包
- GitHub 标星 120K+!这些神器仅需一行代码即可下载全网视频!
- Windows远程桌面出现Error code: 0xc07的解决方案
- 跳转到三方App ,三方App 是如何返回自己的App的
- 安卓 每日一题 2020年5-6月问题及答案
- MT4安卓版下载安装
- wince投屏苹果手机_全民最大党sjm:汽车上没有HDMI插口,怎么投屏?
- 2014 破旧立新,重新启程
- 智能化停车无线通信解决方案
热门文章
- 测试员,你该如何面对自己30岁后的下坡路?
- php 扩展库 开发环境,PHP 扩展开发环境搭建
- mysql单实例和多实例,MySQL单实例、多实例安装_MySQL
- lesson 6 threads synchronization
- 20复变函数的积分(六)
- 基于标记不确定性和类别不平衡的语义分割在植被制图中的应用(soybean+FCN_segNet+newloss)
- linux+gpio+嵌入式,嵌入式Linux系统中对GPIO操作的方法总结
- 动圈耳机振膜_动圈耳机和动铁耳机区别,以及选择
- web 导出文件时如何让用户选择路径_Visual Paradigm 教程[UML]:如何绘制动画UML活动图?...
- mysql 协议测试_mysqlslap压力测试mysql