概述


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. Matlab 工具箱介绍

    Toolbox工具箱 序号 工具箱 备注 数学.统计与优化 1 Symbolic Math Toolbox 符号数学工具箱 2 Partial Differential Euqation Toolbo ...

  2. CF911E Stack Sorting

    洛谷题目链接:CF911E Stack Sorting Codeforces题目链接:Stack Sorting 题意翻译 给你一排列的一部分,让你补全整个排列使其字典序最大并且经过一个栈调整顺序之后 ...

  3. 【BZOJ2882】工艺 [SAM]

    工艺 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 小敏和小燕是一对好朋友. 他们正在玩一 ...

  4. 【BZOJ】1229 [USACO2008 Nov]toy 玩具

    [算法]三分+贪心 [题解] 数据范围小的版本:餐巾计划 这题不是使用最小费用流的下凸函数,因为这题是要满足最大流,那么这题到底在三分什么? 三分的这个函数,其实是总费用随卖出玩具量变化而变化的函数, ...

  5. Everything Has Changed(HDU6354+圆交+求周长)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6354 题目: 题意:用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长( ...

  6. 计蒜客 Goldbach Miller_Rabin判别法(大素数判别法)

    题目链接:https://nanti.jisuanke.com/t/25985 题目: Description: Goldbach's conjecture is one of the oldest ...

  7. KVM初始化过程

    转载:http://blog.csdn.net/dashulu/article/details/17074675 之前打算整理一下在Guest VM, KVM, QEMU中IO处理的整个流程,通过查阅 ...

  8. Linux 入门记录:十六、Linux 多命令协作:管道及重定向

    一.多命令协作 在 Linux 系统当中,大多数命令都很简单,很少出现复杂功能的命令,每个命令往往只实现一个或多个很简单的功能.通过将不同功能的命令组合一起使用,可以实现某个复杂功能的. Linux ...

  9. 【UOJ#9】vfk的数据

    我感觉这题可以出给新高一玩2333 #include<bits/stdc++.h> #define N 10005 using namespace std; string s[N]; in ...

  10. 2017多校第6场 HDU 6097 Mindis 计算几何,圆的反演

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6097 题意:有一个圆心在原点的圆,给定圆的半径,给定P.Q两点坐标(PO=QO,P.Q不在圆外),取圆 ...