zoukankan      html  css  js  c++  java
  • SOAP Handler

    概述


    SOAP Handler是一个SOAP message的拦截器,它可以拦截进来或出去两个方向的SOAP message,修改并决定是否放行。

    例如:

    在服务端启用一个handler,拦截请求的message,检查是否包含指定的head参数;包含的放行,不包含的以异常作为响应。在客户端启用一个handler,拦截发出的请求message,向其中添加指定的head参数。
    其实现如下文。

    服务端


    文件分布图

    说明:这里使用了Maven的结构,将java文件和xml文件分别放置在src/main/java和src/main/resources两个源文件夹下。

    Handler

    创建一个handler拦截所有请求的message,尝试从head中获取用户信息;获取成功就放行,否则以抛出异常作为响应。
    handler需要实现javax.xml.ws.handler.soap.SOAPHandler接口。
    AccessHandler.java
    package cn.ljl.sand.jws.chapter4.service.handler;
    import java.util.Set;
    import javax.xml.namespace.QName;
    import javax.xml.soap.MessageFactory;
    import javax.xml.soap.SOAPBody;
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPFault;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.soap.SOAPHandler;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    import javax.xml.ws.soap.SOAPFaultException;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    public class AccessHandler implements SOAPHandler<SOAPMessageContext> {
        @Override
        public boolean handleMessage(SOAPMessageContext context) {
            Boolean out = (Boolean) context
                    .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            // true表示出的方向,即服务端返回的时候;false表示进的方向,即服务端接收请求参数的时候
            if (!out) {
                SOAPHeader header = null;
                
                try {
                    header = context.getMessage().getSOAPPart().getEnvelope().getHeader();
                } catch (SOAPException e) {
                    e.printStackTrace();
                    return false;
                }
                if (header == null) {
                    String tip = "缺少头部信息!";
                    SOAPFaultException exception = createFaultException(tip);
                    throw exception;
                } else if (!header.hasChildNodes()) {
                    String tip = "头部信息不能为空!";
                    SOAPFaultException exception = createFaultException(tip);
                    throw exception;
                } else {
                    NodeList nl = header.getElementsByTagNameNS(
                            "http://service.chapter4.jws.sand.ljl.cn/", "user");
                    if (nl.getLength() == 0) {
                        String tip = "头部信息中找不到用户信息!";
                        SOAPFaultException exception = createFaultException(tip);
                        throw exception;
                    }
                    Node node = nl.item(0);
                    String user = node.getTextContent();
                    System.out.println("请求的用户为:" + user);
                }
            }
            return true;
        }
        @Override
        public boolean handleFault(SOAPMessageContext context) {
            return false;
        }
        @Override
        public void close(MessageContext context) {
        }
        @Override
        public Set<QName> getHeaders() {
            return null;
        }
        /**
         * 根据消息创建异常.
         * 
         * @param message
         *            消息
         * @return
         */
        private SOAPFaultException createFaultException(String message) {
            SOAPFault fault = null;
            try {
                SOAPMessage smess = MessageFactory.newInstance().createMessage();
                SOAPBody body = smess.getSOAPPart().getEnvelope().getBody();
                fault = body.addFault();
                fault.setFaultString(message);
            } catch (SOAPException e) {
                e.printStackTrace();
                if (fault == null)
                    return null;
            }
            SOAPFaultException exception = new SOAPFaultException(fault);
            return exception;
        }
    }

    Handler配置文件

    Handler就是一个过滤器,配置文件可以将多个Handler组装成一个链,不同的配置文件可以不同的方式组装,如此就实现了代码的重用和灵活的装配。
    Handler配置文件是一个xml文件。
    handler-chains.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <javaee:handler-chain>
            <javaee:handler>
                <javaee:handler-class>
                    cn.ljl.sand.jws.chapter4.service.handler.AccessHandler
                </javaee:handler-class>
            </javaee:handler>
        </javaee:handler-chain>
    </javaee:handler-chains>

    服务接口

    定义web服务的接口,不需要任何参数,返回一个字符串作为成功的标志;能被服务接收的请求都是成功的。
    IAccessService.java
    package cn.ljl.sand.jws.chapter4.service;
    import javax.jws.WebResult;
    import javax.jws.WebService;
    @WebService
    public interface IAccessService {
        @WebResult(name = "accessResult")
        public String access();
    }

    服务实现类

    实现上面定义的接口,返回一个成功的字符串;使用@HandlerChain注解,指定Handler配置文件,此后请求该服务的消息将被配置文件中装配的过滤链过滤。
    AccessServiceImpl.java

     

    package cn.ljl.sand.jws.chapter4.service;
    import javax.jws.HandlerChain;
    import javax.jws.WebService;
    @WebService(endpointInterface = "cn.ljl.sand.jws.chapter4.service.IAccessService")
    @HandlerChain(file = "cn/ljl/sand/jws/chapter4/service/handler/handler-chains.xml")
    public class AccessServiceImpl implements IAccessService {
        @Override
        public String access() {
            String message = "你成功了!";
            return message;
        }
    }

     

    服务发布者

    定义一个类,发布服务。
    AccessServicePublisher.java
    package cn.ljl.sand.jws.chapter4.service;
    import javax.xml.ws.Endpoint;
    public class AccessServicePublisher {
        public static void main(String[] args) {
            String address = "http://localhost:6666/service/access";
            IAccessService service = new AccessServiceImpl();
            Endpoint.publish(address, service);
        }
    }

    发布服务

    运行AccessServicePublisher的main,发布服务,wsdl地址:http://localhost:6666/service/access?wsdl

    客户端


    文件分布图

    说明:src/main/java:cn.ljl.sand.jws.chapter4.client.wsimport中的文件,都是使用wsimport生成的,不做详细介绍。

    Handler

    创建一个Handler,拦截所有发出的请求message,往其中添加head参数,然后放行。
    UserHandler.java
    package cn.ljl.sand.jws.chapter4.client.handler;
    import java.util.Set;
    import javax.xml.namespace.QName;
    import javax.xml.soap.SOAPEnvelope;
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPFault;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.soap.SOAPHandler;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    public class UserHandler implements SOAPHandler<SOAPMessageContext> {
        @Override
        public boolean handleMessage(SOAPMessageContext context) {
            Boolean out = (Boolean) context
                    .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            // true表示出的方向,即发送请求到服务端
            if (out) {
                try {
                    SOAPEnvelope envelope = context.getMessage().getSOAPPart()
                            .getEnvelope();
                    SOAPHeader header = envelope.getHeader();
                    if (header == null)
                        header = envelope.addHeader();
                    QName hname = new QName(
                            "http://service.chapter4.jws.sand.ljl.cn/", "user");
                    header.addChildElement(hname).setTextContent("杨过");
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
            }
            return true;
        }
        @Override
        public boolean handleFault(SOAPMessageContext context) {
            SOAPFault fault = null;
            try {
                SOAPEnvelope envelope = context.getMessage().getSOAPPart()
                        .getEnvelope();
                fault = envelope.getBody().getFault();
            } catch (SOAPException e) {
                e.printStackTrace();
                return false;
            }
            System.out.println("在客户端Handler中:" + fault.getFaultString());
            return false;
        }
        @Override
        public void close(MessageContext context) {
            // TODO Auto-generated method stub
        }
        @Override
        public Set<QName> getHeaders() {
            // TODO Auto-generated method stub
            return null;
        }
    }

    Handler配置文件

    handler-chains.xml

    • <?xml version="1.0" encoding="UTF-8"?>
      <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <javaee:handler-chain>
              <javaee:handler>
                  <javaee:handler-class>
                      cn.ljl.sand.jws.chapter4.client.handler.UserHandler
                  </javaee:handler-class>
              </javaee:handler>
          </javaee:handler-chain>
      </javaee:handler-chains>

    使用wsimport生成代码

    指定-p cn.ljl.sand.jws.chapter4.client.wsimport
    修改生成AccessServiceImplService.java,为类添加注解:
    @HandlerChain(file = "cn/ljl/sand/jws/chapter4/client/handler/handler-chains.xml")

    客户端

    创建一个测试类,发起请求。
    WSIClient.java
    package cn.ljl.sand.jws.chapter4.client;
    import java.net.MalformedURLException;
    import java.net.URL;
    import org.junit.Assert;
    import org.junit.Test;
    import cn.ljl.sand.jws.chapter4.client.wsimport.AccessServiceImplService;
    import cn.ljl.sand.jws.chapter4.client.wsimport.IAccessService;
    public class WSIClient {
        /** wsdl的地址 */
        private static final String WSDL_URL = "http://localhost:6666/service/access?wsdl";
        @Test
        public void test() throws MalformedURLException {
            URL url = new URL(WSDL_URL);
            AccessServiceImplService ss = new AccessServiceImplService(url);
            IAccessService service = ss.getAccessServiceImplPort();
            String message = service.access();
            Assert.assertEquals("你成功了!", message);
        }
    }

    测试


    客户端不添加head参数

    AccessServiceImplService.java我们添加的注解去掉,进行测试:

    客户端添加head参数

    在AccessServiceImplService.java中添加@HandlerChain注解,进行测试:
     





  • 相关阅读:
    BAT带队烧钱圈地华为们猛追云计算
    各浏览器的cookie的name个数/最大容量限制测试
    多备份:云端数据物流平台为企业提供云备份服务(通过增值服务盈利,数据备份相当于买保险)
    多备份CEO胡茂华:创业路上的五道坎
    蜡笔同步:同步通讯录,同步短信,用电脑发短信
    MIUI是小米的核心竞争力
    tggg
    Ubuntu 创建启动器
    TProcedure,TMethod,TNotifyEvent,TWndMethod的区别,并模拟点击按钮后发生的动作
    所有语言的Awesome
  • 原文地址:https://www.cnblogs.com/ywjy/p/5196085.html
Copyright © 2011-2022 走看看