通过Handler添加HEADER

本文介绍SOAPHandler在客户端和服务端的应用,包括如何通过Handler处理SOAPMessage,实现消息的预处理及故障处理。同时展示了如何配置handler-chain.xml文件以及通过示例演示了如何验证头部信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[b]
LogicHandler 只能获取SOAPBody的信息

SOAPHandler 可以获取SOAPMessage的信息

可以使用多个Handler,但是最终执行顺序:
客户端:LogicHandler ---> SOAPHandler
服务端:SOAPHandler ---> LogicHandler
[/b]

[b]Handler的使用步骤[/b]
[size=medium]
1.定义一个类实现SOAPHandler并指定泛型:SOAPMessageContext
2.实现接口中的方法,在handleMessage(SOAPMessageContext context)中编写代码
3.配置handler-chain.xml
4.在客户端的服务实现类上使用@HandlerChain(file="handler-chain.xml")声明配置[/size]

package com.hqh.soap.handler;

import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
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;

public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {

/**
* 客户端与服务端都会先执行本方法处理消息,再发送消息
*/
@Override
public boolean handleMessage(SOAPMessageContext context) {
//在发送soap消息的时候,加入头信息
try {
//判断消息是发送还是接收:true 往外推送 false 接收数据
Boolean outbound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(outbound) {
SOAPMessage message = context.getMessage();
//判断message中是否存在header
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
if(header==null) {
header = envelope.addHeader();
}
String ns = "http://soap.hqh.com/";
QName qName = new QName(ns, "license", "nn");
header.addHeaderElement(qName).setValue("abc123");
}
} catch (SOAPException e) {
e.printStackTrace();
} finally {

}
return true;
}
/**
* 出现异常本方法执行
*/
@Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("error!");
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;
}

}




[b]handler-chain.xml[/b]

<?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>com.hqh.soap.handler.HeaderHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>



/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.1.6 in JDK 6
* Generated source version: 2.1
*
*/
@WebServiceClient(name = "MyServiceImplService", targetNamespace = "http://soap.hqh.com/", wsdlLocation = "http://localhost:8888/ms?wsdl")
@HandlerChain(file="handler-chain.xml")
public class MyServiceImplService
extends Service
{
...
}


[b]通过TCP/IP Monitor查看交互的信息[/b]
[color=blue]
window-preference-Run/Debug-TCP/IP Monitor-add
local monitor port:8889 发送方端口
host name:localhost
port:8888 服务端的端口
type:tcp/ip
start monitor!
[/color]


package com.hqh.soap.test;

import static org.junit.Assert.*;

import java.net.URL;

import javax.xml.namespace.QName;

import org.junit.Test;

import com.hqh.soap.IMyService;
import com.hqh.soap.MyServiceImplService;
import com.hqh.soap.UserException_Exception;

public class TestHandlerChain {

@Test
public void test() throws Exception {
URL url = new URL("http://localhost:8889/ms?wsdl");
QName qname = new QName("http://soap.hqh.com/", "MyServiceImplService");
MyServiceImplService serviceImpl = new MyServiceImplService(url,qname);
IMyService service = serviceImpl.getMyServiceImplPort();
try {
service.login("admin", "admin");
} catch (UserException_Exception e) {
System.out.println("出错了:"+e.getMessage());
}
}

}



[b]通过tcpM可以看到发送的消息已经添加了header头信息:[/b]

<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<nn:license xmlns:nn="http://soap.hqh.com/">abc123</nn:license>
</S:Header>
<S:Body>
<ns2:login xmlns:ns2="http://soap.hqh.com/">
<username xmlns="">admin</username>
<pwd xmlns="">admin</pwd>
</ns2:login>
</S:Body>
</S:Envelope>



[b]服务端获取头消息中的内容[/b]
1.在服务端编写Handler,通过Handler截取消息
2.在服务端显示定义一个参数来获取信息(基于契约优先的方法使用webservice)


[b]客户端和服务端都使用Handler对消息进行加工和处理[/b]

package com.hqh.soap.handler;

import java.io.IOException;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
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;

/**
* 客户端
* 通过调用的方法名决定是否加入license信息
*/
public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {

/**
* 客户端与服务端都会先执行本方法处理消息,再发送消息
*/
@Override
public boolean handleMessage(SOAPMessageContext context) {
//在发送soap消息的时候,加入头信息
try {
//判断消息是发送还是接收:true 往外推送 false 接收数据
Boolean outbound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
//出
if(outbound) {
SOAPMessage message = context.getMessage();
//判断message中是否存在header
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();
//如果调用服务端的login方法,则在header中加入license信息
if("login".equals(body.getChildNodes().item(0).getLocalName())) {
if(header==null) {
header = envelope.addHeader();
}
String ns = "http://soap.hqh.com/";
QName qName = new QName(ns, "license", "nn");
header.addHeaderElement(qName).setValue("FGEWRWE34654GFG");
}
//将消息打印到控制台
message.writeTo(System.out);
}

} catch (SOAPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {

}
return true;
}
/**
* 出现异常本方法执行
*/
@Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("error!");
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;
}

}



[b]服务端添加配置文件[/b]

<?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>com.hqh.soap.handler.LicenseHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>


[b]服务端的实现类上声明handler[/b]

package com.hqh.soap;

import java.util.ArrayList;
import java.util.List;

import javax.jws.HandlerChain;
import javax.jws.WebService;

@WebService(endpointInterface="com.hqh.soap.IMyService")
@HandlerChain(file="handler-chain.xml")//声明handler配置文件
public class MyServiceImpl implements IMyService {

private static List<User> users = new ArrayList<User>();

public MyServiceImpl() {
users.add(new User(1,"admin","admin"));
}

@Override
public int add(int a, int b) {
System.out.println("MyServiceImpl.add()");
return a+b;
}

@Override
public User addUser(User user) {
users.add(user);
return user;
}

@Override
public User login(String username, String pwd) throws UserException {
System.out.println("MyServiceImpl.login()");
for(User user:users) {
if(username.equals(user.getName()) && pwd.equals(user.getPwd()))
return user;
}
//这里抛出的异常类型如果与接口中声明的异常类型一致,那么服务端将不抛出此异常,而是直接通过soap message将异常传递到客户端
throw new UserException("用户不存在");
//抛出运行时异常与接口声明的异常不同,服务端会自己抛出异常,客户端也能接收到异常信息
// throw new RuntimeException("用户不存在");
}

@Override
public List<User> list(String authInfo) {
System.out.println(authInfo);
return users;
}

}





package com.hqh.soap.handler;

import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
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;
/**
* 服务器端
* 根据当前调用服务的方法名确定是否需要对license进行验证
*/
public class LicenseHandler implements SOAPHandler<SOAPMessageContext> {

@Override
public boolean handleMessage(SOAPMessageContext context) {
try {
Boolean outbound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
//入
if(!outbound) {
SOAPMessage message = context.getMessage();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();
Node methodNode = body.getChildNodes().item(0);
//获取访问服务的方法名
String method = methodNode.getLocalName();
//不是login方法就不进行license的验证
if(!"login".equals(method)) {
return true;
}
if(header==null || header.getFirstChild()==null) {
SOAPFault fault = body.addFault();
fault.setFaultString("license为空,验证不通过!");
throw new SOAPFaultException(fault);
}
NodeList nodeList = header.getElementsByTagName("nn:license");
Node node = nodeList.item(0);
//node =header.getChildNodes().item(0);
System.out.println("客户端带过来的license:"+node.getTextContent());
}
} catch (SOAPException e) {
e.printStackTrace();
}
return true;
}

@Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("server error!");
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;
}

}




package com.hqh.soap.test;

import static org.junit.Assert.*;

import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.soap.SOAPFaultException;

import org.junit.Test;

import com.hqh.soap.IMyService;
import com.hqh.soap.MyServiceImplService;
import com.hqh.soap.User;
import com.hqh.soap.UserException_Exception;

public class TestHandlerChain {

@Test
public void test() throws Exception {
URL url = new URL("http://localhost:8889/ms?wsdl");
QName qname = new QName("http://soap.hqh.com/", "MyServiceImplService");
MyServiceImplService serviceImpl = new MyServiceImplService(url,qname);
IMyService service = serviceImpl.getMyServiceImplPort();
try {
//调用服务端的login()需要在header中加入license
User user = service.login("admin", "admin");
System.out.println();
System.out.println("user id:"+user.getId());

//调用服务端的其它方法不需要加license到header中
long result = service.add(1, 1);
System.out.println();
System.out.println(result);

} catch (UserException_Exception e) {
System.out.println("出错了:"+e.getMessage());
} catch (SOAPFaultException e) {
System.out.println(e.getMessage());
}
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值