Web Services 在Netbeans中生成的Java Web服务客户端-获取Http状态代码307

cwtwac6a  于 2022-11-15  发布在  Java
关注(0)|答案(2)|浏览(140)

我使用Netbeans生成Web服务客户端代码,客户端样式JAX-WS,因此我可以调用Web服务API。
但是,当我调用Web服务API时,会出现异常:异常错误:服务器发送了HTTP状态代码307:临时重定向**
为什么会出现这种情况?解决方法是什么?我知道问题不在于Web服务本身,因为我可以通过soapUI和. Net很好地获得响应。

ngynwnxp

ngynwnxp1#

大约一个月前也遇到了同样的问题。
Web服务客户端类是使用Apache CXF生成的,并且Web服务返回HTTP状态307,这导致了相同的异常。
使用soapUI调用相同的Web服务方法(属性Follow Redirects设置为true)成功,并返回了所需的数据。
在谷歌上搜索了一段时间后,似乎没有属性可以在JAX-WS中为此启用以下重定向。
所以,下面是目前正在工作的代码,虽然我不确定它是否符合任何标准:
假设生成的客户端类如下所示:

// generated service class
public class MyWebServiceClient extends javax.xml.ws.Service {
    // ...
    private final QName portName = "...";
    // ...
    public RetrieveMyObjects getRetrieveMyObjects() {
        return super.getPort(portName, RetrieveMyObject.class);
    }
    // ...
}

// generated port interface
// annotations here
public interface RetrieveMyObjects {

    // annotations here
    List<MyObject> getAll();

}

现在,在执行以下代码时:

MyWebServiceClient wsClient = new MyWebServiceClient("wsdl/location/url/here.wsdl");
RetrieveMyObjectsPort retrieveMyObjectsPort = wsClient.getRetrieveMyObjects();

wsClient应该返回RetrieveMyObjectsjavax.xml.ws.BindingProvider接口的示例。在JAX-WS的表面上没有任何地方说明这一点,但似乎很多代码都是基于这一事实。可以通过执行以下内容来确保自己:

if(!(retrieveMyObjectsPort instanceof javax.xml.ws.BindingProvider)) {
    throw new RuntimeException("retrieveMyObjectsPort is not instance of " + BindingProvider.class + ". Redirect following as well as authentication is not possible");
}

现在,当我们确定retrieveMyObjectsPortjavax.xml.ws.BindingProvider的示例时,我们可以向它发送普通的HTTP POST请求,模拟SOAP请求(虽然它看起来非常不正确和丑陋,但这在我的情况下有效,我在谷歌上搜索时没有找到更好的),并检查Web服务是否会发送重定向状态作为响应:

// defined somewhere before
private static void checkRedirect(final Logger logger, final BindingProvider bindingProvider) {
    try {
        final URL url = new URL((String) bindingProvider.getRequestContext().get(ENDPOINT_ADDRESS_PROPERTY));
        logger.trace("Checking WS redirect: sending plain POST request to {}", url);
        final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setInstanceFollowRedirects(true);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "text/html; charset='UTF-8'");
        connection.setDoOutput(true);

        if(connection.getResponseCode() == 307) {
            final String redirectToUrl = connection.getHeaderField("location");
            logger.trace("Checking WS redirect: setting new endpoint url, plain POST request was redirected with status {} to {}", connection.getResponseCode(), redirectToUrl);
            bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, redirectToUrl);
        }
   } catch(final Exception e) {
       logger.warn("Checking WS redirect: failed", e);
   }
}

// somewhere at the application start
checkRedirect(logger, (BindingProvider) retrieveMyObjectsPort);

这个方法的作用是:它获取retrieveMyObjectsPortBindingProvider.ENDPOINT_ACCESS_PROPERTY,即该端口方法将向其发送SOAP请求的URL,并发送如上所述的普通HTTP POST请求。然后,它检查响应状态是否为307 - Temporary Redirect(也可能包括其他状态,如302或301),如果是,则获取Web服务将重定向到的URL,并为指定端口设置新端点。
在我的例子中,每个Web服务端口接口调用一次checkRedirect方法,然后一切似乎都正常工作:
1.在http://example.com:50678/restOfUrl等url上选中重定向

  1. Web服务重定向到https://example.com:43578/restOfUrl之类的url(请注意,存在Web服务客户端身份验证)-端口的端点设置为该url
    1.通过该端口执行的下一个Web服务请求成功
    免责声明:我是一个很新的网络服务,这是我设法实现由于缺乏解决这个问题,所以请纠正我,如果有什么不对。
    希望这对你有帮助
4sup72z8

4sup72z82#

是的,我知道这篇文章是旧的,但我也有类似的错误,并认为也许有人会受益于我的解决方案。
最让我苦恼的是:

com.sun.xml.ws.client.ClientTransportException: The server sent HTTP status code 200: OK

这意味着一个不完整的响应头。显然jax-ws做了某种验证,包括验证HTTP头。而我使用的服务器只是发送了一个空的头。
将**'application/soap+xml'添加到Content-Type**标题后,它的工作就像一个魔咒。

相关问题