我正在尝试为CXF SOAP/REST web服务(由Camel管理)的WSDL和WADL响应添加隐式标头。
(这些不一定是安全标头……)
所谓"隐式标头",我的意思是,点击服务的WSDL/WADL URL将表明客户端需要在请求中提供标头。
但我不想在web服务的签名中明确指定头。
我有一个CXF拦截器,它为每个SOAP/REST响应添加了一个隐式标头。
因此,由于WSDL/WDL文档是作为对某个GET请求的响应发送的,所以我想以某种方式使用类似的拦截器将头数据添加到WSDL/WADL响应中。我怎么能完成如此了不起的壮举?
以下是CXF拦截器,它为每个SOAP/REST响应添加了一个隐式标头:
public class MyInterceptor extends AbstractPhaseInterceptor<Message> {
public MyInterceptor()
{
super(Phase.RECEIVE);
}
@Override
public void handleMessage(Message message)
{
try
{
//soap
if (message instanceof SoapMessage)
{
List<Header> headers = ((SoapMessage)message).getHeaders();
Header dummyHeader = new Header(new QName("uri:org.apache.cxf", "dummy"), "decapitated", new JAXBDataBinding(String.class));
headers.add(dummyHeader);
}
//rest
else
{
Map<String, List> headers = (Map<String, List>) message.get(Message.PROTOCOL_HEADERS);
String dummyHeader = "decapitated";
headers.put("dummy", Collections.singletonList(dummyHeader));
}
}
catch (JAXBException e)
{
throw new Fault(e);
}
}
@Override
public void handleFault(Message messageParam)
{
}
}
CXF 2.7.4
在CXF中,WSDL是通过位于READ
链中的名为WSDLGetInterceptor
的内链中的拦截器生成的。
它的基本设计是
- 检查调用是否为HTTP GET
- 准备要返回的输出消息
- 访问wsdl(从Java或静态资源)
- 将wsdl写入输出消息
- 中断拦截器链以提供输出消息
对这个过程采取行动的最简单方法是抢占这个拦截器的工作,或者之前注册自己的实现。
在默认总线上删除标准CXF拦截器是一件"很难做到的事"(最简单的方法是注册自己的拦截器,将其放在链中的第一位,并使其删除其他拦截器,如message.getInterceptorChain().remove(removeInterceptor);
但是,在标准WSDL拦截器之前添加自己的拦截器很容易:
public MyWSDLGetInterceptor() {
super(Phase.READ);
addBefore(WSDLGetInterceptor.class.getName());
}
MyWSDLGetInterceptor
将扩展标准WSDLGetInterceptor
,并且您只能覆盖:
public Document getDocument(Message message,
String base,
Map<String, String> params,
String ctxUri,
EndpointInfo endpointInfo) {
Document domDocument = super.getDocument(message, base, params, ctxUri, endpointInfo);
domDocument.getChildNodes(); // Whatever you need to add remove
return domDocument; // Once modified
}
您可以动态修改生成的DOM文档(添加/创建DOM节点),也可以通过XSLT修改,无论什么最适合您,都可以通过标准的API处理标准的XML。
CXF 2.7.x(其中x在某个位置>4且<10)
主体是相同的,但拦截器的工作方式不同。
- 它(在私有方法中)将WSDL作为DOM文档作为输出消息属性
- 它清除所有拦截器的输出拦截器链(绝对必要的除外)
- 它在输出链中注册一个
WSDLGetOutInterceptor
- 它停止IN链并进入停止链
WSDLGetOutInterceptor
完成其序列化工作
所以它有点难/不太干净。但是,使用抢占基本拦截器的相同原理(之前刚刚注册),您可以覆盖cleanUpOutInteceptors
来操作消息,就像在2.7.4中一样,通过outMessage.get(DOCUMENT_HOLDER)
访问WSDL
WADL
对不起,我没有专业知识,但我想CXF对两者都有相同的体系结构。。。