简体   繁体   English

CXF:为CXF SOAP / REST Web服务的WSDL和WADL响应添加隐式标头

[英]CXF: Add implicit headers to WSDL and WADL responses for a CXF SOAP/REST web service

I am trying to add implicit headers to WSDL and WADL responses for a CXF SOAP/REST web service (which is managed by Camel). 我正在尝试为CXF SOAP / REST Web服务(由Camel管理)的WSDL和WADL响应添加隐式标头。

(These are not necessarily security headers....) (这些不一定是安全标题....)

By "implicit header" I mean that hitting the WSDL/WADL URL of the service will show that it's expected of the client to provide the header in the request. 通过“隐式标头”,我的意思是,点击服务的WSDL / WADL URL将显示客户端期望在请求中提供标头。

But I do not want to explicitly specify the header in the signature of the web service. 但我不想在Web服务的签名中明确指定标头。

I have a CXF interceptor that adds an implicit header to every SOAP/REST response. 我有一个CXF拦截器,它为每个SOAP / REST响应添加一个隐式头。

So since WSDL/WADL document are sent as a response to some GET request, I was thinking to somehow use a similar interceptor to add the header data to WSDL/WADL response. 因此,由于WSDL / WADL文档是作为对某些GET请求的响应而发送的,所以我想以某种方式使用类似的拦截器将头数据添加到WSDL / WADL响应中。 How could I carry out such a marvellous feat? 我怎么能进行这样一个奇妙的壮举?

Here is the CXF interceptor that adds an implicit header to every SOAP/REST response: 这是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 2.7.4

In CXF, the WSDL is generated through an Interceptor in the in chain called the WSDLGetInterceptor , that is placed in the READ chain. 在CXF中,WSDL是通过一个名为WSDLGetInterceptor链中的Interceptor生成的,它位于READ链中。

It's basic design is 它的基本设计是

  1. check if the call is a HTTP GET 检查呼叫是否是HTTP GET
  2. prepare an output message to return 准备输出消息以返回
  3. access the wsdl (from Java or from static ressource) 访问wsdl(来自Java或来自静态资源)
  4. write the wsdl to the output message 将wsdl写入输出消息
  5. interrupt the interceptor chain to provide the output message 中断拦截器链以提供输出消息

The easiest way to act on this process is to preempt this interceptor from doing its job, either by registering your own implementation before. 采取行动的最简单方法是抢占这个拦截器,使其无法通过之前注册您自己的实现来完成其工作。

Removing standard CXF interceptors is kind of a "hard thing to do" on a default Bus (easiest way is to register your own interceptor, put it first in the chain, and make it remove other interceptors like so message.getInterceptorChain().remove(removeInterceptor); 删除标准的CXF拦截器在默认的总线上是一件“难事”(最简单的方法是注册你自己的拦截器,把它放在链中,然后让它删除其他拦截器,如message.getInterceptorChain().remove(removeInterceptor);

But adding your own just before the standard WSDL interceptor is easy : 但是在标准WSDL拦截器之前添加自己的东西很简单:

public MyWSDLGetInterceptor() {
    super(Phase.READ);
    addBefore(WSDLGetInterceptor.class.getName());
}

The MyWSDLGetInterceptor would extend the standard WSDLGetInterceptor and you'd only override : 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
}

You could modify the resulting DOM Document on the fly (add / create DOM nodes) or through XSLT, whatever suits you best, you're back to handling standard XML through a standard API. 您可以动态修改生成的DOM Document(添加/创建DOM节点)或通过XSLT,无论您最喜欢什么,您都可以通过标准API处理标准XML。

CXF 2.7.x (where x is somewhere > 4 and < 10) CXF 2.7.x(其中x大于4且<10)

The principal is the same, but the interceptor works differently. 校长是相同的,但拦截器的工作方式不同。

  1. It (in a private method) puts the WSDL, as a DOM Document as an out message property 它(在私有方法中)将WSDL作为DOM Document作为out消息属性
  2. It cleans the output interceptor chain of all interceptors (except the absolute necessary) 它清除所有拦截器的输出拦截器链(绝对必要除外)
  3. It registers a WSDLGetOutInterceptor in the output chain 它在输出链中注册了一个WSDLGetOutInterceptor
  4. It stops the IN chain and proceeds to the stop chain 它会停止IN链并进入停止链
  5. The WSDLGetOutInterceptor does its serialization job WSDLGetOutInterceptor执行其序列化作业

So it's a bit harder / less clean. 所以它有点难/干净。 But using the same principle of pre-empting the base interceptor (registering yourself just before), you could override the cleanUpOutInteceptors to manipulate the message, just as in the 2.7.4 case, by accessing the WSDL through outMessage.get(DOCUMENT_HOLDER) 但是使用相同的预占基础拦截器的原则(之前注册自己),你可以通过outMessage.get(DOCUMENT_HOLDER)访问WSDL来覆盖cleanUpOutInteceptors来操纵消息,就像在2.7.4情况下一样。

WADL WADL

Sorry, I have no expertise, but I guess CXF has the same kind of architecture for both... 对不起,我没有专业知识,但我猜CXF对两者都有相同的架构......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM