专注人工智能在金融领域的应用

Apache CXF拦截器(Interceptor)的使用

CXF官方定义如下:

Apache CXF is an open source services framework. CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI.

该框架提供了以下功能:

  • Web 服务标准支持:CXF 支持以下 Web 服务标准:
    • Java API for XML Web Services (JAX-WS)
    • SOAP
    • Web 服务描述语言(Web Services Description Language ,WSDL)
    • 消息传输优化机制(Message Transmission Optimization Mechanism,MTOM)
    • WS-Basic Profile
    • WS-Addressing
    • WS-Policy
    • WS-ReliableMessaging
    • WS-Security
  • 前端建模:CXF 提供了前端建模的概念,允许您使用不同的前端 API 来创建 Web 服务。API 允许您使用简单的工厂 Bean 并通过 JAX-WAS 实现来创建 Web 服务。它还允许您创建动态 Web 服务客户端。
  • 工具支持:CXF 提供了用于在 Java Bean、Web 服务和 WSDL 之间进行转换的不同工具。它提供了对 Maven 和 Ant 集成的支持,并无缝地支持 Spring 集成。
  • RESTful 服务支持:CXF 支持代表性状态传输(Representational State Transfer,RESTful )服务的概念,并支持 Java 平台的 JAX-RS 实现。(本系列的第 2 部分将提供有关 RESTful 服务的更多信息。)
  • 对不同传输和绑定的支持:CXF 支持不同种类的传输,从 XML 到逗号分隔值 (CSV)。除了支持 SOAP 和 HTTP 协议绑定之外,它还支持 Java Architecture for XML Binding (JAXB) 和 AEGIS 数据绑定。
  • 对非 XML 绑定的支持:CXF 支持非 XML 绑定,例如 JavaScript Object Notation (JSON) 和 Common Object Request Broker Architecture (CORBA)。它还支持 Java 业务集成(Java Business Integration,JBI)体系架构和服务组件体系架构(Service Component Architecture,SCA)。
  • code first 或者 xml first  : 支持使用code first 或者 xml first 的方式来创建web服务。

CXF的拦截器是CXF功能最主要的扩展点。通过自定义的Interceptor,可以改变请求和响应的一些消息处理,其中最基本的原理还是一个动态代理。

Interceptor是CXF架构中一个很有特色的模式。你可以在不对核心模块进行修改的情况下,动态添加很多功能。这对于CXF这个以处理消息为中心的服务框架来说是非常有用的,CXF通过在Interceptor中对消息进行特殊处理,实现了很多重要功能模块,例如:日志记录,Soap消息处理,消息的压缩处理、异常处理等。

如果你想对CXF进行扩展,建议你先从interceptor开始。

为了更好的学习和使用CXF,最好先阅读官方的用户手册:

https://cwiki.apache.org/confluence/display/CXF20DOC/Index

一、      基本原理

下面看看CFX Interceptor在整个请求响应的处理过程中所处的位置。

《Apache CXF拦截器(Interceptor)的使用》

《Apache CXF拦截器(Interceptor)的使用》

二、      CFX Interceptor的核心API

先看拦截器核心包org.apache.cxf.interceptor的说明:Core interceptor interfaces which form the basis for message processing chains in CXF.

翻译:CXF消息处理链最基本的拦截器接口。

以下几个的API的介绍和翻译来自互联网:

Interceptor

定义两个方法,一个处理消息 handleMessage, 一个是处理错误 handleFault。别看Interceptor这么简单,这里需要提醒注意的是,在实行具体的Interceptor的这两个方法中,千万别调用Interceptor内部的成员变量。这是由于Interceptor是面向消息来进行处理的,每个Interceptor都有可能运行在不同的线程中,如果调用了Interceptor中的内部成员变量,就有在Interceptor中造成临界资源的访问的情况,而这时的Interceptor也就不是线程安全的Interceptor了。

在CXF中最常使用的Interceptor都放在cxf-rt-core中的org.apache.cxf.interceptor中,有兴趣的朋友可以研究一下。

InterceptorChain

单个的Interceptor功能有限,CXF要实现一个SOAP消息处理,需要将许许多多的Interceptor组合在一起使用。因此设计了 InterceptorChain,在我看了InterceptorChain就像是一个Interceptor的小队长。 小队长有调配安置Interceptor的权力(add,remove),也有控制消息处理的权力(doInterceptor,pause,resume,reset,abort),同时也有交付错误处理的权力( {get|set}FaultObserver)。更有意思的是为灵活控制Interceptor的处理消息顺序(doInterceptStartingAt,doInterceptorStartingAfter),这也是InterceptorChain比较难理解的地方。

有兴趣的朋友可以跟踪一下,CXF的Client与Server之间通讯是走过哪些Interceptor,这些Interceptor是如何被调用的。

Fault

定义了CXF中的错误消息。

InterceptorProvider

这里定义了Interceptor的后备保障部队。我们可以在InterceptorProvider中设置In,Out,InFault,OutFault 后备小分队,添加我们所希望添加的Interceptor。而InterceptorChain会根据这些后备小分队,组建自己的小分队实例,完成具体的作战功能任务。

AbstractAttributedInterceptorProvider

InterceptorProvider实现的抽象类,由于这个类来继承了HashMap,我们可以像这个类中存储一些属性信息。

AbstractBasicInterceptorProvider

与AbstractAttributedInterceptorProvider不同,这个Interceptor只是简单实现了InterceptorProvider的功能,并不提供对其属性存储的扩展。

Message

由于Interceptor是针对Message来进行处理的,当你打开Message这个类文件时,你会发现在Message中定义了很多常量,同时你还可以从Message中获取到很多与Message操作相关的信息。可以获取设置的对象有InterceptorChain Exchange Destination,还有获取设置Content的泛型接口,是不是感觉Message和Bus差不多,都成了大杂货铺,一切与消息处理相关的信息都可以放在Message中。我想这也是咱CXF以Message处理为中心的设计思想的具体表现吧。

Exchange

和Message打交道就离不开Exchange。Exchange建立In/Out,InFault/OutFault Message 之间的联系。你可以从Exchange中获取到与消息传输相关的Conduit,Destination的信息,同时也可以设置和Session相关的其他信息,以及知道是否是OneWay的消息。

AbstractFeature

为了简化配置Interceptor的复杂操作,在这里设置了AbstractFeature,通过Feature我们可以向Bus,Client,Endpoint配置不同功能的Interceptor组。这样可以极大减轻我们配置文件的体积。

在此之前我们如果想把一组Log Interceptors添加到Bus中,需要写的配置文件如下

  1. <bean id=“jsonProvider” class=“org.codehaus.jackson.jaxrs.JacksonJsonProvider” />   
  2.   
  3.     <jaxrs:server id=“appServer” address=“/”>   
  4.   
  5.        <jaxrs:serviceBeans>   
  6.   
  7.            <ref bean=“callbackService” />   
  8.   
  9.            <ref bean=“appService” />   
  10.   
  11.        </jaxrs:serviceBeans>   
  12.   
  13.         <jaxws:inInterceptors>   
  14. <bean class=“org.apache.cxf.interceptor.LoggingInInterceptor”/>   
  15. </jaxws:inInterceptors>   
  16. <jaxws:outInterceptors>   
  17. <bean class=“org.apache.cxf.interceptor.LoggingOutInterceptor”>   
  18. </jaxws:outInterceptors>   
  19. <jaxws:inFaultInterceptors>   
  20. <bean class=“org.apache.cxf.interceptor.LoggingInInterceptor”/>   
  21. </jaxws:inInterceptors>   
  22. <jaxws:outFaultInterceptors>   
  23. <bean class=“org.apache.cxf.interceptor.LoggingOutInterceptor”>   
  24.   
  25. </jaxws:outInterceptors>   
  26.   
  27.        <jaxrs:extensionMappings>   
  28.   
  29.            <entry key=“json” value=“application/json” />   
  30.   
  31.            <entry key=“xml” value=“application/xml” />   
  32.   
  33.            <entry key=“zip” value=“application/zip” />   
  34.   
  35.        </jaxrs:extensionMappings>   
  36.   
  37.        <jaxrs:providers>   
  38.   
  39.            <ref bean=“jsonProvider” />   
  40.   
  41.        </jaxrs:providers>   
  42.   
  43.        <jaxrs:languageMappings>   
  44.   
  45.            <entry key=“cn” value=“cn-ZH” />   
  46.   
  47.        </jaxrs:languageMappings>   
  48.   
  49.     </jaxrs:server>  

而一旦使用了Feature,我们的配置文件就变成了

  1. <bean id=“jsonProvider” class=“org.codehaus.jackson.jaxrs.JacksonJsonProvider” />   
  2.   
  3.    <jaxrs:server id=“appServer” address=“/”>   
  4.   
  5.       <jaxrs:serviceBeans>   
  6.   
  7.           <ref bean=“callbackService” />   
  8.   
  9.           <ref bean=“appService” />   
  10.   
  11.       </jaxrs:serviceBeans>   
  12.   
  13.       <jaxrs:features>   
  14.   
  15.           <bean  class=“com.xxx.MyFeature”></bean>   
  16.   
  17.       </jaxrs:features>   
  18.   
  19.       <jaxrs:extensionMappings>   
  20.   
  21.           <entry key=“json” value=“application/json” />   
  22.   
  23.           <entry key=“xml” value=“application/xml” />   
  24.   
  25.           <entry key=“zip” value=“application/zip” />   
  26.   
  27.       </jaxrs:extensionMappings>   
  28.   
  29.       <jaxrs:providers>   
  30.   
  31.           <ref bean=“jsonProvider” />   
  32.   
  33.       </jaxrs:providers>   
  34.   
  35.       <jaxrs:languageMappings>   
  36.   
  37.           <entry key=“cn” value=“cn-ZH” />   
  38.   
  39.       </jaxrs:languageMappings>   
  40.   
  41.    </jaxrs:server>  

三、      定义自己的Interceptor

自定的Interceptor一定要实现CXF的Interceptor接口,这个接口中有两个方法:

 void handleFault(T message)

          当拦截消息处理失败时候所调用的方法。

 void handleMessage(T message)

          拦截了一个消息,并做处理的方法。

对于SOAP这种XML格式的消息,开发者处理太过于麻烦,并且CXF提供大量的已经实现好的拦截器可供使用,只要灵活运用这些拦截器就可以满足大部分开发的要求。

四、      CXF拦截器使用

CXF的使用比较容易,可以单独使用,也可以与Spring完美整合,这里就通过一个异常拦截器的例子来说明如何使用拦截器。

比如,要实现一个统一的异常处理框架,当后台出现异常时,再返回给客户端前进行统一的处理后(例如,将异常信息添加到HTTP header中)再将异常信息返回给客户端。

服务端:

  1. import org.apache.cxf.Bus;   
  2.   
  3. import org.apache.cxf.feature.AbstractFeature;   
  4.   
  5. import org.apache.cxf.interceptor.InterceptorProvider;   
  6.   
  7. /**
  8.  
  9.  * 在此添加自定义拦截器到CXF拦截器链中  
  10.  
  11. * @author http://wangbaocai.cn  
  12.  
  13. */  
  14.   
  15. public class MyFeature extends AbstractFeature {   
  16.   
  17.     @Override  
  18.   
  19.     protected void initializeProvider(InterceptorProvider provider, Bus bus) {   
  20.   
  21.        provider.getOutFaultInterceptors().add(new OutFaultInterceptor());   
  22.   
  23.     }   
  24.   
  25. }   
  26.   
  27. import java.io.IOException;   
  28.   
  29. import java.io.OutputStream;   
  30.   
  31. import java.io.UnsupportedEncodingException;   
  32.   
  33. import java.net.HttpURLConnection;   
  34.   
  35. import java.util.Arrays;   
  36.   
  37. import java.util.Map;   
  38.   
  39. import jxl.common.Logger;   
  40.   
  41. import org.apache.commons.collections.map.HashedMap;   
  42.   
  43. import org.apache.cxf.endpoint.Endpoint;   
  44.   
  45. import org.apache.cxf.interceptor.Fault;   
  46.   
  47. import org.apache.cxf.message.Exchange;   
  48.   
  49. import org.apache.cxf.message.Message;   
  50.   
  51. import org.apache.cxf.phase.AbstractPhaseInterceptor;   
  52.   
  53. import org.apache.cxf.phase.Phase;   
  54.   
  55. import org.apache.cxf.transport.Conduit;   
  56.   
  57. import org.apache.cxf.ws.addressing.EndpointReferenceType;   
  58.   
  59. import com.xxx.exception.MyException;   
  60.   
  61. /**
  62.  
  63.  * 异常拦截器,当返回给客户端包含异常信息时,进入该拦截器  
  64.  
  65.  * @author http://wangbaocai.cn  
  66.  
  67.  */  
  68.   
  69. public class OutFaultInterceptor extends AbstractPhaseInterceptor<Message> {   
  70.   
  71.     private static final Logger logger = Logger   
  72.   
  73.            .getLogger(OutFaultInterceptor.class);   
  74.   
  75.     private static final String ERROR_CODE=“Error-Code”;   
  76.   
  77.     private static final String ERROR_MESSAGE=“Error-Message”;   
  78.   
  79.     public OutFaultInterceptor() {   
  80.   
  81.        super(Phase.PREPARE_SEND);   
  82.   
  83.     }   
  84.   
  85.     public OutFaultInterceptor(String phase) {   
  86.   
  87.         super(Phase.PREPARE_SEND);   
  88.   
  89.     }   
  90.   
  91.     @Override  
  92.   
  93.     public void handleMessage(Message message) throws Fault {   
  94.   
  95.        Exception exception = message.getContent(Exception.class);   
  96.   
  97.        if (exception != null) {   
  98.   
  99.            Throwable e = exception.getCause();   
  100.   
  101.            if (e instanceof MyException) {   
  102.   
  103.               String code = ((MyException) e).getCode();   
  104.   
  105.               String msg = e.getMessage();   
  106.   
  107.               logger.error(e);   
  108.   
  109.               try {   
  110.   
  111.                   sendErrorResponse(message,   
  112.   
  113.                          HttpURLConnection.HTTP_INTERNAL_ERROR, code, msg);   
  114.   
  115.               } catch (UnsupportedEncodingException e1) {   
  116.   
  117.                   logger.error(e1);   
  118.   
  119.               }   
  120.   
  121.            } else {   
  122.   
  123.               logger.error(exception);   
  124.   
  125.            }   
  126.   
  127.        }   
  128.   
  129.     }   
  130.   
  131.     private Message getOutMessage(Message inMessage) {   
  132.   
  133.        Exchange exchange = inMessage.getExchange();   
  134.   
  135.        Message outMessage = exchange.getOutMessage();   
  136.   
  137.        if (outMessage == null) {   
  138.   
  139.            Endpoint endpoint = exchange.get(Endpoint.class);   
  140.   
  141.            outMessage = endpoint.getBinding().createMessage();   
  142.   
  143.            exchange.setOutMessage(outMessage);   
  144.   
  145.        }   
  146.   
  147.        outMessage.putAll(inMessage);   
  148.   
  149.        return outMessage;   
  150.   
  151.     }   
  152.   
  153.     private Conduit getConduit(Message inMessage) throws IOException {   
  154.   
  155.        Exchange exchange = inMessage.getExchange();   
  156.   
  157.        EndpointReferenceType target = exchange   
  158.   
  159.               .get(EndpointReferenceType.class);   
  160.   
  161.        Conduit conduit = exchange.getDestination().getBackChannel(inMessage,   
  162.   
  163.               null, target);   
  164.   
  165.        exchange.setConduit(conduit);   
  166.   
  167.        return conduit;   
  168.   
  169.     }   
  170.   
  171.     private void close(Message outMessage) throws IOException {   
  172.   
  173.        OutputStream os = outMessage.getContent(OutputStream.class);   
  174.   
  175.        os.flush();   
  176.   
  177.        os.close();   
  178.   
  179.     }   
  180.   
  181.     @SuppressWarnings({ “unchecked”“rawtypes” })   
  182.   
  183.     private void sendErrorResponse(Message message, int responseCode,   
  184.   
  185.            String errorCode, String errorMsg) throws UnsupportedEncodingException {   
  186.   
  187.        Message outMessage = getOutMessage(message);   
  188.   
  189.        outMessage.put(Message.RESPONSE_CODE, responseCode);   
  190.   
  191.        // Set the response headers   
  192.   
  193.        Map responseHeaders = (Map) outMessage.get(Message.PROTOCOL_HEADERS);   
  194.   
  195.        if (responseHeaders != null) {   
  196.   
  197.            responseHeaders.put(ERROR_CODE,   
  198.   
  199.                   Arrays.asList(new String[] { errorCode}));   
  200.   
  201.            responseHeaders.put(ERROR_MESSAGE,   
  202.   
  203.                   Arrays.asList(new String[] { errorMsg}));   
  204.   
  205.        }else{   
  206.   
  207.            responseHeaders = new HashedMap();   
  208.   
  209.            responseHeaders.put(ERROR_CODE,   
  210.   
  211.                   Arrays.asList(new String[] { errorCode}));   
  212.   
  213.            responseHeaders.put(ERROR_MESSAGE,   
  214.   
  215.                   Arrays.asList(new String[] { new String( errorMsg.getBytes(),“utf-8″)}));   
  216.   
  217.            responseHeaders.put(“Content-Type”,Arrays.asList(new String[] { “text/xml;charset=UTF-8″}));   
  218.   
  219.            outMessage.put(Message.PROTOCOL_HEADERS, responseHeaders);   
  220.   
  221.        }   
  222.   
  223.        message.getInterceptorChain().abort();   
  224.   
  225.        try {   
  226.   
  227.            getConduit(message).prepare(outMessage);   
  228.   
  229.            close(outMessage);   
  230.   
  231.        } catch (IOException e) {   
  232.   
  233.            logger.error(e);   
  234.   
  235.        }   
  236.   
  237.     }   
  238.   
  239. }  

applicationContext.xml文件配置如下:

  1. <bean id=“jsonProvider” class=“org.codehaus.jackson.jaxrs.JacksonJsonProvider” />   
  2.   
  3.     <jaxrs:server id=“appServer” address=“/”>   
  4.   
  5.        <jaxrs:serviceBeans>   
  6.   
  7.            <ref bean=“pService” />   
  8.   
  9.            <ref bean=“callbackService” />   
  10.   
  11.            <ref bean=“appWSService” />   
  12.   
  13.            <ref bean=“appService” />   
  14.   
  15.        </jaxrs:serviceBeans>   
  16.   
  17.        <jaxrs:features>   
  18.   
  19.            <bean   
  20.   
  21.     class=“com.xxx.exception.interceptor.MyFeature”></bean>   
  22.   
  23.        </jaxrs:features>   
  24.   
  25.        <jaxrs:extensionMappings>   
  26.   
  27.            <entry key=“json” value=“application/json” />   
  28.   
  29.            <entry key=“xml” value=“application/xml” />   
  30.   
  31.            <entry key=“zip” value=“application/zip” />   
  32.   
  33.        </jaxrs:extensionMappings>   
  34.   
  35.        <jaxrs:providers>   
  36.   
  37.            <ref bean=“jsonProvider” />   
  38.   
  39.        </jaxrs:providers>   
  40.   
  41.        <jaxrs:languageMappings>   
  42.   
  43.            <entry key=“cn” value=“cn-ZH” />   
  44.   
  45.        </jaxrs:languageMappings>   
  46.   
  47.     </jaxrs:server>  

客户端:

客户端使用Spring的RestTemplate进行Rest请求,当请求响应码非200时,会调用ResponseErrorHandler进行如处理,因此我们可以实现ResponseErrorHandler接口来对响应的内容进行处理。

  1. /**  
  2.  
  3.  * 后台Rest异常处理  
  4.  
  5.  * @author http://wangbaocai.cn  
  6.  
  7.  */  
  8.   
  9. public class MyResponseErrorHandler implements ResponseErrorHandler {   
  10.   
  11.     @Override  
  12.   
  13.     public boolean hasError(ClientHttpResponse response) throws IOException {   
  14.   
  15.        return hasError(getHttpStatusCode(response));   
  16.   
  17.     }   
  18.   
  19.     @Override  
  20.   
  21.     public void handleError(ClientHttpResponse response) throws IOException {   
  22.   
  23.        String body;   
  24.   
  25.        HttpStatus statusCode = getHttpStatusCode(response);   
  26.   
  27.        switch (statusCode.series()) {   
  28.   
  29.        case CLIENT_ERROR:   
  30.   
  31.               throw new HttpClientErrorException(statusCode,   
  32.   
  33.                      response.getStatusText(), response.getHeaders(),   
  34.   
  35.                      getResponseBody(response), getCharset(response));   
  36.   
  37.        case SERVER_ERROR:   
  38.   
  39.            if (HttpStatus.INTERNAL_SERVER_ERROR.equals(statusCode)) {   
  40.   
  41.               // 后台rest异常   
  42.   
  43.               HttpHeaders headers = response.getHeaders();   
  44.   
  45.               List<String> codes = headers.get(“Error-Code”);   
  46.   
  47.               List<String> msgs = headers.get(“Error-Message”);   
  48.   
  49.               String code = null, msg = null;   
  50.   
  51.               if (codes != null && codes.size() > 0 && msgs != null  
  52.   
  53.                      && msgs.size() > 0) {   
  54.   
  55.                   code = codes.get(0);   
  56.   
  57.                   msg = msgs.get(0);   
  58.   
  59.               }   
  60.   
  61.               throw new MyException(code, new Object[] { msg });   
  62.   
  63.            } else {   
  64.   
  65.               throw new HttpServerErrorException(statusCode,   
  66.   
  67.                      response.getStatusText(), response.getHeaders(),   
  68.   
  69.                      getResponseBody(response), getCharset(response));   
  70.   
  71.            }   
  72.   
  73.        default:   
  74.   
  75.            throw new RestClientException(“Unknown status code [“ + statusCode   
  76.   
  77.                   + “]”);   
  78.   
  79.        }   
  80.   
  81.     }   
  82.   
  83.     protected boolean hasError(HttpStatus statusCode) {   
  84.   
  85.        return (statusCode.series() == HttpStatus.Series.CLIENT_ERROR || statusCode   
  86.   
  87.               .series() == HttpStatus.Series.SERVER_ERROR);   
  88.   
  89.     }   
  90.   
  91.     private HttpStatus getHttpStatusCode(ClientHttpResponse response)   
  92.   
  93.            throws IOException {   
  94.   
  95.        HttpStatus statusCode;   
  96.   
  97.        try {   
  98.   
  99.            statusCode = response.getStatusCode();   
  100.   
  101.        } catch (IllegalArgumentException ex) {   
  102.   
  103.            throw new UnknownHttpStatusCodeException(   
  104.   
  105.                   response.getRawStatusCode(), response.getStatusText(),   
  106.   
  107.                   response.getHeaders(), getResponseBody(response),   
  108.   
  109.                   getCharset(response));   
  110.   
  111.        }   
  112.   
  113.        return statusCode;   
  114.   
  115.     }   
  116.   
  117.     private byte[] getResponseBody(ClientHttpResponse response) {   
  118.   
  119.        try {   
  120.   
  121.            InputStream responseBody = response.getBody();   
  122.   
  123.            if (responseBody != null) {   
  124.   
  125.               return FileCopyUtils.copyToByteArray(responseBody);   
  126.   
  127.            }   
  128.   
  129.        } catch (IOException ex) {   
  130.   
  131.            // ignore   
  132.   
  133.        }   
  134.   
  135.        return new byte[0];   
  136.   
  137.     }   
  138.   
  139.     private Charset getCharset(ClientHttpResponse response) {   
  140.   
  141.        HttpHeaders headers = response.getHeaders();   
  142.   
  143.        MediaType contentType = headers.getContentType();   
  144.   
  145.        return contentType != null ? contentType.getCharSet() : null;   
  146.   
  147.     }   
  148.   
  149. }  

applicationContext.xml配置文件如下:

  1. <bean id=“errorHandler” class=“com.xxx.handler.My ResponseErrorHandler” />   
  2.   
  3.   <bean id=“restTemplate” class=“org.springframework.web.client.RestTemplate”>   
  4.   
  5.      <property name=“errorHandler” ref=“ errorHandler ” />   
  6.   
  7.   </bean>  

五、  拦截器链的不同阶段

《Apache CXF拦截器(Interceptor)的使用》

 

incoming chains包含以下几个阶段:

Phase

Functions

RECEIVE

Transport level processing

(PRE/USER/POST)_STREAM

Stream level processing/transformations

READ

This is where header reading typically occurs.

(PRE/USER/POST)_PROTOCOL

Protocol processing, such as JAX-WS SOAP handlers

UNMARSHAL

Unmarshalling of the request

(PRE/USER/POST)_LOGICAL

Processing of the umarshalled request

PRE_INVOKE

Pre invocation actions

INVOKE

Invocation of the service

POST_INVOKE

Invocation of the outgoing chain if there is one

 

outgoing chain包含以下阶段:

Phase

Functions

SETUP

Any set up for the following phases

(PRE/USER/POST)_LOGICAL

Processing of objects about to marshalled

PREPARE_SEND

Opening of the 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

通过Phase可以定义拦截器在哪个阶段生效。

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>