SOAP处理程序是SOAP消息拦截器,它能够拦截传入或传出的SOAP消息并操纵其值。 例如,在客户端附加一个SOAP处理程序,它将为客户端发送的每个传出SOAP消息将客户端的计算机MAC地址注入SOAP标头块。 在服务器端,附加另一个SOAP处理程序,以从每个传入的SOAP消息中检索回SOAP标头块中的客户端MAC地址。 这样服务器端就可以确定允许哪台计算机访问已发布的服务。
本文分为三个部分:
- JAX-WS:服务器端的SOAP处理程序。 (本文)
- JAX-WS:客户端中的SOAP处理程序
- JAX-WS:针对客户端和服务器端的SOAP处理程序测试
服务器端的SOAP处理程序
在本文中,我们向您展示如何创建SOAP处理程序并将其附加到服务器端,以从每个传入的SOAP消息中检索SOAP标头块中的mac地址。 并进行验证以仅允许MAC地址为“ 90-4C-E5-44-B9-8F ”的计算机访问此发布的服务。 如果无效的客户端尝试访问服务,则将SOAPFaultException
返回给客户端。
本示例的目录结构
1. Web服务
一个简单的Web服务,带有getServerName()
方法以返回字符串。
文件:ServerInfo.java
package com.mkyong.ws;
import javax.jws.HandlerChain;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
public class ServerInfo{
@WebMethod
public String getServerName() {
return "mkyong server";
}
}
生成Web服务部署所需的Java文件。
D:\workspace-new\WebServices\bin>wsgen -keep -verbose -cp . com.mkyong.ws.ServerInfo
Note: ap round: 1
...
com\mkyong\ws\jaxws\GetServerName.java
com\mkyong\ws\jaxws\GetServerNameResponse.java
Note: ap round: 2
生成两个文件:
- com \ mkyong \ ws \ jaxws \ GetServerName.java
- com \ mkyong \ ws \ jaxws \ GetServerNameResponse.java
文件:GetServerName.java
package com.mkyong.ws.jaxws;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "getServerName", namespace = "http://ws.mkyong.com/")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getServerName", namespace = "http://ws.mkyong.com/")
public class GetServerName {
}
文件:GetServerNameResponse.java
package com.mkyong.ws.jaxws;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "getServerNameResponse", namespace = "http://ws.mkyong.com/")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getServerNameResponse", namespace = "http://ws.mkyong.com/")
public class GetServerNameResponse {
@XmlElement(name = "return", namespace = "")
private String _return;
/**
*
* @return
* returns String
*/
public String getReturn() {
return this._return;
}
/**
*
* @param _return
* the value for the _return property
*/
public void setReturn(String _return) {
this._return = _return;
}
}
2. SOAP处理程序
对于每个传入的SOAP消息,创建一个SOAP处理程序以检索SOAP标头块中的值。 有关代码说明,请参见注释。
文件MacAddressValidatorHandler.java
package com.mkyong.handler;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConstants;
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;
public class MacAddressValidatorHandler implements SOAPHandler<SOAPMessageContext>{
@Override
public boolean handleMessage(SOAPMessageContext context) {
System.out.println("Server : handleMessage()......");
Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
//for response message only, true for outbound messages, false for inbound
if(!isRequest){
try{
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader();
//if no header, add one
if (soapHeader == null){
soapHeader = soapEnv.addHeader();
//throw exception
generateSOAPErrMessage(soapMsg, "No SOAP header.");
}
//Get client mac address from SOAP header
Iterator it = soapHeader.extractHeaderElements(SOAPConstants.URI_SOAP_ACTOR_NEXT);
//if no header block for next actor found? throw exception
if (it == null || !it.hasNext()){
generateSOAPErrMessage(soapMsg, "No header block for next actor.");
}
//if no mac address found? throw exception
Node macNode = (Node) it.next();
String macValue = (macNode == null) ? null : macNode.getValue();
if (macValue == null){
generateSOAPErrMessage(soapMsg, "No mac address in header block.");
}
//if mac address is not match, throw exception
if(!macValue.equals("90-4C-E5-44-B9-8F")){
generateSOAPErrMessage(soapMsg, "Invalid mac address, access is denied.");
}
//tracking
soapMsg.writeTo(System.out);
}catch(SOAPException e){
System.err.println(e);
}catch(IOException e){
System.err.println(e);
}
}
//continue other handler chain
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("Server : handleFault()......");
return true;
}
@Override
public void close(MessageContext context) {
System.out.println("Server : close()......");
}
@Override
public Set<QName> getHeaders() {
System.out.println("Server : getHeaders()......");
return null;
}
private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
try {
SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
SOAPFault soapFault = soapBody.addFault();
soapFault.setFaultString(reason);
throw new SOAPFaultException(soapFault);
}
catch(SOAPException e) { }
}
}
3. SOAP处理程序XML文件
创建一个SOAP处理程序XML文件,然后放入SOAP处理程序声明。
文件: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.mkyong.handler.MacAddressValidatorHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
4.附加SOAP处理程序–> Web服务
要将上面的SOAP处理程序附加到Web服务ServerInfo.java
,只需使用@HandlerChain注释并在其中指定SOAP处理程序文件名即可。
文件:ServerInfo.java
package com.mkyong.ws;
import javax.jws.HandlerChain;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
@HandlerChain(file="handler-chain.xml")
public class ServerInfo{
@WebMethod
public String getServerName() {
return "mkyong server";
}
}
5. Web服务发布者
一个简单的Web服务发布者进行测试。
package com.mkyong.endpoint;
import javax.xml.ws.Endpoint;
import com.mkyong.ws.ServerInfo;
//Endpoint publisher
public class WsPublisher{
public static void main(String[] args) {
Endpoint.publish("http://localhost:8888/ws/server", new ServerInfo());
System.out.println("Service is published!");
}
}
完成后,请继续下一篇文章– 第2部分:JAX-WS –客户端中的SOAP处理程序 。
下载源代码
下载它– JAX-WS-Handler-Example.zip (21KB)
翻译自: https://mkyong.com/webservices/jax-ws/jax-ws-soap-handler-in-server-side/