java web服务客户端,添加http标头

mur*_*ngu 16 java soap web-services jax-ws

在wsdl上使用wsimport创建了一个java Web服务客户端,我需要为http请求中嵌入的每个soap消息设置Authorization头.生成了javax.xml.ws.Service的子类后,如何将http标头附加到每个传出请求?

Dan*_*iuc 19

这是基于Femi答案的代码.

弄明白这可能有点棘手.工作得很漂亮!

Service jaxwsService = Service.create(wsdlURL, serviceName);
Dispatch<SOAPMessage> disp = jaxwsService.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);

//Add HTTP request Headers
Map<String, List<String>> requestHeaders = new HashMap<>();
requestHeaders.put("Auth-User", Arrays.asList("BILL_GATES"));
disp.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!如果你像我一样愚蠢,你可能会尝试使用`Map <String,String>`,因为你读得的答案太快了.不要像我一样.使用`Map <String,List <String >>`并保存我尝试调试`HTTP传输错误所花费的四个小时:java.lang.ClassCastException:java.lang.String不能转换为java.util.List`. (5认同)

Fem*_*emi 13

您可以将带有自定义标头的地图传递给BindingProvider(我相信您可以设置MessageContext.HTTP_REQUEST_HEADERS属性).尝试创建一个Authorization标头并将其传入.


小智 7

为了补充 Daniel Alexiuc 和 Femi 的答案,这里是基于此文档的略微替代方法:https ://javaee.github.io/metro/doc/user-guide/user-guide.html#adding-soap-headers-when-发送请求

public class HelloClient {

   @WebServiceRef(wsdlLocation="http://localhost:8080/helloservice/hello?wsdl")
   static HelloService service;


   public HelloPort getHelloPort(){
       HelloPort helloPort = service.getHelloPort();

       Map<String, List<String>> requestHeaders = new HashMap<>();
       requestHeaders.put("Your_Header",Arrays.asList("Your_Header_value"));

       BindingProvider bindingProvider = (BindingProvider)helloPort;
       bindingProvider.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);

       return helloPort;
    }
}
Run Code Online (Sandbox Code Playgroud)

这将向 http 请求添加标头


Mar*_*rco 6

为了完整起见并在类似情况下为他人提供帮助,我想说明一下使用JAX-WS-handler-chain的IMHO最干净的解决方案:

1)在另一个(未生成的)包中将您的服务类(而不是端口类)子类化。因为服务类(及其整个包)可能是从WSDL生成的,所以在WSDL更改后更新服务类时,对子类的更改不会丢失。

2)这样注释您的服务子类(import javax.jws.HandlerChain):

@HandlerChain(file="HandlerChain.xml")
public class MyService extends GeneratedService {
Run Code Online (Sandbox Code Playgroud)

3)HandlerChain.xml在与服务子类相同的程序包中创建一个名为的文件,即紧随MyService以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
    <handler-chain>
        <handler>
            <handler-name>co.codewizards.example.HttpHeaderExtensionSOAPHandler</handler-name>
            <handler-class>co.codewizards.example.HttpHeaderExtensionSOAPHandler</handler-class>
        </handler>
    </handler-chain>
</handler-chains>
Run Code Online (Sandbox Code Playgroud)

您可以添加多个<handler>元素,顺便说一句。

并确保此文件确实以您的JAR结尾!例如,在使用Maven时,您必须将其放置在${project}/src/main/resources/(而不是${project}/src/main/java/)中,或者必须更改构建配置以包括java-folder中的资源!我建议使用后者,因为在-文件resources夹中具有并行的包结构很麻烦,在重构过程中常常会忘记该结构。

4)实施HttpHeaderExtensionSOAPHandler-类似:

import static com.google.common.base.Preconditions.*;

import java.util.*;

import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import co.codewizards.webservice.WebserviceContext;

public class HttpHeaderExtensionSOAPHandler implements SOAPHandler<SOAPMessageContext> {

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        checkNotNull(context, "context");

        Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        checkNotNull(outboundProperty, "outboundProperty");

        if (outboundProperty.booleanValue()) {
            WebserviceContext<?, ?> webserviceContext = WebserviceContext.getThreadWebserviceContextOrFail();
            String something = (String) webserviceContext.___(); // my API method ;-)

            @SuppressWarnings("unchecked")
            Map<String, List<String>> requestHeaders = (Map<String, List<String>>) context.get(MessageContext.HTTP_REQUEST_HEADERS);
            if (requestHeaders == null) {
                requestHeaders = new HashMap<String, List<String>>();
                context.put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);
            }
            requestHeaders.put(MyService.MY_CONSTANT, Collections.singletonList(something));
        }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) { return true; }

    @Override
    public void close(MessageContext context) { }

    @Override
    public Set<QName> getHeaders() { return Collections.emptySet(); }
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例(以及生产性代码)中,我从ThreadLocale,即当前线程的上下文,获取要传递到HTTP请求标头的数据。由于这WebserviceContext是我的自定义类,因此您需要实现自己的访问数据的方式。