承前

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

前一篇文章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.

  1. public class AuthorHandler implements LogicalHandler<LogicalMessageContext> {
  2.  
  3. public boolean handleMessage(LogicalMessageContext context) {
  4. boolean outBound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  5. //判断是出站消息还是进站消息。只对出站消息做修改
  6. if (outBound) {
  7. LogicalMessage message = context.getMessage();
  8. JAXBContext jaxbc=null;
  9. try {
  10. //ObjectFactory为wsimport根据wsdl所生成。
  11. jaxbc = JAXBContext.newInstance(ObjectFactory.class);
  12. Object obj = ((JAXBElement)message.getPayload(jaxbc)).getValue();
  13. //载体是不是AddRawBook
  14. //AddRawBook为wsimport根据wsdl所生成。
  15. if (obj instanceof AddRawBook) {
  16. AddRawBook book = (AddRawBook) obj;
  17. if ("".equals(book.getAuthor())) {
  18. book.setAuthor("xpbug");
  19. message.setPayload(new ObjectFactory().createAddRawBook(book), jaxbc);
  20. }
  21. }
  22. } catch (JAXBException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. return true;
  27. }
  28.  
  29. public boolean handleFault(LogicalMessageContext context) {
  30. // TODO Auto-generated method stub
  31. return false;
  32. }
  33.  
  34. public void close(MessageContext context) {
  35. // TODO Auto-generated method stub
  36. }
  37. }

SOAPHandler

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

  1. public class LoggerHandler implements SOAPHandler<SOAPMessageContext> {
  2.  
  3. public boolean handleMessage(SOAPMessageContext context) {
  4. boolean outBound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  5. if (outBound) {
  6. System.out.println("<<<<<<<<<<<<<<<<");
  7. System.out.println("Message out:");
  8. } else {
  9. System.out.println(">>>>>>>>>>>>>>>>");
  10. System.out.println("Message in:");
  11. }
  12. try {
  13. context.getMessage().writeTo(System.out);
  14. } catch (SOAPException e) {
  15. e.printStackTrace();
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
  19. System.out.println("");
  20. return true;
  21. }
  22.  
  23. public boolean handleFault(SOAPMessageContext context) {
  24. // TODO Auto-generated method stub
  25. return false;
  26. }
  27.  
  28. public void close(MessageContext context) {
  29. // TODO Auto-generated method stub
  30.  
  31. }
  32.  
  33. public Set<QName> getHeaders() {
  34. return null;
  35. }
  36.  
  37. }

配置Handlers

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

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

  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <javaee:handler-chains
  3. xmlns:javaee="http://java.sun.com/xml/ns/javaee"
  4. xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  5. <javaee:handler-chain>
  6. <javaee:handler>
  7. <javaee:handler-class>com.mycompany.library.AuthorHandler</javaee:handler-class>
  8. </javaee:handler>
  9. <javaee:handler>
  10. <javaee:handler-class>com.mycompany.library.LoggerHandler</javaee:handler-class>
  11. </javaee:handler>
  12. </javaee:handler-chain>
  13. </javaee:handler-chains>

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

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

运行客户端

修改App.java的main函数

  1. public class App {
  2. public static void main( String[] args ) throws LibraryException_Exception {
  3.  
  4. int id;
  5. String rawBook;
  6. id = createPort().addRawBook("java", "");
  7. rawBook = createPort().getRawBook(id);
  8. System.out.println("find"+rawBook);
  9. }
  10.  
  11. public static Library createPort() {
  12. Library port = new LibraryService().getLibraryPort();
  13. return port;
  14. }
  15. }

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

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

JAX-WS使用Handler Chain加工消息的更多相关文章

  1. Android ------ handler 异步处理消息

    Handler基本概念: Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出,然后对消息进行出来,就是发 ...

  2. [转]Handler MessageQueue Looper消息循环原理分析

    Handler MessageQueue Looper消息循环原理分析   Handler概述 Handler在Android开发中非常重要,最常见的使用场景就是在子线程需要更新UI,用Handler ...

  3. (原)Android在子线程用handler发送的消息,主线程是怎么loop到的?

    来自知乎:https://www.zhihu.com/question/48130951?sort=created   大家都知道Android的Looper是ThreadLocal方式实现,每个线程 ...

  4. android handler ,message消息发送方式

    1.Message msg =  Message.obtain(mainHandler) msg.obj=obj;//添加你需要附加上去的内容 msg.what = what;//what消息处理的类 ...

  5. Android Handler、Lopper消息驱动机制

    Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例(MesageQueue),应用程序的主线程不断地从这个消息队例中获取消息(Mesage),然后对这些消息进行处理(Han ...

  6. Handler没法取出消息队列中的数据的一个原因

    主线程发送消息到工作线程,工作线程的步骤是固定为3步的. Looper.prepare();//步骤1,线程里使用handler必须这样写, handler = new Handler(){//步骤2 ...

  7. Android为TV端助力 handler ,message消息发送方式

    1.Message msg =  Message.obtain(mainHandler) msg.obj=obj;//添加你需要附加上去的内容 msg.what = what;//what消息处理的类 ...

  8. Android开发 ---多线程操作:Handler对象,消息队列,异步任务下载

    效果图: 1.activity_main.xml 描述:定义了六个按钮 <?xml version="1.0" encoding="utf-8"?> ...

  9. Android Handler类 发送消息-post()和postDelay(), Looper讲解

    https://blog.csdn.net/weixin_41101173/article/details/79701832 首先,post和postDelay都是Handler的方法,用以在子线程中 ...

随机推荐

  1. DIY PIXHAWK APM等飞控用的PPM转接板

    需要的硬件 一块arduino pro mini(推荐这个,比较小,当然如果你没有USB转转口的烧写工具买个ardunio nano板也是不错的,直接用USB线连接电脑就可以,用nano板要注意.它的 ...

  2. c/c++ qsort 函数 结构体简单使用(1)

    #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct student ...

  3. LinQ 组合查询与分页

    1.以开头查 public List<Car> Select1(string a){ return con.Car.Where(r => r.Name.StartsWith(a)). ...

  4. mysql count(*)和count(列)速率

    count(*)通常是对主键进行索引扫描,count(列)不一定 count(*)是统计表中所有符合的记录总数,count(列)是计算表中所有符合的列的记录数 count的时候,如果没有where限制 ...

  5. Struts2相关面试题

    Struts2面试题 1.struts2工作流程 Struts 2框架本身大致可以分为3个部分: 核心控制器FilterDispatcher.业务控制器Action和用户实现的企业业务逻辑组件. 核心 ...

  6. 【转】PowerShell入门(十):使用配置文件

    转至:http://www.cnblogs.com/ceachy/archive/2013/03/01/PowerShell_Profile.html 在命令行中定义别名.变量和函数,只是将它们添加在 ...

  7. python之haproxy配置文件操作(第三天)

    作业: 对haproxy配置文件进行操作 要求: 对haproxy配置文件中backend下的server实现增删改查的功能 一.这个程序有二个版本 1. python2.7版本见haproxy_py ...

  8. 笔记--mysql rpm 安装

    1.rpm包下载 http://taokey.blog.51cto.com/4633273/1630561

  9. JBOSS服务器的安装及配置

    1 安装jdk(jdk-1_5_0_05-windows-i586-p.exe)2 配置jdk环境 安装完成后还需要配置运行时环境:右键点击"我的电脑"->"属性& ...

  10. Linux-4.4-x86_64 内核配置选项简介【转】

    转自:http://fx114.net/qa-188-150553.aspx 本篇文章主要介绍了"Linux-4.4-x86_64 内核配置选项简介",主要涉及到Linux-4.4 ...