加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

webservice(3):CXF拦截器介绍及自定义拦截器实现

发布时间:2020-12-16 21:49:16 所属栏目:安全 来源:网络整理
导读:引自:http://www.cnblogs.com/luangeng/p/6602667.html CXF拦截器是功能的主要实现单元,也是主要的扩展点,可以在不对核心模块进行修改的情况下,动态添加功能。当服务被调用时,会经过多个拦截器链(Interceptor Chain)处理,拦截器链在服务输入(IN)或

引自:http://www.cnblogs.com/luangeng/p/6602667.html

CXF拦截器是功能的主要实现单元,也是主要的扩展点,可以在不对核心模块进行修改的情况下,动态添加功能。当服务被调用时,会经过多个拦截器链(Interceptor Chain)处理,拦截器链在服务输入(IN)或输出(OUT)阶段实现附加功能,拦截器可以在客户端加入,也可以在服务端加入。

拦截器链的阶段:

拦截器链有多个阶段,每个阶段都有多个拦截器。拦截器在拦截器链的哪个阶段起作用,可以在拦截器的构造函数中声明。?
输入拦截器链有如下几个阶段,这些阶段按照在拦截器链中的先后顺序排列。

阶段名称 阶段功能描述
RECEIVE Transport level processing(接收阶段,传输层处理)
(PRE/USER/POST)_STREAM Stream level processing/transformations(流处理/转换阶段)
READ This is where header reading typically occurs(SOAPHeader读取)
(PRE/USER/POST)_PROTOCOL Protocol processing,such as JAX-WS SOAP handlers(协议处理阶段,例如JAX-WS的Handler处理)
UNMARSHAL Unmarshalling of the request(SOAP请求解码阶段)
(PRE/USER/POST)_LOGICAL Processing of the umarshalled request(SOAP请求解码处理阶段)
PRE_INVOKE Pre invocation actions(调用业务处理之前进入该阶段)
INVOKE Invocation of the service(调用业务阶段)
POST_INVOKE Invocation of the outgoing chain if there is one(提交业务处理结果,并触发输入连接器)


输出拦截器链有如下几个阶段,这些阶段按照在拦截器链中的先后顺序排列。

阶段名称 阶段功能描述
SETUP Any set up for the following phases(设置阶段)
(PRE/USER/POST)_LOGICAL Processing of objects about to marshalled
PREPARE_SEND Opening of the connection(消息发送准备阶段,在该阶段创建Connection)
PRE_STREAM 流准备阶段
PRE_PROTOCOL Misc protocol actions(协议准备阶段)
WRITE Writing of the protocol message,such as the SOAP Envelope.(写消息阶段)
MARSHAL Marshalling of the objects
(USER/POST)_PROTOCOL Processing of the protocol message
(USER/POST)_STREAM Processing of the byte level message(字节处理阶段,在该阶段把消息转为字节)
SEND 消息发送


在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],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],BODY_INDEX=-1,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],22 Mar 2017 15:07:38 GMT],transfer-encoding=[chunked]},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],org.apache.cxf.empty.request=true}
null
~~~~~~~~~~~~~~~~~~~

复制代码

?

?

end

原创不易,转载请告知

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读