SpringBoot中写webService接口和调用

一、webService接口的编写

参考文档:springboot实现WebService接口_springboot webservice接口-CSDN博客

1、引入依赖:

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
    <version>3.2.7</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2、定义公共接口,限制命名空间(可忽略)

package cn.bjca.spi.service;

import javax.jws.WebService;

/**
 * @Description  这里主要是想要在暴露方法的时候能够统一,方便管理
 *
 */
@WebService(targetNamespace = "http://service.spi.bjca.cn/")
public interface ApiService {

}

此接口为了在暴露时对方法进行统一的管理,也可以不用定义公共的接口,直接定义webservice接口,targetNamespase是命名空间,调用时统一值就行,不写是默认为包名的倒序

3、定义webservice接口

如果定义了公共接口,记得在此集成,在此示例为不继承公共接口的样例

package cn.bjca.spi.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * @ClassName ApiService
 * @Description
 * @Date 2024/6/14 16:48
 * @Version 1.0
 */
@WebService(targetNamespace = "http://service.spi.bjca.cn/")
public interface ApiCommonService {
    @WebMethod(operationName = "commonApi")
    String commonApi(@WebParam(name="param1") String param1,@WebParam(name = "param2") String param2);
}

4、webservice实现类

package cn.bjca.spi.service.impl;

import cn.bjca.spi.service.ApiCommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.jws.WebService;

/**
 * @ClassName ApiServiceImpl
 * @Description  测试地址:http://127.0.0.1:8099/ws/ApiCommonService?wsdl
 * @Date 2024/6/14 16:52
 * @Version 1.0
 */
@Component
@WebService(name = "ApiCommonService",
        targetNamespace = "http://service.spi.bjca.cn/",
        endpointInterface = "cn.bjca.spi.service.ApiCommonService",
        portName = "10000")
@Slf4j
public class ApiCommonServiceImpl implements ApiCommonService {

    @Override
    public String commonApi(String param1,String param2) {
        log.info("调用的入参为:"+param1+","+param2);
        return "成功";
    }
}

5、发布webservice,即配置webservice的config文件

未实现公共接口,需要一个一个注册webservice接口的

package cn.bjca.spi.config;

import cn.bjca.spi.service.ApiCommonService;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.xml.ws.Endpoint;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName WebServicePublishConfig
 * @Description
 * @Date 2024/6/14 16:57
 * @Version 1.0
 */
@Configuration
public class WebServicePublishConfig {
    @Bean
    public ServletRegistrationBean wsServlet(){
        return new ServletRegistrationBean(new CXFServlet(),"/ws/*");
    }

    @Resource
    private ApiCommonService apiCommonService;
    @Resource
    private List<ApiCommonService> apiServices;
    @Resource
    @Qualifier(Bus.DEFAULT_BUS_ID)
    private SpringBus bus;

    @Bean
    public Endpoint[] endPoint(){
        List<Endpoint> endpointList = new ArrayList<>(apiServices.size());
        EndpointImpl endpoint = new EndpointImpl(bus, apiCommonService);
        String simpleName = apiCommonService.getClass().getSimpleName();
        //如果有Impl结尾的类名,去掉Impl
        if (simpleName.endsWith("Impl")) {
            simpleName = simpleName.substring(0, simpleName.length() - 4);
        }
        endpoint.publish("/"+simpleName);
        endpointList.add(endpoint);
        return endpointList.toArray(new Endpoint[0]);
    }

}

实现了公用接口的用下面的这个

package com.zhqc.cloud.oms.webService;

import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.xml.ws.Endpoint;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author zdd
 */
@Configuration
public class WebServicePublishConfig {
    @Bean
    public ServletRegistrationBean wsServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/ws/*");
    }

    @Resource
    private List<ApiService> apiServices;

    @Resource
    @Qualifier(Bus.DEFAULT_BUS_ID)
    private SpringBus bus;

    @Bean
    public Endpoint[] endpoint() {
        List<Endpoint> endpointList = new ArrayList<>(apiServices.size());
        for (ApiService apiService : apiServices) {
            EndpointImpl endpoint = new EndpointImpl(bus, apiService);
            String simpleName = apiService.getClass().getSimpleName();
            //如果有Impl结尾的类名,去掉Impl
            if (simpleName.endsWith("Impl")) {
                simpleName = simpleName.substring(0, simpleName.length() - 4);
            }
            endpoint.publish("/" + simpleName);
            endpointList.add(endpoint);
        }
        return endpointList.toArray(new Endpoint[0]);
    }
}

6、测试访问,在浏览器中打开下面地址:

http://127.0.0.1:8099/ws/ApiCommonService?wsdl

 返回,下面内容即发布成功

二、调用webservice接口

参考文献:意外的元素 (uri:““, local:“arg0“)。所需元素为&lt;{}arg0正确解决方法_意外的元素 url 所需元素为-CSDN博客

1、postman方法:

选择Body->raw,xml格式,内容如下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pm="http://www.xxx.com/">
<soapenv:Header/>
<soapenv:Body>
<pm:getClassinfoBasic>

<arg0>123</arg0>

</pm:getClassinfoBasic>
</soapenv:Body>
</soapenv:Envelope>

其中:
(1) xmlns:pm="http://www.xxx.com/",这个与第一种写法参数一致,还是后端配置的那个targetNamespace,和后端配置的保持一致即可。
(2)<pm:getClassinfoBasic></pm:getClassinfoBasic>,这个还是后端的方法名。
(3)<arg0>123</arg0>,还是方法的入参,表示第一个参数传入参123;如果有多个,就用<arg0>123</arg0><arg1>456</arg1>这样即可,配置了webParam注解,需要改成对应的webParam名字。

2、java调用

java调用有多种方法,这里只写一种(使用AXIS调用WebService),具体其他的可以参考:Java 调用 WebService 服务的 3 种方式_java 调用webservice-CSDN博客

2.1、引入依赖:

    <dependency>
      <groupId>axis</groupId>
      <artifactId>axis</artifactId>
      <version>1.4</version>
    </dependency>

call.setOperationName(new QName("命名空间地址", "方法名")); 

package cn.bjca.spi.web.controller;

import cn.bjca.spi.api.facade.SdkDemoFacade;
import cn.bjca.spi.service.SdkDemoService;
import cn.org.bjca.footstone.common.api.web.ReturnResult;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;


@RestController
@Slf4j
public class SdkDemoController{

    public static void main(String[] args) {
        System.out.println(webServer1());
    }

    public static String webServer1() {
        try {
            //请求服务地址
            String url="http://127.0.0.1:8099/ws/ApiCommonService?wsdl";
            //请求命名空间
            String targetNameSpace="http://service.spi.bjca.cn/";
            //请求方法
            String method="commonApi";
            Service service = new Service();
            Call call = (org.apache.axis.client.Call)service.createCall();
            //设置服务地址,指明远程调用的类
            call.setTargetEndpointAddress(url);
            //call.setOperationName(new QName("命名空间地址", "方法名"));
            call.setOperationName(new QName(targetNameSpace,method));
            call.setTimeout(60000);            //设置超时时间
            call.setUseSOAPAction(true);//开启soap
            //call.addParameter("参数名称", (参数类型)XMLType.XSD_STRING, ParameterMode.IN(输入、输出));// 接口的参数
            call.addParameter("param1", XMLType.XSD_STRING, ParameterMode.IN);
            call.addParameter("param2", XMLType.XSD_STRING, ParameterMode.IN);
            call.setReturnType(XMLType.XSD_STRING);
            String result  = (String)call.invoke(new Object[]{"1231231","asdfasfd"}); 给方法传递参数,并且调用方法
            System.out.println("调用结果:"+ JSONObject.toJSONString(result));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "调用成功";
    }
    
}

三、其他

1、报错提示:意外的元素 (uri:"http://www.xxx.com/", local:"arg0")。所需元素为&lt;{}arg0或者 意外的元素 (uri:"", local:"param3")。所需元素为<{}param1>,<{}param2>

答:这种多是方法的参数未被找到,多半是命名空间的问题,像上面Java的调用addParameter方法中就未指定方法参数的命名空间,默认就是空,所以在定义的webService方法中的参数也不能指定targetNamespace 

2、调用提示:Message part {http://service.spi.bjca.cn/}commonApi2 was not recognized.

答:这种也是方法名用错了或者命名空间不对,检查调用时配置的命名空间是否正确

3、就是当webService方法是需要传递对象的时候,如何传值

package com.zhqc.cloud.oms.webService.sku;

import com.zhqc.cloud.oms.webService.ApiService;
import com.zhqc.cloud.oms.webService.sku.entity.SkuKSFNoticeRequest;
import com.zhqc.framerwork.common.model.vo.ResponseVO;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * @author zdd
 */
@WebService(targetNamespace = "http://andot.org/webservice/zhqc/server")
public interface ApiSkuService extends ApiService {


    /**
     * 创建订单
     *
     * @param skuKSFNoticeRequest 请求参数
     * @return ResponseVO 返回结果
     */
    @WebMethod
    ResponseVO wmsApi(@WebParam(name = "KSF_Notice", targetNamespace = "http://andot.org/webservice/zhqc/server") SkuKSFNoticeRequest skuKSFNoticeRequest);

}
package com.zhqc.cloud.oms.webService.sku;

import com.alibaba.fastjson.JSONObject;
import com.zhqc.cloud.common.model.base.dto.SkuAddOrUpdateReqDTO;
import com.zhqc.cloud.common.utils.ConvertUtil;
import com.zhqc.cloud.oms.api.base.service.ErpSkuService;
import com.zhqc.cloud.oms.api.order.service.ErpOrderService;
import com.zhqc.cloud.oms.webService.sku.entity.SkuDetail;
import com.zhqc.cloud.oms.webService.sku.entity.SkuKSFNoticeRequest;
import com.zhqc.framerwork.common.model.vo.BusinessResponseVO;
import com.zhqc.framerwork.common.model.vo.ResponseVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.jws.WebService;
import java.util.List;

/**
 * @author zdd
 */
@Component
@WebService(name = "ApiService",
        targetNamespace = "http://andot.org/webservice/zhqc/server",
        endpointInterface = "com.zhqc.cloud.oms.webService.sku.ApiSkuService",
        portName = "10000")
@Slf4j
public class ApiSkuServiceImpl implements ApiSkuService {

    @Resource
    @Lazy
    private ErpSkuService erpSkuService;


    @Override
    public ResponseVO wmsApi(SkuKSFNoticeRequest skuKSFNoticeRequest) {
        try {
            log.info("接收到SAP数据-saveOrUpdateOfSku:{}", JSONObject.toJSONString(skuKSFNoticeRequest));
            List<SkuDetail> skuDetailList = skuKSFNoticeRequest.getSkuElements().getSkuElement().getSkuDetail();
            for (SkuDetail skuDetail : skuDetailList) {
                erpSkuService.saveOrUpdate(ConvertUtil.cast(skuDetail, SkuAddOrUpdateReqDTO.class));
            }


        } catch (Exception e) {
            log.error("createSku error", e);
            return BusinessResponseVO.buildFailVo(e.getMessage());
        }
        return ResponseVO.success();
    }


}
package com.zhqc.cloud.oms.webService.sku.entity;

import lombok.Data;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author zdd
 */
@Data
@XmlRootElement(name = "KSF_Notice", namespace = "http://andot.org/webservice/zhqc/server")
public class SkuKSFNoticeRequest {



    private SkuAPIMessage skuApiMessage;

    private SkuElements skuElements;



    @XmlElement(name = "API_Message", namespace = "http://andot.org/webservice/zhqc/server")
    public SkuAPIMessage getSkuApiMessage() {
        return skuApiMessage;
    }

    @XmlElement(name = "Elements", namespace = "http://andot.org/webservice/zhqc/server")
    public SkuElements getSkuElements() {
        return skuElements;
    }
}
package com.zhqc.cloud.oms.webService.sku.entity;

import lombok.Data;

import javax.xml.bind.annotation.XmlElement;

/**
 * @author zdd
 */
@Data
public class SkuAPIMessage {

    private String guid;

    private String sourceSys;

    private String targetSys;

    private String singleTargetSys;

    private String updateTime;

    private String appKey;

    private String isTest;

    private String isManualSend;




    @XmlElement(name = "Guid", namespace = "http://andot.org/webservice/zhqc/server")
    public String getGuid() {
        return guid;
    }

    @XmlElement(name = "SourceSys", namespace = "http://andot.org/webservice/zhqc/server")
    public String getSourceSys() {
        return sourceSys;
    }

    @XmlElement(name = "TargetSys", namespace = "http://andot.org/webservice/zhqc/server")
    public String getTargetSys() {
        return targetSys;
    }

    @XmlElement(name = "SingleTargetSys", namespace = "http://andot.org/webservice/zhqc/server")
    public String getSingleTargetSys() {
        return singleTargetSys;
    }

    @XmlElement(name = "UpdateTime", namespace = "http://andot.org/webservice/zhqc/server")
    public String getUpdateTime() {
        return updateTime;
    }

    @XmlElement(name = "AppKey", namespace = "http://andot.org/webservice/zhqc/server")
    public String getAppKey() {
        return appKey;
    }

    @XmlElement(name = "IsTest", namespace = "http://andot.org/webservice/zhqc/server")
    public String getIsTest() {
        return isTest;
    }

    @XmlElement(name = "IsManualSend", namespace = "http://andot.org/webservice/zhqc/server")
    public String getIsManualSend() {
        return isManualSend;
    }

}

猜你喜欢

转载自blog.csdn.net/weixin_50003028/article/details/139864896