Spring Boot 开发 WebService 服务

https://www.cnblogs.com/fishpro/p/spring-boot-study-webservice.html

验证通过

WebService 虽然现在大部分互联网企业不太提倡使用,但在以第三方接口为主导的市场,对方来什么接口你还得用什么接口,不可能把接口重写了。例如大部分传统的大型企业都在用 WebService,并且版本还不一样。

本章主要介绍在 Spring Boot 下有常用的整合 WebService 的方法并给出示例。为了方便测试,本章有两个独立的项目

  1. 用户的获取、增加、更新、删除 webservice 服务
  2. 用于调用 1 的webservice 服务的客户端

本项目源码 github 下载

1 新建 Spring Boot Maven 示例工程项目

注意:是用来 IDEA 开发工具

  1. File > New > Project,如下图选择 Spring Initializr 然后点击 【Next】下一步
  2. 填写 GroupId(包名)、Artifact(项目名) 即可。点击 下一步
    groupId=com.fishpro
    artifactId=webservice
  3. 选择依赖 Spring Web Starter 前面打钩。
  4. 项目名设置为 spring-boot-study-webservice.

2 引入依赖 Pom.xml

这里主要是引入 org.apache.cxf

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-spring-boot-starter-jaxws -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.5</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3 编写一个用户获取、新增、修改、删除服务

3.1 传输对象 UserDto

通常我们把展示层与服务层之间传输的对象使用Dto后缀来标识。

UserDto(路径 src/main/java/com/fishpro/webservice/dto/UserDto.java)


/**
 * 用户传输实体对象 通常我们把展示层与服务层之间传输的对象使用Dto后缀来标识。
 * */
public class UserDto {

    private Integer userId;//用户id
    private String userName;//用户名称
    private String password;//用户密码
    private Integer sex;//用户性别 0女 1男

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }
}

3.2 用户服务类

UserService 接口类(路径 src/main/java/com/fishpro/webservice/service/UserService.java)

/**
 * 用户服务类 必须使用 @WebService
 * */
@WebService(targetNamespace = WsConst.NAMESPACE_URI ,name = "userPortType")
public interface UserService {
    /**
     * 根据用户id获取用户信息
     * */
    @WebMethod(operationName="getUserById")
    UserDto get(@WebParam(name = "id")  String id);

    /**
     * 获取全部用户信息
     * */
    @WebMethod(operationName="getUsers")
    List<UserDto> list();

    /**
     * 获取用户数
     * */
    @WebMethod(operationName="count")
    int count(@);

    /**
     * 新增用户
     * */
    @WebMethod(operationName="save")
    int save(@WebParam(name = "user")  UserDto user);

    /**
     * 更新用户
     * */
    @WebMethod(operationName="update")
    int update(@WebParam(name = "user")  UserDto user);

    /**
     * 删除用户
     * */
    @WebMethod(operationName="remove")
    int remove(@WebParam(name = "id")  Integer id);

    /**
     * 批量删除用户
     * */
    @WebMethod(operationName="batchRemove")
    int batchRemove(@WebParam(name = "ids")  Integer[] ids);
}

UserServiceImpl 接口类(路径 src/main/java/com/fishpro/webservice/service/UserServiceImpl.java)


@WebService(
        targetNamespace = WsConst.NAMESPACE_URI, //wsdl命名空间
        name = "userPortType",                 //portType名称 客户端生成代码时 为接口名称
        serviceName = "userService",           //服务name名称
        portName = "userPortName",             //port名称
        endpointInterface = "com.fishpro.webservice.service.UserService")//指定发布webservcie的接口类,此类也需要接入@WebService注解
public class UserServiceImpl implements UserService {

    @Override
    public UserDto get(String id){
        if(null==id){
            return  null;
        }

        List<UserDto> list= getData();
        UserDto UserDto=null;
        for (UserDto user:list
                ) {
            if(id.equals(user.getUserId().toString())){
                UserDto=user;
                break;
            }
        }

        return UserDto;
    }

    @Override
    public List<UserDto> list(){
        List<UserDto> list=new ArrayList<>();

        list=getData();

        return list;
    }

    @Override
    public int count(){
        return getData().size();
    }

    @Override
    public int save(UserDto user){
        return 1;
    }

    @Override
    public int update(UserDto user){
        return 1;
    }

    @Override
    public int remove(Integer id){
        return 1;
    }

    @Override
    public int batchRemove(Integer[] ids){
        return 1;
    }

    /**
     * 模拟一组数据
     * */
    private List<UserDto> getData(){
        List<UserDto> list=new ArrayList<>();

        UserDto UserDto=new UserDto();
        UserDto.setUserId(1);
        UserDto.setUserName("admin");
        list.add(UserDto);

        UserDto=new UserDto();
        UserDto.setUserId(2);
        UserDto.setUserName("heike");
        list.add(UserDto);

        UserDto=new UserDto();
        UserDto.setUserId(3);
        UserDto.setUserName("tom");
        list.add(UserDto);

        UserDto=new UserDto();
        UserDto.setUserId(4);
        UserDto.setUserName("mac");
        list.add(UserDto);

        return  list;
    }

}

4 服务发布

编写 CxfWebServiceConfig(路径 src/main/java/com/fishpro/webservice/config/CxfWebServiceConfig.java)

import com.fishpro.websevice.service.UserService;
import com.fishpro.websevice.service.impl.UserServiceImpl;
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.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.xml.ws.Endpoint;

@Configuration
public class CxfWebServiceConfig {

   /**
    *
    * */
   @Bean("cxfServletRegistration")
   public ServletRegistrationBean dispatcherServlet(){

       return new ServletRegistrationBean(new CXFServlet(),"/ws/*");
   }
   /**
    * 申明业务处理类 当然也可以直接 在实现类上标注 @Service
    */
   @Bean
   public UserService userService() {
       return new UserServiceImpl();
   }

   /*
    * 非必要项
    */
   @Bean(name = Bus.DEFAULT_BUS_ID)
   public SpringBus springBus() {
       SpringBus springBus = new SpringBus();
       return springBus;
   }

   /*
    * 发布endpoint
    */
   @Bean
   public Endpoint endpoint( ) {
       EndpointImpl endpoint = new EndpointImpl(springBus(), userService());
       endpoint.publish("/user");//发布地址
       return endpoint;
   }
}

打开浏览器输入 http://localhost:8080/ws/user?wsdl 可以见到发布的效果

如何使用 Spring Boot 调用 WebService ,请阅读 Spring Boot 使用 CXF 调用 WebService 服务

5 问题

  1. cxf 的服务方法中,是不能使用java.util.Map作为参数的,因为本身不支持转换
    cxf对很多复杂类型支持并不友好,建议参数能使用简单的类型,就使用简单的类型

本项目源码 github 下载

spring boot 下开发webservice接口

1、引入pom依赖

  1.  
    <!-- 引入CXF jar包 -->
  2.  
    <dependency>
  3.  
    <groupId>org.apache.cxf</groupId>
  4.  
    <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
  5.  
    <version>3.3.3</version>
  6.  
    </dependency>

2、编写webservice服务端

2.1 新建接口,并添加targetNamespace,targetNamespace是接口所在包的倒序,如果不添加,在动态调用接口的时候,会报错误信息。

  1.  
     
  2.  
    import javax.jws.WebParam;
  3.  
    import javax.jws.WebService;
  4.  
     
  5.  
    // ~ File Information
  6.  
    /**
  7.  
    * @author zxy
  8.  
    * @date 2019年9月23日 下午2:45:10
  9.  
    * 类说明:定义接口,targetNamespace是当前所在包的倒序。
  10.  
    */
  11.  
    @WebService(targetNamespace="http://webservice.common.bmSystem.com")
  12.  
    public interface IHelloWord {
  13.  
     
  14.  
    // ~ Methods
  15.  
    public String say(@WebParam(name="helloName") String helloName);
  16.  
     
  17.  
    }

2.2 新建接口实现类,targetNamespace与实现接口保持一致,endpointInterface为接口所在包的全路径。

  1.  
     
  2.  
    import javax.jws.WebService;
  3.  
     
  4.  
    import org.springframework.stereotype.Component;
  5.  
     
  6.  
    import com.bmSystem.common.webservice.IHelloWord;
  7.  
     
  8.  
    // ~ File Information
  9.  
    /**
  10.  
    * @author zxy
  11.  
    * @date 2019年9月23日 下午2:46:18
  12.  
    * 类说明:接口实现类,targetNamespace是当前所在包的倒序。
  13.  
    */
  14.  
    @Component
  15.  
    @WebService(targetNamespace="http://webservice.common.bmSystem.com",
  16.  
    endpointInterface ="com.bmSystem.common.webservice.IHelloWord")
  17.  
    public class HelloWordImpl implements IHelloWord{
  18.  
     
  19.  
    @Override
  20.  
    public String say(String str) {
  21.  
    System.out.println("进入接口...");
  22.  
    return str;
  23.  
    }
  24.  
     
  25.  
    }

3、发布webservice接口

  1.  
    package com.bmSystem.common.sys.config.webservice;
  2.  
     
  3.  
    import javax.xml.ws.Endpoint;
  4.  
    import org.apache.cxf.Bus;
  5.  
    import org.apache.cxf.bus.spring.SpringBus;
  6.  
    import org.apache.cxf.jaxws.EndpointImpl;
  7.  
    import org.apache.cxf.transport.servlet.CXFServlet;
  8.  
    import org.springframework.beans.factory.annotation.Autowired;
  9.  
    import org.springframework.boot.web.servlet.ServletRegistrationBean;
  10.  
    import org.springframework.context.annotation.Bean;
  11.  
    import org.springframework.context.annotation.Configuration;
  12.  
     
  13.  
    import com.bmSystem.common.webservice.impl.HelloWordImpl;
  14.  
     
  15.  
    // ~ File Information
  16.  
    /**
  17.  
    * @author zxy
  18.  
    * @date 2019年9月23日 下午3:12:00
  19.  
    * 类说明:webservice发布,默认访问地址为:localhost:8080/services/helloWord?wsdl
  20.  
    *
  21.  
    */
  22.  
    @Configuration
  23.  
    public class WebServiceConfig {
  24.  
     
  25.  
    // ~ Fields
  26.  
    @Autowired
  27.  
    private HelloWordImpl helloWord;//接口实现类
  28.  
     
  29.  
    // ~ Methods
  30.  
     
  31.  
    /**
  32.  
    * 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
  33.  
    * 此方法被注释后:wsdl访问地址为http://127.0.0.1:8080/services/user?wsdl
  34.  
    * 去掉注释后:wsdl访问地址为:http://127.0.0.1:8080/soap/user?wsdl
  35.  
    * @return
  36.  
    */
  37.  
    /*
  38.  
    * @SuppressWarnings("all")
  39.  
    *
  40.  
    * @Bean public ServletRegistrationBean dispatcherServlet() { return new
  41.  
    * ServletRegistrationBean(new CXFServlet(), "/soap/*"); }
  42.  
    */
  43.  
     
  44.  
    @Bean(name = Bus.DEFAULT_BUS_ID)
  45.  
    public SpringBus springBus() {
  46.  
    return new SpringBus();
  47.  
    }
  48.  
     
  49.  
    @Bean
  50.  
    public Endpoint endpoint() {
  51.  
    EndpointImpl endpoint=new EndpointImpl(springBus(), helloWord);
  52.  
    endpoint.publish("/helloWord");//访问地址
  53.  
    return endpoint;
  54.  
    }
  55.  
     
  56.  
    }

4、开发webservice客户端调用,这里采用的是动态调用方式(推荐)

  1.  
     
  2.  
    import java.util.HashMap;
  3.  
    import java.util.Map;
  4.  
     
  5.  
    import org.apache.cxf.endpoint.Client;
  6.  
    import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
  7.  
     
  8.  
    import com.google.gson.Gson;
  9.  
     
  10.  
    /**
  11.  
    * @author zxy
  12.  
    * @date 2020年6月5日 上午9:05:06
  13.  
    * @Description : 动态调用webservice接口
  14.  
    */
  15.  
    public class TestWebservice {
  16.  
     
  17.  
    public static void main(String[] args) {
  18.  
    // 创建动态客户端
  19.  
    JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
  20.  
    Client client = dcf.createClient("http://127.0.0.1:8085/services/helloWord?wsdl");
  21.  
    // 需要密码的情况需要加上用户名和密码
  22.  
    // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
  23.  
    Object[] objects = new Object[0];
  24.  
    try {
  25.  
    // invoke("方法名",参数1,参数2,参数3....);
  26.  
    //json的形式
  27.  
    Map<String,Object> params=new HashMap<String,Object>();
  28.  
    params.put("name", "dasda");
  29.  
    Gson gson = new Gson();
  30.  
    String json = gson.toJson(params);
  31.  
    objects = client.invoke("say", json);
  32.  
    System.out.println("返回数据:" + objects[0]);
  33.  
    } catch (java.lang.Exception e) {
  34.  
    e.printStackTrace();
  35.  
    }
  36.  
    }
  37.  
    }

axis方式调用webservice接口:

  1.  
    import javax.xml.namespace.QName;
  2.  
    import javax.xml.rpc.ParameterMode;
  3.  
     
  4.  
    import org.apache.axis.client.Call;
  5.  
    import org.apache.axis.client.Service;
  6.  
    import org.apache.axis.encoding.XMLType;
  7.  
     
  8.  
    public class Test01 {
  9.  
    public static void main(String[] args) {
  10.  
    try {
  11.  
    //1、直接引用远程的wsdl文件
  12.  
    String endpoint = "接口访问路径";
  13.  
    Service service = new Service();
  14.  
    Call call = (Call) service.createCall(); //创建服务
  15.  
    call.setTargetEndpointAddress(endpoint);
  16.  
    //2、定义报名和接口方法
  17.  
    call.setOperationName(new QName("targetNamespace", //wsdl文件中的targetNamespace
  18.  
    "getAllResourceDetail") //接口实现功能的方法
  19.  
    );
  20.  
     
  21.  
    //3、设置参数
  22.  
    call.addParameter("resType", XMLType.XSD_INT,ParameterMode.IN);// 接口的参数
  23.  
    call.addParameter("nodeIndexCode",XMLType.XSD_STRING,ParameterMode.IN);// 接口的参数
  24.  
    call.setReturnType(XMLType.XSD_STRING);// 设置返回类型
  25.  
     
  26.  
    int resType=1000;
  27.  
    String nodeIndexCode="";
  28.  
     
  29.  
    //4、给方法传递参数,并且调用方法
  30.  
    String result = (String) call.invoke(new Object[] {nodeIndexCode ,resType});
  31.  
    System.out.println(result);
  32.  
    } catch (Exception e) {
  33.  
    e.printStackTrace();
  34.  
    }
  35.  
    }
  36.  
    }
原文地址:https://www.cnblogs.com/zhoading/p/13853272.html