概述


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注解,进行测试:

 

SOAP Handler的更多相关文章

  1. A little bit about Handlers in JAX-WS

    by Rama Pulavarthi Handlers are message interceptors that can be easily plugged in to the JAX-WS run ...

  2. CXF之五 拦截器Interceptor

    拦截器(Interceptor)是CXF功能最主要的扩展点,可以在不对核心模块进行修改的情况下,动态添加很多功能.拦截器和JAX-WS Handler.Filter的功能类似,当服务被调用时,就会创建 ...

  3. WebService--jax

    使用javax.jws编写webservice服务: 服务端: 1,定义webservice接口: package com.jws.serviceInterface; import javax.jws ...

  4. 全国人口 信息(NCIIC)接口开发纪要

    阶段一:根据wsdl2java命令解析https://ws.nciic.org.cn/nciic_ws/services/NciicServices?wsdl以生成接口调用的对象类: wsdl2jav ...

  5. CXF实战之拦截器Interceptor(四)

    拦截器(Interceptor)是CXF功能最基本的扩展点,能够在不正确核心模块进行改动的情况下.动态加入非常多功能.拦截器和JAX-WS Handler.Filter的功能相似,当服务被调用时.就会 ...

  6. org.codehaus.xfire.fault.XFireFault: Could not read XML stream.. Nested exception is javax.xml.strea

    xfire使用中出现故障: 1. [2014-04-16 14:51:07.564]-[ERROR] org.apache.struts2.dispatcher.Dispatcher Exceptio ...

  7. Kali linux 2016.2(Rolling)中的Exploits模块详解

    简单来将,这个Exploits模块,就是针对不同的已知漏洞的利用程序. root@kali:~# msfconsole Unable to handle kernel NULL pointer der ...

  8. XFire客户端调用CXF服务端(四)

    前面章节:http://www.cnblogs.com/xiehongwei/p/8082337.html 已经开发出了CXF服务端,现在用XFire开发客户端调用CXF服务端,代码如下: impor ...

  9. salesforce 零基础学习(五十五)java通过SOAP方式定时访问某个文件然后插入到sObject中

    项目源码:https://github.com/zhangyueqidlmu/SOAP-Access-SFDC.git 项目背景:salesforce端相关数据需要其他系统提供,其他系统可以提供相关数 ...

随机推荐

  1. UVA 1648 Business Center

    https://vjudge.net/problem/UVA-1648 设上升x层,列个方程解出来,再把x带回去 #include<cmath> #include<cstdio> ...

  2. [USACO13FEB]出租车Taxi

    洛谷题目链接:[USACO13FEB]出租车Taxi 题目描述 Bessie is running a taxi service for the other cows on the farm. The ...

  3. 【设计模式】 模式PK:装饰模式VS适配器模式

    1.概述 装饰模式和适配器模式在通用类图上没有太多的相似点,差别比较大,但是它们的功能有相似的地方:都是包装作用,都是通过委托方式实现其功能.不同点是:装饰模式包装的是自己的兄弟类,隶属于同一个家族( ...

  4. linux时区修定转

    https://blog.csdn.net/feng12345zi/article/details/80348501

  5. 【51NOD-0】1081 子段求和

    [算法]树状数组(区间和) [题解]记得开long long #include<cstdio> #include<cstring> #include<algorithm& ...

  6. 01背包问题的延伸即变形 (dp)

    对于普通的01背包问题,如果修改限制条件的大小,让数据范围比较大的话,比如相比较重量而言,价值的范围比较小,我们可以试着修改dp的对象,之前的dp针对不同的重量限制计算最大的价值.这次用dp针对不同的 ...

  7. HDU 5117 Fluorescent

    题目链接:HDU-5117 题意为有n盏灯,m个开关,每个开关控制着\( k_{i} \)灯.X为最后亮着的灯的个数,要求出\( E(X^{3} ) * 2^{M} mod (10^9 + 7) \) ...

  8. JS函数和变量名称冲突

    在JS中如果函数名与变量名冲突,JS是怎么执行的? <script> console.log(sum);//function sum(){} function sum(){} var su ...

  9. [会装]Spark standalone 模式的安装

    1. 简介 以standalone模式安装spark集群bin运行demo. 2.环境和介质准备 2.1 下载spark介质,根据现有hadoop的版本选择下载,我目前的环境中的hadoop版本是2. ...

  10. [New learn] 设计模式思考

    本文是对上文[New learn] 设计模式的思考总结 1.大框架 无论应用使用多少种设计模式和技巧,此模式都是应用的大框架.下图为本项目的基本架构图: 1.上图中大框架为经典的MVC模式. 2.Co ...