• 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)
    .....
  • 相关阅读:
    等级,
    JS高阶---回调函数
    JS高阶---函数
    JS高阶---对象
    JS高阶---数据、变量、内存
    JS高阶---简介+数据类型
    JS里==和===区别
    vue中assets和static的区别
    vue2.0 实现导航守卫(路由守卫)---登录验证
    exports与module.exports,export与export default 之间的关系和区别
  • 原文地址:https://www.cnblogs.com/Mrchengs/p/10575453.html
Copyright © 2020-2023  润新知