我在Jboss 4.2.3上有一个SOAP Web服务实现。我想为服务添加版本号检查。每当客户端拨打电话时,我都会传递客户端版本号。我将在服务器上编写一个拦截器来检查客户端版本号。如果它是具有不同版本号的客户端,我将不会处理该请求。
我想知道的是,除了在Web服务方法签名中添加版本号之外,是否有其他方法可以从客户端传递版本号?
一般情况下,如果我想将一些自定义的META-DATA从客户端传递给服务器,我该怎么做?
答案 0 :(得分:1)
一般来说,如果我想从客户端传递一些自定义的META-DATA 服务器,我该怎么做?
这可以通过Jax-WS中的 SOAP Message Handlers 双方(客户端和服务器)来实现。
客户端:
可以通过SOAP Headers添加自定义元数据,例如版本号,UUID,签名信息。
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..Mention 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(){
}
这里,我们添加了一个新的头元素“versionnumber”和mustunderstand = true,这意味着服务器/中介必须处理这个元素,否则Jax-WS-Runtime会将SOAP Fault异常抛给客户端。现在我们需要在服务器端编写一个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。
答案 1 :(得分:0)
您可以将其添加到http-headers,但这意味着您的客户端需要执行此操作,这也意味着他们可以更改它并为您提供错误的数字,从而导致服务器出现问题。它只与发送的消息一样可靠。
无论哪种方式,这都不是限制访问Web服务的正确方法,您应该使用http基本身份验证,或者如果版本存在差异,那么您应该创建多个版本端点,以便客户端访问所需的版本。
另外,JBoss 4.2.3已经很老了,甚至可能都无法运行。见[1]
小家鼠
答案 2 :(得分:0)
尝试将带外元数据添加到Web服务是个坏主意。如果数据结构不兼容,只需为每个版本选择一个新URL。如果它们兼容,请将版本号放在请求中。
通过这种方式,您仍然可以支持与所有不同库的互操作,而不需要您的客户端为每个工具包找到新的环节。