我在 Jboss 4.2.3 上实现了 SOAP Web 服务。我想为该服务添加版本号检查。每当客户端调用时,我都会传递客户端版本号。我将在服务器上编写一个拦截器来检查客户端版本号。如果是不同版本号的客户端,我不会处理该请求。
我想知道的是,除了将版本号添加到 Web 服务方法签名中之外,是否有其他方法可以在某些上下文参数中从客户端传递版本号?
一般来说,如果我想将一些自定义元数据从客户端传递到服务器,我该怎么做?
最佳答案
<小时/>In general, if I want to pass some custom META-DATA from client to server, how do I do it ?
这可以通过SOAP Message Handlers来实现 Jax-WS 中的双方(客户端和服务器)。
客户端:
自定义元数据,如版本号、UUID、签名信息可以通过SOAP Headers添加.
1..编写一个VersionNumberHandler,如下所示。
public class VersionNumberHandler implements SOAPHandler<SOAPMessageContext> {
private static final String LoggerName = "ClientSideLogger";
private Logger logger;
private final boolean log_p = true; // set to false to turn off
public VersionNumberHandler() {
logger = Logger.getLogger(LoggerName);
}
public boolean handleMessage(SOAPMessageContext ctx) {
if (log_p)
logger.info("handleMessage");
// Is this an outbound message, i.e., a request?
Boolean request_p = (Boolean) ctx
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
// Manipulate the SOAP only if it's a request
if (request_p) {
// Get the Version Number from some property file ,
// to place in the message header.
String versionNumber = "v1.0";
try {
SOAPMessage msg = ctx.getMessage();
SOAPEnvelope env = msg.getSOAPPart().getEnvelope();
SOAPHeader hdr = env.getHeader();
// Ensure that the SOAP message has a header.
if (hdr == null)
hdr = env.addHeader();
QName qname = new QName("http://ticket.example.com/",
"versionnumber");
SOAPHeaderElement helem = hdr.addHeaderElement(qname);
// In SOAP 1.2, setting the actor is equivalent to
// setting the role.
helem.setActor(SOAPConstants.URI_SOAP_ACTOR_NEXT);
helem.setMustUnderstand(true);
helem.addTextNode(versionNumber);
msg.saveChanges();
// For tracking, write to standard output.
msg.writeTo(System.out);
} catch (SOAPException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
}
return true; // continue down the chain
}
public boolean handleFault(SOAPMessageContext ctx) {
if (log_p)
logger.info("handleFault");
try {
ctx.getMessage().writeTo(System.out);
} catch (SOAPException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
return true;
}
public Set<QName> getHeaders() {
if (log_p)
logger.info("getHeaders");
return null;
}
public void close(MessageContext messageContext) {
if (log_p)
logger.info("close");
}
2..在 Handler-Chain.xml 中提及此类。
<javaee:handler>
<javaee:handler-class>
com.example.client.handler.VersionNumberHandler
</javaee:handler-class>
</javaee:handler>
3..还在客户端( stub )中添加处理程序链。
@WebServiceClient(name = "TicketWSImplService", targetNamespace = "http://ticket.example.com/", wsdlLocation = "http://localhost:8080/ticket?wsdl")
@HandlerChain(file = "handler-chain.xml")
public class TicketWSImplService extends Service {
@WebMethod
public void method(){
}
在这里,我们添加了一个新的 header 元素“versionnumber”并且mustunderstand=true,这意味着服务器/中介必须处理该元素,否则Jax-WS-Runtime将向客户端抛出SOAP错误异常。现在我们需要在服务器端编写一个 validator (SOAP Handler)来验证客户端传递的版本号。
服务器端:
1..编写一个VersionNumberValidator,如下所示。
public class VersionNumberValidator implements SOAPHandler<SOAPMessageContext> {
@SuppressWarnings("unused")
@Override
public boolean handleMessage(SOAPMessageContext ctx) {
// Is this an inbound message, i.e., a request?
Boolean response_p = (Boolean) ctx
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
// Manipulate the SOAP only if it's incoming.
if (!response_p) {
try {
SOAPMessage msg = ctx.getMessage();
SOAPEnvelope env = msg.getSOAPPart().getEnvelope();
SOAPHeader hdr = env.getHeader();
// Ensure that the SOAP message has a header.
if (hdr == null) {
generateSOAPFault(msg, "No message header.");
return true;
}
Iterator mustUnderstandHeaders = msg.getSOAPHeader()
.examineMustUnderstandHeaderElements(
"http://schemas.xmlsoap.org/soap/actor/next");
String value = null;
while (mustUnderstandHeaders.hasNext()) {
Node next = (Node) mustUnderstandHeaders.next();
System.out.println("mustUnderstandHeaders name:"
+ next.getValue());
if (next.getNodeName().equalsIgnoreCase("versionnumber"))
value = next.getValue();
if (value != null && !value.equalsIgnoreCase("v1.0")) {
generateSOAPFault(msg, "Version Number Mismatch");
}
}
// For tracking, write to standard output.
msg.writeTo(System.out);
} catch (SOAPException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
}
return true; // continue down the chain
}
@Override
public boolean handleFault(SOAPMessageContext ctx) {
return true; // do continue down the chain
}
// For now, no-ops.
@Override
public Set<QName> getHeaders() {
Set<QName> headers = new HashSet<QName>();
QName qName = new QName("http://ticket.example.com/", "versionnumber");
headers.add(qName);
return headers;
}
@Override
public void close(MessageContext messageContext) {
}
private void generateSOAPFault(SOAPMessage msg, String reason) {
try {
SOAPBody body = msg.getSOAPBody();
SOAPFault fault = body.addFault();
QName fault_name = new QName(
SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE, "UltimateReceiver");
fault.setFaultCode(fault_name);
fault.setFaultRole("http://ticket.example.com/versionNumber_validator");
fault.addFaultReasonText(reason, Locale.US);
} catch (SOAPException e) {
}
}
2..在 Handler-Chain-server.xml 中提及此类。
<javaee:handler>
<javaee:handler-class>
com.example.client.handler.VersionNumberValidator
</javaee:handler-class>
</javaee:handler>
3..发布网络服务。
现在,每个客户端请求都会有“版本号=v1.0”,在服务器端,您将验证该值是否正确。如果不正确,将抛出 SOAPFaultException。
关于Java网络服务: User defined meta-data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22197593/