JAX-WS使用Handler Chain加工消息

承前

本文的示例,是基於前一篇文章中的實例而改進的,若是想要運行本文的代碼例子,須要先實現前一篇的代碼。java

前一篇文章JAX-WS開發WebService初級 編程

Handler概念

在WebService目錄下的上一篇文章中,給出來一個初級的WebService開發實例。接下來的幾篇文章,將一步一步更加深刻的討論JAXWS中的各類特性。當咱們瞭解JAXWS全部特性之時,就能夠對WebService的開發瞭如指掌了。maven

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。spa

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

  3. 從WSDL生成。code

  4. 使用custom binding聲明HandlerChain。server

  5. 在sun-jaxws.xml中聲明。
    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,查看控制檯的輸出。

相關文章
相關標籤/搜索