asp.net通过webservice调用java接口全过程_SpringBoot2.x系列教程|整合Web Service实现远程接口调用

SpringBoot2.x系列教程--SpringBoot整合Web Service实现远程接口调用

作者:一一哥

上一章节中,我带大家学习了Web Service的理论知识,接下来在本节中,我带大家实现SpringBoot中整合Web Service,实现远程接口调用。

SpringBoot整合Web Service的详细实现

一. 创建通用模块

本项目中,我们需要进行远程接口的调用,也就是需要有一个A项目来调用B项目里的接口,然后A,B两个项目都需要依赖一些共同的内容,所以我们首先创建这个被共同依赖的通用模块C。

1371ed561f1306ddd065f33a11cd2d51.png

1. 创建通用的实体类User

package com.yyg.boot.domain;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;/** * @Author 一一哥Sun * @Date Created in 2020/5/9 * @Description Description */@Data@NoArgsConstructor@AllArgsConstructorpublic class User implements Serializable {    private Long id;    private String username;    private String address;}

2. 定义通用的MyService接口

9b4d47d98e329d0b4fd773e71ba955ba.png
  • 先在接口类上添加@WebService注解,代表发布一个WebService服务。
  • 给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。
  • 如果希望某个方法不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。
  • 如果一个类上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。
  • protected、private、final、static方法不能对外公开。
package com.yyg.boot.service;import com.yyg.boot.domain.User;import javax.jws.WebService;import java.util.List;/** * @Author 一一哥Sun * @Date Created in 2020/5/9 * @Description Description */@WebService(name = "MyService", // 暴露服务名称        targetNamespace = "http://service.boot.yyg.com"// 命名空间,一般是接口的包名倒序)public interface MyService {    String sayHello(String msg);    List getUsers();}

二. 创建Web Service中的Server端项目

完整项目结构如下图所示:

6efeefc9f88f20ff4d4a3ceaae70f548.png

1. 添加依赖包

com.yyg.boot    demo46_commons    1.0-SNAPSHOTorg.springframework.boot    spring-boot-starter-web-servicesorg.apache.cxf    cxf-rt-frontend-jaxws    3.1.12org.apache.cxf    cxf-rt-transports-http    3.1.12

注意:网上有网友用cxf-spring-boot-starter-jaxws这个依赖包,但是我在Spring Boot2.2.5的环境中,使用该依赖会导致如下异常:

java.lang.ClassNotFoundException: org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer

所以我这里不适用该依赖,而是使用cxf-rt-frontend-jaxws与cxf-rt-transports-http依赖包。

2. 定义CXFServlet的配置类

  • 通过EndPoint(端点服务)发布一个webService。Endpoint也是jdk提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是本地的服务地址,二是提供服务的类。它位于javax.xml.ws.*包中。
  • Endpoint.publish(String address, Object implementor) 静态方法在给定地址处针对指定的实现者对象创建并发布端点。
package com.yyg.boot.config;import com.yyg.boot.service.MyService;import com.yyg.boot.service.impl.MyServiceImpl;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;/** * @Author 一一哥Sun * @Date Created in 2020/5/9 * @Description Description */@Configurationpublic class CxfConfig {    @Bean    public ServletRegistrationBean createServletRegistrationBean() {        return new ServletRegistrationBean(new CXFServlet(), "/myService/*");    }    @Bean(name = Bus.DEFAULT_BUS_ID)    public SpringBus springBus() {        return new SpringBus();    }    @Bean    public MyService myService() {        return new MyServiceImpl();    }    @Bean    public Endpoint endpoint() {        EndpointImpl endpoint = new EndpointImpl(springBus(), myService());        endpoint.publish("/api");        return endpoint;    }}

注意:在该配置类中,网上有不少文章,在注册CXFServlet的时候,定义的方法名称都是dispatcherServlet,注意不要这么定义!!!否则会导致ErrorMvcAutoConfiguration错误.

//注意:该方法的名称不能使用dispatcherServlet(),否则会导致ErrorMvcAutoConfiguration错误.    //org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration    //required a bean of type 'org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath'    // that could not be found.//    @Bean//    public ServletRegistrationBean dispatcherServlet() {//        return new ServletRegistrationBean(new CXFServlet(), "/myService/*");//    }

3. 定义MyServiceImpl接口实现类

在实现类中也有添加@WebService注解,指定serviceName,targetNamespace,endpointInterface属性。

package com.yyg.boot.service.impl;import com.yyg.boot.domain.User;import com.yyg.boot.service.MyService;import javax.jws.WebService;import java.util.ArrayList;import java.util.Date;import java.util.List;/** * @Author 一一哥Sun * @Date Created in 2020/5/9 * @Description Description */@WebService(serviceName = "MyService", // 与接口中指定的服务name一致        targetNamespace = "http://service.boot.yyg.com", // 与接口中的命名空间一致,一般是接口的包名倒        endpointInterface = "com.yyg.boot.service.MyService"// 接口地址)public class MyServiceImpl implements MyService {    @Override    public String sayHello(String msg) {        return "收到的信息是:--->" + msg + ",现在时间是:--->" + new Date();    }    @Override    public List getUsers() {        List users = new ArrayList<>();        users.add(new User(1L, "一一哥", "北京"));        users.add(new User(2L, "一一哥", "上海"));        return users;    }}

4.创建application.yml配置文件

server:  port: 8080spring:  application:    name: web-service-server

5. 创建入口类

package com.yyg.boot;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * @Author 一一哥Sun * @Date Created in 2020/5/9 * @Description Description */@SpringBootApplicationpublic class WebServiceApplication {    public static void main(String[] args) {        SpringApplication.run(WebServiceApplication.class, args);    }}

6. 启动Server端项目

会发现在控制台中打印出如下启动信息。

348596511b8e01c5136aeaaf95abe6d3.png

然后我们在浏览器中输入如下地址:http://localhost:8080/myService/api?wsdl

会看到如下xml信息:

ce0343d6ce9fe3b6751b0643ebad5beb.png

在这份xml文件中,指明了我们在service中定义的接口等信息。

三. 创建Web Service的client项目

1. 添加依赖包

com.yyg.boot    demo46_commons    1.0-SNAPSHOTorg.apache.cxf    cxf-rt-frontend-jaxws    3.1.12org.apache.cxf    cxf-rt-transports-http    3.1.12

2. 创建application.yml配置文件

定义端口为8081。

server:  port: 8081spring:  application:    name: web-service-client

3. 定义一个Controller进行测试

package com.yyg.boot.web;import com.yyg.boot.domain.User;import com.yyg.boot.service.MyService;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;/** * @Author 一一哥Sun * @Date Created in 2020/5/9 * @Description Description */@RestControllerpublic class ClientController {    /**     * webservice接口地址     */    private static String address = "http://localhost:8080/myService/api?wsdl";    @GetMapping("/show")    public String showMsg() {        try {            // 代理工厂            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();            // 设置代理地址            jaxWsProxyFactoryBean.setAddress(address);            //添加用户名密码拦截器            //jaxWsProxyFactoryBean.getOutInterceptors().add(new LoginInterceptor("root","admin"));;            // 设置接口类型            jaxWsProxyFactoryBean.setServiceClass(MyService.class);            // 创建一个代理接口实现            MyService service = (MyService) jaxWsProxyFactoryBean.create();            // 调用代理接口的方法调用并返回结果            return service.sayHello("hello");        } catch (Exception e) {            e.printStackTrace();            return "error";        }    }    @GetMapping("/users")    public List showUsers() {        try {            // 代理工厂            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();            // 设置代理地址            jaxWsProxyFactoryBean.setAddress(address);            // 设置接口类型            jaxWsProxyFactoryBean.setServiceClass(MyService.class);            // 创建一个代理接口实现            MyService service = (MyService) jaxWsProxyFactoryBean.create();            // 调用代理接口的方法调用并返回结果            return service.getUsers();        } catch (Exception e) {            e.printStackTrace();            return null;        }    }}

4. 创建应用程序入口类

package com.yyg.boot;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * @Author 一一哥Sun * @Date Created in 2020/5/9 * @Description Description */@SpringBootApplicationpublic class CxfClientApplication  {    public static void main(String[] args){        SpringApplication.run(CxfClientApplication.class,args);    }}

5. 启动项目进行测试

测试show接口:

发现展示如下信息,说明我们的客户端已经成功的调用了服务端的接口,实现了RPC跨进程通信。

71c188e4c845a0c0adc0ffa1607fd18e.png

测试users接口:

发现展示如下信息,说明我们的客户端已经成功的调用了服务端的接口,也实现了RPC跨进程通信。

9382a9b1d603b836d23708a83adb6267.png

四. WSDL文件解析

1. WSDL报文概述

fd2122462672236a09311cc16670fffb.png
        定义 web service 使用的数据类型            每个消息均由一个或多个部件组成。可以把它当做java中一个函数调用的参数。            它类似Java中的一个函数库(或一个模块、或一个类)            为每个端口定义消息格式和协议细节。    

2. WSDL报文之wsdl:definitions

96c5a833a70e83ead4cc0091368bf0a4.png

3. WSDL报文之wsdl:types

我们java中定义的服务接口中某个方法的输入参数和返回值。

4a9b418ef99a5136da7365911f934a2e.png
c4de7716d96d0bf7f1da6816bc6fa05c.png

4. WSDL报文之wsdl:message

通信消息的数据结构的抽象类型化定义,使用Types所定义的类型来定义整个消息的数据结构。

da2425129c40edc1723f0b773c134b65.png

WebService中每个方法包含两部分:

  • 一个是方法的输入参数,另一个是方法的输出参数。
  • 其实质都是基于SOAP协议将其封装为消息,所以每一个方法对应有两个消息,一个输入一个输出回应。简单而言,就是方法和Message的关系是N:2N的关系,一对二。
  • Message中的具体内容是part,结合前面可知,message中的part内容请到前面定义过的types中去看,它会引用之前的type相关内容。

5. WSDL报文之wsdl:portType

  • portType = 接口
  • operation = 接口中定义的方法 
a1dda96e839ded1f6ad84ee1fcfca192.png

6. WSDL报文之wsdl:binding

特定端口类型的具体协议和数据格式规范的绑定。

2b23648d0edd1a599d04ee45280a633e.png

7. WSDL报文之wsdl:service

负责将网络通信地址赋给一个具体的绑定。

53a590d0db820a5c93eaf0759f755dbf.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值