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的方式有下面几种:
编程方式,使用handlerResolver。
使用Annotation javax.ws.HandlerChain来指向配置文件。
从WSDL生成。
使用custom binding声明HandlerChain。
在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
JAX-WS使用Handler Chain加工消息的更多相关文章
- Android ------ handler 异步处理消息
Handler基本概念: Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出,然后对消息进行出来,就是发 ...
- [转]Handler MessageQueue Looper消息循环原理分析
Handler MessageQueue Looper消息循环原理分析 Handler概述 Handler在Android开发中非常重要,最常见的使用场景就是在子线程需要更新UI,用Handler ...
- (原)Android在子线程用handler发送的消息,主线程是怎么loop到的?
来自知乎:https://www.zhihu.com/question/48130951?sort=created 大家都知道Android的Looper是ThreadLocal方式实现,每个线程 ...
- android handler ,message消息发送方式
1.Message msg = Message.obtain(mainHandler) msg.obj=obj;//添加你需要附加上去的内容 msg.what = what;//what消息处理的类 ...
- Android Handler、Lopper消息驱动机制
Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例(MesageQueue),应用程序的主线程不断地从这个消息队例中获取消息(Mesage),然后对这些消息进行处理(Han ...
- Handler没法取出消息队列中的数据的一个原因
主线程发送消息到工作线程,工作线程的步骤是固定为3步的. Looper.prepare();//步骤1,线程里使用handler必须这样写, handler = new Handler(){//步骤2 ...
- Android为TV端助力 handler ,message消息发送方式
1.Message msg = Message.obtain(mainHandler) msg.obj=obj;//添加你需要附加上去的内容 msg.what = what;//what消息处理的类 ...
- Android开发 ---多线程操作:Handler对象,消息队列,异步任务下载
效果图: 1.activity_main.xml 描述:定义了六个按钮 <?xml version="1.0" encoding="utf-8"?> ...
- Android Handler类 发送消息-post()和postDelay(), Looper讲解
https://blog.csdn.net/weixin_41101173/article/details/79701832 首先,post和postDelay都是Handler的方法,用以在子线程中 ...
随机推荐
- js执行环境的深入理解
第一个例子中 :之所以每个函数都返回不同的值的原因 有2点 (简写如下文) 就是[SCOPE]内部属性,函数可能拥有相同的父作用域时,多个函数引用同一个[SCOPE]属性,所以return i的值还是 ...
- Java线程新特征——Java并发库
一.线程池 Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定 ...
- Mysql复合索引
当Mysql使用索引字段作为条件时,如果该索引是复合索引,必须使用该索引中的第一个字段作为条件才能保证系统使用该索引,否则该索引不会被使用,并且应尽可能地让索引顺序和字段顺序一致
- 【笔记】科普createDocumentFragment() 创建文档碎片节点
上一篇文章说到了动态添加文本节点的方法那如果我们要添加多个文本节点或者元素节点呢? 大家可能会想到用循环然后逐个逐个添加 但是别忘了js 还提供了创建一个文本碎片的方法 createDocumentF ...
- mysql中使用 where 1=1和 0=1 的作用
操作mysql的时候,经常使用where语句进行查询.当where语句不存在的时候,经常在后面加一个where 1=1 where 1=1; 这个条件始终为True,在不定数量查询条件情况下,1=1可 ...
- QT 网络编程
#include "networkinformation.h" #include "ui_networkinformation.h" networkinform ...
- Lucene热词统计
1.建立搜索表 ID KeyWords DT 搜索一次保存一次,id才用guid提高效率 /// <summary> /// 搜索数据 /// </summary> /// & ...
- [已解决] No syntax specified for the proto file : xxx.proto
在使用protobuf生成相应类文件如java文件的时候需要指定proto的版本, 如: syntax = "proto2"; package my_package; messag ...
- angularJS中directive与directive 之间的通信
上一篇讲了directive与controller之间的通信:但是我们directive与directive之间的通信呢? 当我们两个directive嵌套使用的时候怎么保证子directive不会被 ...
- mysql基本语句
mysql -u root -p; 登录数据库 show databases; 展示数据库 show tables; 展示表 desc messages; 查看messages表的结构 drop da ...