6、Web Service-拦截器

1、为什么CXF设置拦截器

为了在webservice请求过程中,能动态操作请求和响应数据, CXF设计了拦截器。拦截器分类

1.按所处的位置分:服务器端拦截器,客户端拦截器

2.按消息的方向分:入拦截器,出拦截器

3.按定义者分:系统拦截器,自定义拦截器

系统拦截器:

LoggingInInterceptor(系统日志入拦截器类)

LoggingOutInterceptor(系统日志出拦截器类)

 2、系统拦截器

 https://www.cnblogs.com/Mrchengs/p/10562458.html依旧是这里的服务端代码进行使用

1、服务端的拦截

在发布的main方法中:

package com.cr.server;

import java.util.List;

import javax.wsdl.Message;
import javax.xml.ws.Endpoint;

import org.apache.cxf.interceptor.Interceptor;import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;

import com.cr.service.impl.HelloServiceImpl;

import service1.DateTypeWsImpl;

//发布service
public class server {  
      public static void main(String[] args){
             
        String address = "http://localhost:8081/webserviceserver/helloService";
        Endpoint endpoint =  Endpoint.publish(address , new HelloServiceImpl());
        
        System.out.println(endpoint);
        EndpointImpl e = (EndpointImpl) endpoint;
        System.out.println(e);
        //服务端的日志入拦截器
        List<Interceptor<? extends org.apache.cxf.message.Message>> in = e.getInInterceptors();
        in.add(new LoggingInInterceptor());
        
        List<Interceptor<? extends org.apache.cxf.message.Message>> out = e.getOutInterceptors();
        out.add(new LoggingOutInterceptor());
        System.out.println();
        System.out.println("发布成功....");
    }
}

 

测试结果:

----------------------------
ID: 1
Address: http://localhost:8081/webserviceserver/helloService?wsdl
Http-Method: GET
Content-Type: 
Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Type=[null], Host=[localhost:8081], User-Agent=[Java/1.8.0_101]}
--------------------------------------
三月 21, 2019 9:33:01 下午 org.apache.cxf.services.HelloServiceImplService.HelloServiceImplPort.HelloService
信息: Inbound Message
----------------------------
ID: 2
Address: http://localhost:8081/webserviceserver/helloService?wsdl
Http-Method: GET
Content-Type: 
Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Type=[null], Host=[localhost:8081], User-Agent=[Java/1.8.0_101]}
--------------------------------------
三月 21, 2019 9:33:01 下午 org.apache.cxf.services.HelloServiceImplService.HelloServiceImplPort.HelloService
信息: Inbound Message
----------------------------
ID: 3
Address: http://localhost:8081/webserviceserver/helloService?wsdl=HelloService.wsdl
Http-Method: GET
Content-Type: 
Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Type=[null], Host=[localhost:8081], User-Agent=[Java/1.8.0_101]}
--------------------------------------
三月 21, 2019 9:33:02 下午 org.apache.cxf.services.HelloServiceImplService.HelloServiceImplPort.HelloService
信息: Inbound Message
----------------------------
ID: 4
Address: http://localhost:8081/webserviceserver/helloService?wsdl=HelloService.wsdl
Http-Method: GET
Content-Type: 
Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Type=[null], Host=[localhost:8081], User-Agent=[Java/1.8.0_101]}
--------------------------------------
三月 21, 2019 9:33:02 下午 org.apache.cxf.services.HelloServiceImplService.HelloServiceImplPort.HelloService
信息: Inbound Message
----------------------------
ID: 5
Address: http://localhost:8081/webserviceserver/helloService?wsdl=HelloService.wsdl
Http-Method: GET
Content-Type: 
Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Type=[null], Host=[localhost:8081], User-Agent=[Java/1.8.0_101]}
--------------------------------------
三月 21, 2019 9:33:11 下午 org.apache.cxf.services.HelloServiceImplService.HelloServiceImplPort.HelloService
信息: Inbound Message
----------------------------
ID: 6
Address: http://localhost:8081/webserviceserver/helloService
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[application/soap+xml, application/dime, multipart/related, text/*], Cache-Control=[no-cache], connection=[close], Content-Length=[330], content-type=[text/xml; charset=UTF-8], Host=[localhost:8081], Pragma=[no-cache], SOAPAction=[""], User-Agent=[IBM Web Services Explorer]}
Payload: <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://service.cr.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <q0:sayHello>
      <arg0>1</arg0>
    </q0:sayHello>
  </soapenv:Body>
</soapenv:Envelope>

--------------------------------------
webservice sercer...
name:1
三月 21, 2019 9:33:11 下午 org.apache.cxf.services.HelloServiceImplService.HelloServiceImplPort.HelloService
信息: Outbound Message
---------------------------
ID: 6
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://service.cr.com/"><return>hello:1</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------

 2、客户端的拦截

package cn.com.client;

import java.util.List;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.message.Message;

import com.cr.service.HelloService;
import com.cr.service.impl.HelloServiceImplService;

public class client {
     public static void main(String[] args){
        

        HelloServiceImplService factory = new HelloServiceImplService();
        HelloService hello = factory.getHelloServiceImplPort();
        
        //发送请求的客户端对象
        Client client = ClientProxy.getClient(hello);
        //添加日志出拦截器的集合
        List<Interceptor<? extends Message>> out =  client.getOutInterceptors();
        out.add(new LoggingOutInterceptor());
        
        //添加日志出拦截器的集合
        List<Interceptor<? extends Message>> in =  client.getInInterceptors();
        in.add(new LoggingInInterceptor());
        
        String res = hello.sayHello("mr");
        System.out.println("end:"+res);
    }

}
---------------------------
ID: 1
Address: http://localhost:8081/webserviceserver/helloService
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://service.cr.com/"><arg0>mr</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------
三月 21, 2019 9:59:28 下午 org.apache.cxf.services.HelloServiceImplService.HelloServiceImplPort.HelloService
信息: Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=utf-8
Headers: {content-type=[text/xml;charset=utf-8], Date=[Thu, 21 Mar 2019 13:59:28 GMT], Server=[Jetty(9.4.14.v20181114)], transfer-encoding=[chunked]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://service.cr.com/"><return>hello:mr</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------
end:hello:mr
首先是从客户端发送请求给服务器,先是发出请求给服务器被拦截(客户端出拦截器),服务器返回响应数据后又被客户端拦截器拦截(客户端入拦截器)
服务器接收到客户端请求后,该请求先是被拦截(服务器入拦截器),接着服务器接收请求并执行后,将数据发回给客户端又被拦截(服务器出拦截器)

 3、自定义拦截器

案例:使用自定义拦截器,实现用户名和密码的权限,即访问权限控制!

    需要的拦截器:客户端的出拦截器和服务器的入拦截器

说明:自定义拦截器都从AbstractPhaseIntercepter继承

问题:为什么客户端需要设置拦截器?

因为客户端拦截器能得到客户端的用户名和密码,并且将用户名和密码设置到请求头中

这样服务器接收请求时才能获取到用户名和密码,并且根据得到的用户名和密码来做出验证!

关于客户端的拦截器设置:

新建拦截类:

AddUserInterceptor.java 
package com.interceptor;

import java.util.List;

import javax.xml.namespace.QName;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.sun.org.apache.xml.internal.utils.DOMHelper;
import com.sun.xml.internal.ws.message.DOMHeader;


public class AddUserInterceptor extends AbstractPhaseInterceptor<SoapMessage> {


    private String name;
    private String pwd;
    
    //Phase.class可以查看相关的值
    public AddUserInterceptor(String name,String pwd) {
        super(Phase.PRE_PROTOCOL);//准备初始化拦截
        this.name=name;
        this.pwd=pwd;
    }
    
    /*
    <Envelope>
        <head>
            <cr>
                 <name>name</name>
                 <pwd>pwd</pwd>
             </cr>
        </head>
        <body>
          //...
        </body>
    </Envelope>
    
    
     */

    @Override
    public void handleMessage(SoapMessage msg) throws Fault {
        List<Header> header = msg.getHeaders();
        
        /*
         <head>
             <cr>
                 <name>name</name>
                 <pwd>pwd</pwd>
             </cr>
         </hean>
         */
        Document document = DOMHelper.createDocument();
        Element cr =  document.createElement("cr");//创建标签<cr></cr>
        Element name =  document.createElement("name");//创建标签<name></name>
        name.setTextContent(this.name);
        cr.appendChild(name);//将name加入到cr标签中

Element pwd
= document.createElement("pwd"); pwd.setTextContent(this.pwd); cr.appendChild(pwd);
     //设置《cr》标签的cr header.add(
new Header(new QName("cr"), cr)); System.out.println("clinet....."); } }

在客户端的使用

package cn.com.client;

import java.util.List;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.message.Message;

import com.cr.service.HelloService;
import com.cr.service.impl.HelloServiceImplService;
import com.interceptor.AddUserInterceptor;

public class client3 {
     public static void main(String[] args){
        
        HelloServiceImplService factory = new HelloServiceImplService();
        HelloService hello = factory.getHelloServiceImplPort();
        
        //发送请求的客户端对象
        Client client = ClientProxy.getClient(hello);
        //添加日志出拦截器的集合
        List<Interceptor<? extends Message>> out =  client.getOutInterceptors();
        out.add(new AddUserInterceptor("cr", "123"));

        String res = hello.sayHello("mr");
        System.out.println("end:"+res);
    }
}

关于服务器端的拦截类:

package interceptor;

import javax.xml.namespace.QName;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;

public class CheckUserInterceptor extends AbstractPhaseInterceptor<SoapMessage>{

    public CheckUserInterceptor() {
        super(Phase.PRE_PROTOCOL);//准备初始化拦截
    }

    @Override
    public void handleMessage(SoapMessage msg) throws Fault {
        
        Header header = msg.getHeader(new QName("cr"));
        if(header!=null){
            //取出数据
            Element e =(Element) header.getObject();
       //取出name标签的值 String name
= e.getElementsByTagName("name").item(0).getTextContent();
       //取出pwd标签的值 String pwd
= e.getElementsByTagName("pwd").item(0).getTextContent();
if("cr".equals(name) && "123".equals(pwd)){ System.out.println("用户密码正确..."); return; } //没有通过 System.out.println("不正确..."); throw new Fault(new RuntimeException("请求需要正确的账户....")); } } }

发布类中:

package com.cr.server;

import java.util.List;

import javax.wsdl.Message;
import javax.xml.ws.Endpoint;

import org.apache.cxf.interceptor.Interceptor;import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;

import com.cr.service.impl.HelloServiceImpl;

import interceptor.CheckUserInterceptor;
import service1.DateTypeWsImpl;

//发布service
public class server2 {  
      public static void main(String[] args){

        String address = "http://localhost:8081/webserviceserver/helloService";
        Endpoint endpoint =  Endpoint.publish(address , new HelloServiceImpl());
        
        System.out.println(endpoint);
        EndpointImpl e = (EndpointImpl) endpoint;
        System.out.println(e);
        //服务端的日志入拦截器
        List<Interceptor<? extends org.apache.cxf.message.Message>> in = e.getInInterceptors();
        in.add(new CheckUserInterceptor());
        
        System.out.println("发布成功....");     
    }
}

测试:正确的情况下:

客户端的打印:

三月 21, 2019 10:58:49 下午 org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
信息: Creating Service {http://impl.service.cr.com/}HelloServiceImplService from WSDL: file:/D:/myeclipse/MyEclipseProject/webservices_cxf_client/client.wsdl
clinet.....
end:hello:mr

服务端的打印;

用户密码正确...
webservice sercer...
name:mr

测试:错误的i情况下:

客户端的打印:

三月 21, 2019 10:59:55 下午 org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
信息: Creating Service {http://impl.service.cr.com/}HelloServiceImplService from WSDL: file:/D:/myeclipse/MyEclipseProject/webservices_cxf_client/client.wsdl
clinet.....
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: 请求需要正确的账户....
    at org.apache.cxf.jaxws.JaxWsClientProxy.mapException(JaxWsClientProxy.java:195)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:145)
    at com.sun.proxy.$Proxy35.sayHello(Unknown Source)
    at cn.com.client.client3.main(client3.java:29)
Caused by: org.apache.cxf.binding.soap.SoapFault: 请求需要正确的账户....

服务端的打印:

不正确...
三月 21, 2019 10:59:55 下午 org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
警告: Interceptor for {http://impl.service.cr.com/}HelloServiceImplService has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: 请求需要正确的账户....
    at interceptor.CheckUserInterceptor.handleMessage(CheckUserInterceptor.java:33)
    at interceptor.CheckUserInterceptor.handleMessage(CheckUserInterceptor.java:1)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267)
    at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:247)
    at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:79)
.....

猜你喜欢

转载自www.cnblogs.com/Mrchengs/p/10575453.html