CXF拦截器介绍及自定义拦截器实现
Posted 魏大宾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CXF拦截器介绍及自定义拦截器实现相关的知识,希望对你有一定的参考价值。
这篇文章从理论角度描述CXF的拦截器,描述的比较清楚。
CXF拦截器是功能的主要实现单元,也是主要的扩展点,可以在不对核心模块进行修改的情况下,动态添加功能。 当服务被调用时,会经过多个拦截器链(Interceptor Chain)处理,拦截器链在服务输入(IN)或输出(OUT)阶段实现附加功能,拦截器可以在客户端加入,也可以在服务端加入。
拦截器链的阶段:
拦截器链有多个阶段,每个阶段都有多个拦截器。拦截器在拦截器链的哪个阶段起作用,可以在拦截器的构造函数中声明。 输入拦截器链有如下几个阶段,这些阶段按照在拦截器链中的先后顺序排列。
输出拦截器链有如下几个阶段,这些阶段按照在拦截器链中的先后顺序排列。
在CXF中,所有对消息的处理都是通过各种拦截器实现。CXF已经实现了多种拦截器,如操纵消息头、执行认证检查、验证消息数据、日志记录、消息压缩等,有些拦截器在发布服务、访问服务时已经默认添加到拦截器链。
日志拦截器
CXF已经内置了一些拦截器,这些拦截器大部分默认添加到拦截器链中,有些需要手动添加,如CXF提供的日志拦截器:输入日志拦截器LoggingInInterceptor和输出日志拦截器LoggingOutInterceptor,可以用在服务端也可以用在客户端,用来在测试或调试的时候输出服务端、客户端请求和接收到的信息。
服务端配置方式如下:
<!-- 发布REST WebService -->
<jaxrs:server id="restServiceContainer" address="/cxf">
<!--输入拦截器设置-->
<jaxrs:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxrs:inInterceptors>
<!--输出拦截器设置-->
<jaxrs:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxrs:outInterceptors>
<!--WebService服务类-->
<jaxrs:serviceBeans>
<ref bean="restService"/>
</jaxrs:serviceBeans>
</jaxrs:server>
API方式:
JAXRSServerFactoryBean jrf = new JAXRSServerFactoryBean();
jrf.setResourceClasses(RestServiceImpl.class);
jrf.setResourceProvider(RestServiceImpl.class, new SingletonResourceProvider(new RestServiceImpl()));
jrf.setAddress(url);
jrf.getInInterceptors().add(new LoggingInInterceptor());
jrf.getOutInterceptors().add(new LoggingOutInterceptor());
jrf.create();
客户端配置方式:
JAXRSClientFactoryBean factory = new JAXRSClientFactoryBean();
factory.setServiceClass(RestService.class);
factory.setAddress(url);
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
RestService ser = factory.create(RestService.class);
ser.get();
输出日志形式如下:客户端:
[INFO ] 03-22 22:33:39 org.apache.cxf.interceptor.AbstractLoggingInterceptor.log(AbstractLoggingInterceptor.java:250) Outbound Message
---------------------------
ID: 1
Address: http://localhost:8080/webapp/ws/cxf/rest
Http-Method: GET
Content-Type: application/xml
Headers: Content-Type=[application/xml], Accept=[text/plain]
--------------------------------------
[INFO ] 03-22 22:33:39 org.apache.cxf.interceptor.AbstractLoggingInterceptor.log(AbstractLoggingInterceptor.java:250) Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: ISO-8859-1
Content-Type: text/plain
Headers: content-type=[text/plain], Date=[Wed, 22 Mar 2017 14:33:39 GMT], transfer-encoding=[chunked]
Payload: this is default get plain
--------------------------------------
服务端:
[INFO ] 03-22 22:33:39 org.apache.cxf.interceptor.AbstractLoggingInterceptor.log(AbstractLoggingInterceptor.java:250) Inbound Message
----------------------------
ID: 4
Address: http://localhost:8080/webapp/ws/cxf/rest
Encoding: UTF-8
Http-Method: GET
Content-Type: application/xml
Headers: Accept=[text/plain], cache-control=[no-cache], connection=[keep-alive], content-type=[application/xml], host=[localhost:8080], pragma=[no-cache], user-agent=[Apache CXF 3.0.3]
--------------------------------------
[INFO ] 03-22 22:33:39 org.apache.cxf.interceptor.AbstractLoggingInterceptor.log(AbstractLoggingInterceptor.java:250) Outbound Message
---------------------------
ID: 4
Response-Code: 200
Content-Type: text/plain
Headers: Content-Type=[text/plain], Date=[Wed, 22 Mar 2017 14:33:39 GMT]
Payload: this is default get plain
--------------------------------------
自定义拦截器
CXF中也可以自定义拦截器,CXF中实现自定义拦截器需要继承AbstractPhaseInterceptor或者其子类如AbstractSoapInterceptor。
/**
* CXF 自定义拦截器
*/
public class MyInterceptor extends AbstractPhaseInterceptor<Message>
//必需提供一个带参数的构造函数
public MyInterceptor(String phase)
super(phase);
//覆写拦截后的动作
@Override
public void handleMessage(Message message) throws Fault
Q.p("~~~~~~~~~~~~~~~~~~");
if (message.getDestination() != null)
Q.p(message.getDestination().getAddress());
if (message.getExchange() != null)
Q.p(message.getExchange().getInMessage());
Q.p(message.getExchange().getOutMessage());
Q.p(message.getContent(String.class));
Q.p("~~~~~~~~~~~~~~~~~~~");
添加到客户端拦截器链:
JAXRSClientFactoryBean factory = new JAXRSClientFactoryBean();
factory.setServiceClass(RestService.class);
factory.setAddress(url);
factory.getInInterceptors().add(new MyInterceptor(Phase.RECEIVE));
factory.getOutInterceptors().add(new MyInterceptor(Phase.SEND));
ser = factory.create(RestService.class);
ser.get();
输出:
[DEBUG] 03-22 23:07:38 org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:304) Invoking handleMessage on interceptor cn.lg.ws.MyInterceptor@58cbafc2
~~~~~~~~~~~~~~~~~~
null
org.apache.cxf.message.Message.PROTOCOL_HEADERS=Content-Type=[application/xml], Accept=[text/plain], org.apache.cxf.transport.Conduit=conduit: class org.apache.cxf.transport.http.URLConnectionHTTPConduit1715248762target: http://localhost:8080/webapp/ws/cxf/rest, org.apache.cxf.request.uri=http://localhost:8080/webapp/ws/cxf/rest, jaxrs.template.parameters=null, org.apache.cxf.message.Message.ENDPOINT_ADDRESS=http://localhost:8080/webapp/ws/cxf/rest, jaxrs.proxy=true, org.apache.cxf.request.method=GET, org.apache.cxf.transport.processOneWayResponse=true, http.connection=sun.net.www.protocol.http.HttpURLConnection:http://localhost:8080/webapp/ws/cxf/rest, org.apache.cxf.message.Message.BASE_PATH=http://localhost:8080/webapp/ws/cxf/, org.apache.cxf.client=true, org.apache.cxf.invocation.context=ResponseContext=, RequestContext=org.apache.cxf.message.Message.PROTOCOL_HEADERS=Content-Type=[application/xml], Accept=[text/plain], org.apache.cxf.request.uri=http://localhost:8080/webapp/ws/cxf/rest, BODY_INDEX=-1, org.apache.cxf.message.Message.ENDPOINT_ADDRESS=http://localhost:8080/webapp/ws/cxf/rest, jaxrs.proxy=true, org.apache.cxf.jaxrs.model.OperationResourceInfo=org.apache.cxf.jaxrs.model.OperationResourceInfo@117159c0, java.lang.annotation.Annotation=[Ljava.lang.annotation.Annotation;@19e4653c, org.apache.cxf.message.inbound=false, http.scheme=http, Content-Type=application/xml, org.apache.cxf.empty.request=true
null
~~~~~~~~~~~~~~~~~~~
``` [DEBUG] 03-22 23:07:38 org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:304) Invoking handleMessage on interceptor cn.lg.ws.MyInterceptor@795509d9 ~~~~~~~~~~~~~~~~~~ org.apache.cxf.message.Message.PROTOCOL_HEADERS=content-type=[text/plain], Date=[Wed, 22 Mar 2017 15:07:38 GMT], transfer-encoding=[chunked], org.apache.cxf.transport.Conduit=conduit: class org.apache.cxf.transport.http.URLConnectionHTTPConduit1715248762target: http://localhost:8080/webapp/ws/cxf/rest, org.apache.cxf.client=true, org.apache.cxf.message.Message.ENCODING=ISO-8859-1, org.apache.cxf.message.inbound=true, org.apache.cxf.message.Message.RESPONSE_CODE=200, Content-Type=text/plain org.apache.cxf.message.Message.PROTOCOL_HEADERS=Content-Type=[application/xml], Accept=[text/plain], org.apache.cxf.transport.Conduit=conduit: class org.apache.cxf.transport.http.URLConnectionHTTPConduit1715248762target: http://localhost:8080/webapp/ws/cxf/rest, org.apache.cxf.request.uri=http://localhost:8080/webapp/ws/cxf/rest, jaxrs.template.parameters=null, org.apache.cxf.message.Message.ENDPOINT_ADDRESS=http://localhost:8080/webapp/ws/cxf/rest, jaxrs.proxy=true, org.apache.cxf.request.method=GET, org.apache.cxf.transport.processOneWayResponse=true, http.connection=sun.net.www.protocol.http.HttpURLConnection:http://localhost:8080/webapp/ws/cxf/rest, org.apache.cxf.message.Message.BASE_PATH=http://localhost:8080/webapp/ws/cxf/, org.apache.cxf.client=true, org.apache.cxf.invocation.context=ResponseContext=, RequestContext=org.apache.cxf.message.Message.PROTOCOL_HEADERS=Content-Type=[application/xml], Accept=[text/plain], org.apache.cxf.request.uri=http://localhost:8080/webapp/ws/cxf/rest, BODY_INDEX=-1, org.apache.cxf.message.Message.ENDPOINT_ADDRESS=http://localhost:8080/webapp/ws/cxf/rest, jaxrs.proxy=true, org.apache.cxf.jaxrs.model.OperationResourceInfo=org.apache.cxf.jaxrs.model.OperationResourceInfo@117159c0, java.lang.annotation.Annotation=[Ljava.lang.annotation.Annotation;@19e4653c, org.apache.cxf.message.inbound=false, http.scheme=http, Content-Type=application/xml, org.apache.cxf.empty.request=true null ~~~~~~~~~~~~~~~~~~~
--------------------------END--------------------------
- 作者:luangeng
- 主页:https://luangeng.gitee.io/
- 本文出处:https://www.code996.cn/post/2017/cxf-interceptor/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
以上是关于CXF拦截器介绍及自定义拦截器实现的主要内容,如果未能解决你的问题,请参考以下文章
WebService -- Java 实现之 CXF ( 添加系统预定义的拦截器)