【问题标题】:Do a HTTP POST instead of a GET执行 HTTP POST 而不是 GET
【发布时间】:2021-12-18 07:24:29
【问题描述】:

我尝试使用的 WebService 是 SOAP,它只接收 HTTP 方法 POST 的请求,但由于某种原因,我无法做到这一点,它只发送 GET。

我一直在松散地遵循本指南:https://spring.io/guides/gs/consuming-web-service/

我认为这不会是错误方法的情况,但我已经尝试通过 Postman 使用记录的信封,它工作正常,也是这样:

debugger image with GET

这就是我的做法:

package com.example.ws;

import com.demo.partner.wsdl.ObjectFactory;
import com.demo.partner.wsdl.StoreInformation;
import com.example.util.PartnerWSHttpHeaderCallBack;
import com.example.util.SoapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;

public class StoreInformationClient extends WebServiceGatewaySupport {

    private static final Logger log = LoggerFactory.getLogger(StoreInformationClient.class);

    @Autowired
    private ObjectFactory objectFactory;

    public StoreInformation getStoreInformation() {

        StoreInformation storeInformation = objectFactory.createStoreInformation();
        storeInformation.setStoreID("99633");

        return  (StoreInformation) getWebServiceTemplate()
            .marshalSendAndReceive("https://aurl.com/api/ws.wsdl", SoapUtils.buildEnvelope(storeInformation, StoreInformation.class),
                new PartnerWSHttpHeaderCallBack());
    }

}
package com.example.configuration;

import com.demo.partner.wsdl.ObjectFactory;
import com.example.ws.StoreInformationClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;

@Configuration
public class AppConfiguration {

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("com.demo.partner.wsdl");
        return marshaller;
    }

    @Bean
    public StoreInformationClient countryClient(Jaxb2Marshaller marshaller) {
        StoreInformationClient client = new StoreInformationClient();
        client.setMarshaller(marshaller);
        client.setUnmarshaller(marshaller);
        return client;
    }

    @Bean
    public ObjectFactory objectFactory() {
        return new ObjectFactory();
    }

}
package com.example.util;

import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.context.TransportContext;
import org.springframework.ws.transport.context.TransportContextHolder;
import org.springframework.ws.transport.http.HttpUrlConnection;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class PartnerWSHttpHeaderCallBack implements WebServiceMessageCallback {

    @Override
    public void doWithMessage(WebServiceMessage webServiceMessage) {
        Map<String, String> headers = new HashMap<>();

        headers.put("Authorization", "Basic definitelyABase64value");
        headers.put("SOAPAction", "http://www.partner.com/action/GetStoreInformation");
        headers.put("Content-Type", "text/xml");

        addRequestHeader(headers);
    }

    private void addRequestHeader(Map<String, String> headers) {
        TransportContext context = TransportContextHolder.getTransportContext();
        WebServiceConnection connection = context.getConnection();

        if (connection instanceof HttpUrlConnection) {
            HttpUrlConnection conn = (HttpUrlConnection) connection;
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                String k = entry.getKey();
                String v = entry.getValue();
                try {
                    conn.addRequestHeader(k, v);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

【问题讨论】:

  • 你怎么知道发送的是get而不是post?你有什么错误吗?
  • 我得到与通过 Postman 执行相同的错误,并且您可以看到连接正在使用 GET 方法的图像。我已经尝试在 PartnerWSHttpHeaderCallBack 中设置它,但它也不起作用。

标签: java spring-boot web-services soap http-method


【解决方案1】:

查看了 spring 的 6 个 api 和 8 个 api 文档,发现这种方式几乎是不可能的(如果不是不可能的话),因为正如您所发现的那样,在该层次结构的类集中似乎没有方法,并且接口(以您的代码形式)将http连接转换为“POST”的一种明智的连贯方式,它只会发送“GET”。 我知道 HttpUrlConnection 不是 java.net 而是 org.spring。但是弹簧连接必须通过连接对象的扩展和实例上下文来获得。 spring 框架文档似乎也是错误的,因为它显示没有实现 org.springframework.ws.transport.TransportConstants 和 org.springframework.ws.transport.http.HttpTransportConstants。 Niether在网上搜索了一下。 我只能建议“尝试”这个但是“Spring.org 项目”需要清楚地记录如何为这些接口设置常量以及是否有任何实际实现它们!

/*
            org.springframework.ws.transport.TransportConstants
            import org.springframework.ws.transport.http.HttpTransportConstants
            */
            
            HttpTransportConstants httCxt = ((HttpTransportConstants)TransportContextHolder.getTransportContext());
            // perhaps httCxt."METHOD_POST";
        httCxt.METHOD_POST;
    // no really, there should be an implementing class in the .transport packages that uses and sets this however i could not locate one throughout the ws classes and interfaces.
    // all interface variables are static and final (because interfaces are abstract they can be cast together)
            TransportContext context = (TransportContext)httCxt;

这是一篇似乎有些相似的文章 https://pretagteam.com/question/soap-request-to-webservice-with-java 但是我认为他们使用 java.net HttpURLConnection

spring中有一个类似的HttpURLConnection对象

*** spring 文档也没有在相同的类和接口上显示完整的层次结构**

org.springframework.ws.transport.http
Class HttpUrlConnection IMPLEMENTS org.springframework.ws.transport
Interface WebServiceConnection

The following worked many years back for applets and since finding ambiguous docs naming it appears this would work (or be immensely close)

To make a org.springframework.ws.transport.http.HttpUrlConnection

make a protected method 


protected org.springframework.ws.transport.http.HttpUrlConnection makeConnHttp(String uuu){
    java.net.URL urli = new java.net.URL(uuu);
    Java.net.UrlConnection urlcon = new Java.net.UrlConnection(urli);
    Java.net.HttpUrlConnection netUrl = (Java.net.HttpUrlConnection)urlcon;
    netUrl.setRequestMethod("POST");
    org.springframework.ws.transport.http.HttpUrlConnection wsUrlConn = new org.springframework.ws.transport.http.HttpUrlConnection(netUrl);
    return (org.springframework.ws.transport.http.HttpUrlConnection)wsUrlConn;
    }
    
    public org.springframework.ws.transport.http.HttpUrlConnection getWSconnectionHttp(String uuu){
    return (org.springframework.ws.transport.http.HttpUrlConnection)makeConnHttp(uuu);
    }

// spring 2.1.4 HttpUrlConnection is also a WebServiceConnection
org.springframework.ws.transport.WebServiceConnection wdConnsvc = (org.springframework.ws.transport.WebServiceConnection)getWSconnectionHttp(uuu);

我不知道 api 进程是在 UrLConnection 上调用 open()/close() 还是必须手动完成。

你的代码哪里出错了 请注意您的代码如何获得一个 TransportContext 和一个 WebServiceConnection。 生成的对象实例是一个单独的对象实例,与后来构建的spring框架HttpUrlConnection无关。 您可以打开连接,但它不是使用传输上下文构造的 WebServiceConnection 对象。

问题是 org spring HttpUrlConnection IS(a WebServiceConnection) 也是多态性的,因此您不需要获取 WebServiceConnection,因为您可以通过创建 org.spring HttpUrlConnection 来获得。 然而,org spring HttpUrlConnection 必须为实际网络提供一个实现编码的 java.net.HttpUrlConnection,org spring HttpUrlConnection 更像是一个连接器包装器,用于获取和管理绑定到 java.net.HttpUrlConnection 的数据和容器注册服务端点。

您的代码需要通过将任何 org.springframework....HttpUrlConnection 实例替换为一个/或使用 lava.lang.reflect 外部创建的 HttpUrlConnection 来连接这两个部分。

但是,在该问题中绑定对象的最佳方法是从类 org.springframework.ws.transport.http.HttpUrlConnection 扩展以防止绑定和访问问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-25
    • 2015-06-02
    • 2017-08-09
    • 1970-01-01
    • 2018-04-21
    • 1970-01-01
    • 2020-02-07
    • 2023-03-14
    相关资源
    最近更新 更多