клиент веб-службы Java, добавление заголовков http - PullRequest
16 голосов
/ 12 июля 2011

Создав клиент веб-службы java с помощью wsimport для wsdl, мне нужно установить заголовок авторизации для каждого сообщения мыла, встроенного в запрос http. Сгенерировав подкласс javax.xml.ws.Service, как я могу добавить заголовок http к каждому исходящему запросу ???

Ответы [ 4 ]

19 голосов
/ 05 сентября 2013

Вот код, основанный на ответе Феми.

Это может быть немного сложно понять.Работает красиво!

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);
13 голосов
/ 12 июля 2011

Вы можете передать карту с пользовательскими заголовками в BindingProvider (я полагаю, вы можете установить свойство MessageContext.HTTP_REQUEST_HEADERS).Попробуйте создать заголовок авторизации и передать его.

5 голосов
/ 12 октября 2016

Для полноты картины и для помощи другим в подобных ситуациях я хотел бы проиллюстрировать самое чистое решение IMHO с использованием JAX-WS-handler-chain:

1) Подкласс вашего класса обслуживания (не класса порта) в другом (не сгенерированном) пакете. Поскольку сервисный класс (и весь его пакет), вероятно, был сгенерирован из WSDL, ваши изменения в подклассе не будут потеряны при обновлении вашего сервисного класса после изменения WSDL.

2) Аннотируйте свой подкласс службы следующим образом (импорт javax.jws.HandlerChain):

@HandlerChain(file="HandlerChain.xml")
public class MyService extends GeneratedService {

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>

Вы можете добавить несколько <handler> элементов, кстати.

И убедитесь, что этот файл действительно попадает в ваш JAR! Например, при использовании Maven вы должны поместить его либо в ${project}/src/main/resources/ (вместо ${project}/src/main/java/), либо изменить конфигурацию сборки, включив ресурсы из папки java! Я рекомендую последнее, потому что в папке 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(); }
}

В моем примере выше (и в моем производительном коде) я получаю данные для передачи в заголовки HTTP-запроса из ThreadLocale, то есть контекста моего текущего потока. Поскольку этот WebserviceContext - мой пользовательский класс, вам нужно будет реализовать свой собственный способ доступа к вашим данным.

1 голос
/ 11 июля 2017

при отправке в режиме сообщений вы также можете передать MimeHeaders в сообщение SOAP, которое в конечном итоге преобразуется в заголовки http, т.е.:

soapMessage.getMimeHeaders().addHeader("Authorization","Basic [md5]")
...