1. 场景

最近客户给了一个 API,如图,最开始以为是一个传统的post请求,结果始终返回一段奇怪的响应。
在这里插入图片描述
最后和小伙伴沟通、查阅资料后才知道是一种特有的SOAP协议的请求方式。

2. 原生java

豆包和Deepseek 给了一种非原生的方式,需要安装依赖和执行wsimport命令行命令。
这里提供一种清爽的方法,代码如下:

2.1 SOAP client实现
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j2;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Log4j2
@Service
public class WeatherSoapClient {

    private static final String SOAP_ENDPOINT = "http://12.122.222.223:7777/GetSeaWeather.asmx?op=GetCurSeaWeatherInfo";

    // 根据实际文档设置命名空间
    private static final String SOAP_NAMESPACE = "http://tempuri.org/";

    public Map<String, Object> getWeatherData(double longitude, double latitude) {
        try {
            // 1. 构建 SOAP 请求体
            String soapRequest = buildSoapRequest(longitude, latitude);
            log.info("SOAP Request: {}", soapRequest);

            // 2. 发送 POST 请求
            String soapResponse = sendSoapRequest(soapRequest);

            // 3. 解析 SOAP 响应
            String str = extractTagContent(soapResponse, "GetCurSeaWeatherInfoResult");
            JSONObject jsonObject = JSON.parseObject(str, JSONObject.class);
            return jsonObject;
        } catch (Exception e) {
            throw new RuntimeException("SOAP request failed", e);
        }
    }

    private String buildSoapRequest(double lon, double lat) {
        return String.format(
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                        "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\"" +
                        "               xmlns:api=\"%s\">" +
                        "   <soap:Header/>" +
                        "   <soap:Body>" +
                        "       <api:GetCurSeaWeatherInfo>" +
                        "           <api:lon>%s</api:lon>" +
                        "           <api:lat>%s</api:lat>" +
                        "       </api:GetCurSeaWeatherInfo>" +
                        "   </soap:Body>" +
                        "</soap:Envelope>",
                SOAP_NAMESPACE, lon, lat
        );
    }

    private String sendSoapRequest(String soapRequest) throws Exception {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(SOAP_ENDPOINT);

            // 设置 SOAP 特定请求头
            httpPost.setHeader("Content-Type", "text/xml; charset=utf-8");
            httpPost.setHeader("SOAPAction", SOAP_NAMESPACE + "GetCurSeaWeatherInfo");

            // 设置请求体
            httpPost.setEntity(new StringEntity(soapRequest, ContentType.TEXT_XML));

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                HttpEntity entity = response.getEntity();
                if (entity == null) {
                    throw new RuntimeException("Empty response from SOAP service");
                }

                // 获取响应内容
                String responseContent = EntityUtils.toString(entity);
                EntityUtils.consume(entity);

                // 检查 HTTP 状态码
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    throw new RuntimeException(
                            "SOAP service returned HTTP " + statusCode +
                                    "\nResponse: " + responseContent
                    );
                }

                return responseContent;
            }
        }
    }

    public static String extractTagContent(String xmlStr, String tagName) {
        String pattern = "<" + tagName + ">(.*?)</" + tagName + ">";
        Pattern r = Pattern.compile(pattern, Pattern.DOTALL);
        Matcher m = r.matcher(xmlStr);
        if (m.find()) {
            return m.group(1);
        }
        return null;
    }

}
2.2 controller
    @Autowired
    private WeatherSoapClient weatherSoapClient;
    
    @GetMapping("/getCurrentWeather")
    public ApiResult getCurrentWeather(
            @RequestParam double lon,
            @RequestParam double lat) {
        try {
            Map<String, Object> weatherData = weatherSoapClient.getWeatherData(lon, lat);
            return ApiResult.ok(weatherData);
        } catch (Exception e) {
            Map<String, Object> error = new HashMap<>();
            error.put("error", "SOAP request failed");
            error.put("message", e.getMessage());
            return ApiResult.fail(ApiCode.BUSINESS_EXCEPTION, error);
        }
    }
Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐