拦截器(Interceptor)是CXF功能最主要的扩展点,可以在不对核心模块进行修改的情况下,动态添加很多功能。拦截器和JAX-WS Handler、Filter的功能类似,当服务被调用时,就会创建一个拦截器链(Interceptor Chain),拦截器链在服务输入(IN)或输出(OUT)阶段实现附加功能。
拦截器可以在客户端,也可以在服务端添加。当客户端发起一个WebService请求时,在客户端会创建输出拦截器链(outinterceptor),服务端接收到客户端的后,会创建输入拦截器链(ininterceptor)。当服务端返回响应消息时,响应消息会经过服务端的输出拦截链,客户端接收到服务端的响应时,会创建输入拦截器链,响应消息先经过输入拦截器链处理。拦截器在服务端和客户端的作用如图所示。
注:上图来源于网络。
下面,我们以一个Header认证为例,来演示CXF的拦截器的使用。
1、客户端拦截器
- public class ClientAuthorInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
-
- /**
- * 客户端申请的token信息
- */
- private String token;
-
- public ClientAuthorInterceptor(String token) {
- // 设置拦截器的时机,在发送请求到服务端之前进行拦截
- super(Phase.PREPARE_SEND);
- this.token = token;
- }
-
- @Override
- public void handleMessage(SoapMessage soap) throws Fault {
- // 在soap消息中添加认证头信息
- List<Header> headers = soap.getHeaders();
- Document doc = DOMUtils.createDocument();
- Element auth = doc.createElement(AuthorHeader.HEADER_NAME);
- Element token = doc.createElement(AuthorHeader.HEADER_TOKEN);
- token.setTextContent(this.token);
- auth.appendChild(token);
- Header header = new SoapHeader(new QName(AuthorHeader.HEADER_NAME), auth);
- headers.add(header);
- }
- }
注意:客户端是outinterceptor
2、服务端拦截器
下面,服务端对发送的消息进行拦截,并做认证
- @Slf4j
- @Component
- public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
-
- @Autowired
- private AuthorizationRepository repository;
-
- public AuthInterceptor() {
- super(Phase.USER_LOGICAL);
- }
-
- @Override
- public void handleMessage(SoapMessage message) throws Fault {
- Header header = message.getHeader(new QName("authrity"));
- if(null == header){
- log.warn("token没有认证通过!原因为:客户端请求中不存在认证的Header");
- throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中不存在认证的Header"));
- }
- Element ele = (Element) header.getObject();
- if(null == ele){
- log.warn("token没有认证通过!原因为:客户端请求中认证的Header无认证信息");
- throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中认证的Header无认证信息"));
- }
- Node node = ele.getFirstChild();
- if(null == node){
- log.warn("token没有认证通过!原因为:客户端请求中认证的Header无认证信息");
- throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中认证的Header无认证信息"));
- }
- String token = node.getTextContent();
- if(null == token || token.isEmpty()){
- log.warn("token没有认证通过!原因为:客户端请求中认证的Header无token信息");
- throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中认证的Header无token信息"));
- }
- Authorization auth = repository.findByToken(token);
- if(null == auth){
- log.warn("token没有认证通过!原因为:客户端请求中认证的token信息无效,请查看申请流程中的正确token信息");
- throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中认证的token信息无效,请查看申请流程中的正确token信息,流程申请地址:http://127.0.0.1:8080/email"));
- }
- log.info("客户端认证成功,token有效!");
- }
- }
注:服务端为ininterceptor
编写拦截器很简单,只需继承AbstractPhaseInterceptor类并实现handleMessage即可。
3、spring boot配置拦截器,并发布服务
- @Configuration
- public class WebserviceConfig {
- @Autowired
- private EmailService emailService;
-
- @Autowired
- private AuthInterceptor interceptor;
-
- @Autowired
- private ValidateInterceptor validateInterceptor;
-
- @Bean(name = Bus.DEFAULT_BUS_ID)
- public SpringBus springBus() {
- return new SpringBus();
- }
-
- /**
- * attention:
- * Details:发布WebService服务
- * @author chhliu
- * 创建时间:2017年5月22日 上午11:30:08
- * @return
- * Endpoint
- */
- @Bean
- public Endpoint endpoint() {
- EndpointImpl endPoint = new EndpointImpl(springBus(), emailService);
- endPoint.publish("/eamil");
- endPoint.getInInterceptors().add(interceptor); // 添加Header认证拦截器
- endPoint.getInInterceptors().add(validateInterceptor);// 添加消息格式校验拦截器
- return endPoint;
- }
- }
4、拦截器的Phase
Phase用来控制拦截器的工作时机,目前CXF支持的Phase如下:
- public static final String SETUP = "setup";// 设置阶段
- public static final String SETUP_ENDING = "setup-ending"; // 设置完之后
- public static final String PRE_LOGICAL = "pre-logical";// 程序对象编码
- public static final String PRE_LOGICAL_ENDING = "pre-logical-ending";
- public static final String USER_LOGICAL = "user-logical";
- public static final String USER_LOGICAL_ENDING = "user-logical-ending";
- public static final String POST_LOGICAL = "post-logical";
- public static final String POST_LOGICAL_ENDING = "post-logical-ending";
- public static final String PRE_MARSHAL = "pre-marshal";
- public static final String MARSHAL = "marshal";
- public static final String POST_MARSHAL = "post-marshal";
- public static final String MARSHAL_ENDING = "marshal-ending";
- public static final String PRE_PROTOCOL = "pre-protocol";
- public static final String PRE_PROTOCOL_FRONTEND = "pre-protocol-frontend";
- public static final String PRE_PROTOCOL_ENDING = "pre-protocol-ending";
- public static final String USER_PROTOCOL = "user-protocol";
- public static final String USER_PROTOCOL_ENDING = "user-protocol-ending";
- public static final String POST_PROTOCOL = "post-protocol";
- public static final String POST_PROTOCOL_ENDING = "post-protocol-ending";
- public static final String PREPARE_SEND = "prepare-send";
- public static final String PREPARE_SEND_ENDING = "prepare-send-ending";
- public static final String PRE_STREAM = "pre-stream";
- public static final String PRE_STREAM_ENDING = "pre-stream-ending";
- public static final String USER_STREAM = "user-stream";
- public static final String USER_STREAM_ENDING = "user-stream-ending";
- public static final String POST_STREAM = "post-stream";
- public static final String POST_STREAM_ENDING = "post-stream-ending";
- public static final String WRITE = "write";
- public static final String WRITE_ENDING = "write-ending";
- public static final String SEND = "send";
- public static final String SEND_ENDING = "send-ending";
-
- public static final String RECEIVE = "receive"; // 接收阶段,传输层处理
- public static final String READ = "read";// SOAPHeader读取
- public static final String PROTOCOL = "protocol";// 协议处理阶段,例如JAX-WS的Handler处理
- public static final String PRE_UNMARSHAL = "pre-unmarshal";// SOAP请求解码之前
- public static final String UNMARSHAL = "unmarshal";// SOAP请求解码阶段
- public static final String POST_UNMARSHAL = "post-unmarshal"; // SOAP请求解码之后
- public static final String PRE_INVOKE = "pre-invoke"; // 调用业务处理之前进入该阶段
- public static final String INVOKE = "invoke"; // 调用业务阶段
- public static final String POST_INVOKE = "post-invoke";// 业务调用之后
以下是ininterceptor定义的Phase
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 |
以下是outintercptor定义的Phase
On the outgoing chain there are the following phases:
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 | |
在SEND Phase后,有一堆以*_ENDING Phase以及与之对应的Phase,例如SEND和SEND_ENDING,这类以ENDING结尾的Phase允许清理和关闭与之对应的Phase打开或启动的任何资源。
通过上面的示例,可以发现,CXF的拦截器可以为我们实现很多的附加功能。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。