在wsdl上使用wsimport创建了一个java Web服务客户端,我需要为http请求中嵌入的每个soap消息设置Authorization标头。生成了javax.xml.ws.Service的子类后,如何将http标头附加到每个传出请求???
答案 0 :(得分: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);
答案 1 :(得分:13)
您可以将带有自定义标头的地图传递给BindingProvider(我相信您可以设置MessageContext.HTTP_REQUEST_HEADERS属性)。尝试创建一个Authorization标头并将其传入。
答案 2 :(得分:4)
为了完整和帮助处于类似情况的其他人,我想用JAX-WS-handler-chain来说明IMHO最干净的解决方案:
1)将服务类(不是端口类)子类化为另一个(非生成的)包。因为服务类(及其整个包)可能是从WSDL生成的,所以当您在WSDL更改后更新服务类时,对子类的更改不会丢失。
2)像这样注释你的服务子类(import 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(); }
}
在上面的示例中(以及我的高效代码中),我获取了要从ThreadLocale
传递到HTTP请求标头的数据,即我当前线程的上下文。由于此WebserviceContext
是我的自定义类,因此您需要实现自己的方式来访问数据。
答案 3 :(得分:1)
当您在消息模式下发送时,您还可以在SOAP消息上传递MimeHeaders,最终将转换为http标头,即:
soapMessage.getMimeHeaders().addHeader("Authorization","Basic [md5]")
答案 4 :(得分:0)
根据本文档,{D {3}}
是对Daniel Alexiuc和Femi的回答的补充,这里是另一种替代方法。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;
}
}
这会将标头添加到http请求