zoukankan      html  css  js  c++  java
  • JAX-WS使用Handler Chain加工消息

    承前

    本文的示例,是基于前一篇文章中的实例而改进的,如果想要运行本文的代码例子,需要先实现前一篇的代码。

    前一篇文章JAX-WS开发WebService初级 

    Handler概念

    在WebService目录下的上一篇文章中,给出来一个初级的WebService开发实例。接下来的几篇文章,将一步一步更加深入的讨论JAXWS中的各种特性。当我们了解JAXWS所有特性之时,就可以对WebService的开发了如指掌了。

    Servlet肯定无人不知晓,在servlet中,存在着FilterChain。FilterChain由一串的Filter顺序排列组建而成,Filter可以在Resquest到达servlet之前,和Response离开servlet之后处理一些逻辑。在WebService中,我们可以使用Handler Chain。

    在JAXWS下,存在两个Handler接口,LogicalHandler和SOAPHandler. LogicalHandler处理的是Message Payload, 而SOAPHandler则处理的是整个SOAP消息。注册Handler的方式有下面几种:

    1. 编程方式,使用handlerResolver。

    2. 使用Annotation javax.ws.HandlerChain来指向配置文件。

    3. 从WSDL生成。

    4. 使用custom binding声明HandlerChain。

    5. 在sun-jaxws.xml中声明。

    执行顺序

    像Servlet Filter一样,如果依次声明了H1,H2,H3,H4几个Handler,那么,对于进站的Message,则依次通过H1,H2,H3,H4,然后到Endpoint。对于出站的消息,则依次通过H4,H3,H2,H1. 所以,整个消息经过的路径应该是H1,H2,H3,H4,Endpoint,H4,H3,H2,H1.

    如果同时声明了LogicalHandler和SOAPHandler,LogicalHandler要优先于SOAPHandler。LogicalHandler将提前。

    每个Handler都有两个方法:handleMessage和handleFault. 它们的作用如下:

    对于正常的message,在经过handlerchain的时候,会依次调用每个handler的handleMessage方法。

    当在Endpoint执行之前,如果handleMessage返回false,则不再向后执行,返回message. 如果抛出异常,后面的handler则执行handleFault方法。如果handleFault返回true,则继续执行后面的handleFault。如果返回为false,则不再执行后面的handler,直接返回FaultMessage。

    当在Endpoint执行完毕以后,如果handleMessage返回false,message方向调头,继续执行后面的Handler。如果抛出异常,后面的handler则执行handleFault方法。如果handleFault返回true,则继续执行后面的handleFault。如果返回为false,则不再执行后面的handler,直接返回FaultMessage。

    LogicalHander

    此Handler处理的是Message Payload,对author为空的均改为“xpbug”。

    在上一篇文章,我们介绍了wsimport工具。wsimport可以根据wsdl文件生成相应的java文件。下面的handler也需要使用这些java类。下面用到的wsimport所生成的java类为ObjectFactory和AddRawBook.

    public class AuthorHandler implements LogicalHandler<LogicalMessageContext> {
    
        public boolean handleMessage(LogicalMessageContext context) {
            boolean outBound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            //判断是出站消息还是进站消息。只对出站消息做修改
            if (outBound) {
                LogicalMessage message = context.getMessage();
                JAXBContext jaxbc=null;
                try {
                    //ObjectFactory为wsimport根据wsdl所生成。
                    jaxbc = JAXBContext.newInstance(ObjectFactory.class);
                    Object obj = ((JAXBElement)message.getPayload(jaxbc)).getValue();
                    //载体是不是AddRawBook
                    //AddRawBook为wsimport根据wsdl所生成。
                    if (obj instanceof AddRawBook) {
                        AddRawBook book = (AddRawBook) obj;
                        if ("".equals(book.getAuthor())) {
                            book.setAuthor("xpbug");
                            message.setPayload(new ObjectFactory().createAddRawBook(book), jaxbc);
                        }
                    }
                } catch (JAXBException e) {
                    e.printStackTrace();
                }
            }
            return true;
        }
    
        public boolean handleFault(LogicalMessageContext context) {
            // TODO Auto-generated method stub
            return false;
        }
    
        public void close(MessageContext context) {
            // TODO Auto-generated method stub
        }
    }

    SOAPHandler

    SOAPHandler处理的是SOAP整个消息,包含soap header和soap body。一般可以使用SOAPHandler来处理header,比如加入一些header。本文将实现一个handler,打印所有进出的soap message全文。

    public class LoggerHandler implements SOAPHandler<SOAPMessageContext> {
    
        public boolean handleMessage(SOAPMessageContext context) {
            boolean outBound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            if (outBound) {
                System.out.println("<<<<<<<<<<<<<<<<");
                System.out.println("Message out:");
            } else {
                System.out.println(">>>>>>>>>>>>>>>>");
                System.out.println("Message in:");
            }
            try {
                context.getMessage().writeTo(System.out);
            } catch (SOAPException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("");
            return true;
        }
    
        public boolean handleFault(SOAPMessageContext context) {
            // TODO Auto-generated method stub
            return false;
        }
    
        public void close(MessageContext context) {
            // TODO Auto-generated method stub
            
        }
    
        public Set<QName> getHeaders() {
            return null;
        }
    
    }

    配置Handlers

    handler可以安装在server端,也可以安装在客户端。为了不改动server,我只修改客户端。

    首先,书写handlers的配置文件,在maven project中,在main/resources/下面创建handler-chain.xml

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <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>com.mycompany.library.AuthorHandler</javaee:handler-class>
        </javaee:handler>
        <javaee:handler>
          <javaee:handler-class>com.mycompany.library.LoggerHandler</javaee:handler-class>
        </javaee:handler>
      </javaee:handler-chain>
    </javaee:handler-chains>

    然后,修改LibraryService.java,此文件是由wsimport产生的。将hander配置文件注册在Webservice client上。

    @WebServiceClient(name = "LibraryService", targetNamespace = "http://library.mycompany.com", wsdlLocation = "http://127.0.0.1:8080/library/service?wsdl")
    @HandlerChain(file="handler-chain.xml")
    public class LibraryService 

    运行客户端

    修改App.java的main函数

    public class App {
        public static void main( String[] args ) throws LibraryException_Exception {
            
            int id;
            String rawBook;
            id = createPort().addRawBook("java", "");
            rawBook = createPort().getRawBook(id);
            System.out.println("find"+rawBook);
        }
        
        public static Library createPort() {
            Library port = new LibraryService().getLibraryPort();
            return port;
        }
    }

    运行App,查看控制台的输出。

    参考链接:https://my.oschina.net/xpbug/blog/227204

  • 相关阅读:
    easy ui 常用控件配置
    oracel 查询语句
    .Net 取树形结构的数据
    Asp.Net Core File的操作
    js 页面技巧
    ASP.NET Core 文件上传
    ASP.NET EF实体主外键关系
    ASP.NET MVC 后台传值前端乱码解决方案 富文本Ueditor编辑
    手机访问网站自动跳转到手机版
    Ecshop布局参考图
  • 原文地址:https://www.cnblogs.com/springlight/p/6232998.html
Copyright © 2011-2022 走看看