JavaWeb服务:用户定义的元数据
我在JBoss4.2.3上有一个SOAP web服务实现。我想为该服务添加版本号检查。每当客户机打电话时,我都会传递客户机版本号。我将在服务器上编写一个拦截器来检查客户端版本号。如果是具有不同版本号的客户端,我将不处理该请求 我想知道的是,除了将版本号添加到web服务方法签名中之外,是否有其他方法可以在某些上下文参数中从客户端传递版本号JavaWeb服务:用户定义的元数据,java,web-services,jboss,jax-ws,Java,Web Services,Jboss,Jax Ws,我在JBoss4.2.3上有一个SOAP web服务实现。我想为该服务添加版本号检查。每当客户机打电话时,我都会传递客户机版本号。我将在服务器上编写一个拦截器来检查客户端版本号。如果是具有不同版本号的客户端,我将不处理该请求 我想知道的是,除了将版本号添加到web服务方法签名中之外,是否有其他方法可以在某些上下文参数中从客户端传递版本号 一般来说,如果我想将一些自定义元数据从客户端传递到服务器,我该怎么做?您可以将其添加到http头中,但这意味着您的客户端需要这样做,这也意味着他们可以更改它并给
一般来说,如果我想将一些自定义元数据从客户端传递到服务器,我该怎么做?您可以将其添加到http头中,但这意味着您的客户端需要这样做,这也意味着他们可以更改它并给您错误的号码,从而导致服务器出现问题。它的可靠性取决于发送的信息 无论哪种方式,这都不是限制对Web服务访问的正确方式,您应该使用http基本身份验证,或者如果存在版本差异,那么您应该创建多个版本端点,以便客户端访问他们需要的版本 另外,JBoss4.2.3太旧了,甚至可能无法工作。见[1] 马斯
[1] 尝试向web服务添加带外元数据是个坏主意。如果数据结构不兼容,只需为每个版本选择一个新的URL即可。如果它们兼容,请将版本号放入请求中 通过这种方式,您仍然可以支持与所有不同库的互操作,而不需要您的客户机为每个工具包寻找新的跳转 通常,如果我想将一些自定义元数据从客户端传递到 服务器,我怎么做
这可以通过Jax-WS中的双方(客户机和服务器)来实现 客户端: 可以通过添加自定义元数据,如版本号、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");
}
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) {
}
}
在这里,我们添加了一个新的头元素“versionnumber”,mustunderstand=true,这意味着服务器/中介机构必须处理该元素,否则Jax WS-Runtime将向客户端抛出SOAP故障异常。现在我们需要在服务器端编写一个验证器(SOAP处理程序)来验证客户端传递的这个版本号
服务器端:
1.编写一个VersionNumberValidator,如下所示
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");
}
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) {
}
}
公共类VersionNumberValidator实现SOAPHandler{
@抑制警告(“未使用”)
@凌驾
公共布尔handleMessage(SOAPMessageContext ctx){
//这是入站消息,即请求吗?
布尔响应_p=(布尔)ctx
.get(MessageContext.MESSAGE\u出站\u属性);
//仅当SOAP传入时才对其进行操作。
如果(!响应){
试一试{
SOAPMessage msg=ctx.getMessage();
SOAPEnvelope env=msg.getSOAPPart().getEnvelope();
SOAPHeader hdr=env.getHeader();
//确保SOAP消息具有标头。
如果(hdr==null){
GeneratesApFault(消息,“无消息头”);
返回true;
}
迭代器mustUnderstandHeaders=msg.getSOAPHeader()
.考试标准(
"http://schemas.xmlsoap.org/soap/actor/next");
字符串值=null;
while(mustUnderstandHeaders.hasNext()){
Node next=(Node)mustUnderstandHeaders.next();
System.out.println(“mustUnderstandHeaders名称:”
+next.getValue());
if(next.getNodeName().equalsIgnoreCase(“versionnumber”))
value=next.getValue();
if(value!=null&!value.equalsIgnoreCase(“v1.0”)){
GenerateSapFault(消息,“版本号不匹配”);
}
}
//对于跟踪,写入标准输出。
消息写入(系统输出);
}捕获(SOAPE例外){
系统错误println(e);
}捕获(IOE异常){
系统错误println(e);
}
}
return true;//继续往下链
}
@凌驾
公共布尔handleFault(SOAPMessageContext ctx){
return true;//继续执行链
}
//现在,没有行动。
@凌驾
公共集getHeaders(){
Set headers=new HashSet();
QName QName=新的QName(“http://ticket.example.com/“,“版本号”);
headers.add(qName);
返回标题;
}
@凌驾
公共作废关闭(MessageContext MessageContext){
}
私有void generateSOAPFault(SOAPMessage消息,字符串原因){
试一试{
SOAPBody=msg.getSOAPBody();
SOAPFault fault=body.addFault();
QName fault_name=新的QName(
SOAPConstants.URI_NS_SOAP_1_2_信封,“UltimateReceiver”);
故障。设置故障代码(故障名称);
fault.setFaultRole(“http://ticket.example.com/versionNumber_validator");
addFaultReasonText(reason,Locale.US);
}捕获(SOAPE例外){
}
}
2.在Handler-Chain-server.xml中提到这个类
<javaee:handler>
<javaee:handler-class>
com.example.client.handler.VersionNumberValidator
</javaee:handler-class>
</javaee:handler>
com.example.client.handler.VersionNumberValidator
3.发布Web服务
现在,每个客户端请求都将具有“versionnumber=v1.0”,在服务器端,您将验证此值是否正确。如果不正确,将抛出SOAPFaultException。我不想允许多个版本。其思想是只允许特定版本的服务器使用特定版本的客户端。我需要找到一种方法来验证相同的值。因此,停止为旧版本提供URL我已经有了一个基本的身份验证。现在我需要验证。这正是我要找的。但是,我还有另一个问题。有没有办法使处理程序链信息注释基于处理程序而不是创建处理程序-