• WebService: SpringBoot集成WebService实践二



    简介

    该篇为上一篇的延伸,上一篇知识简单介绍了WebService 的使用,该篇会对代码中模块及功能进行详细介绍,以作对WebService 进一步的理解。

    一、Pom文件配置

    该Pom文件中包含了Provider的配置和Consumer的配置,请自行复制所需。

    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-parentartifactId>
            <version>2.4.0version>
            <relativePath/> 
        parent>
        <groupId>com.rhgroupId>
        <artifactId>ws_testartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>ws_testname>
        <description>Demo project for Spring Bootdescription>
    
        <properties>
            <java.version>1.8java.version>
        properties>
    
        <dependencies>
    
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starterartifactId>
            dependency>
    
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-web-servicesartifactId>
            dependency>
    
            
            <dependency>
                <groupId>org.apache.cxfgroupId>
                <artifactId>cxf-spring-boot-starter-jaxwsartifactId>
                <version>3.2.1version>
            dependency>
            <dependency>
                <groupId>org.apache.cxfgroupId>
                <artifactId>cxf-rt-transports-httpartifactId>
                <version>3.2.1version>
            dependency>
            
    		
    		
            <dependency>
                <groupId>org.hibernategroupId>
                <artifactId>hibernate-validatorartifactId>
                <version>6.0.18.Finalversion>
            dependency>
    
            
            <dependency>
                <groupId>org.apache.axisgroupId>
                <artifactId>axisartifactId>
                <version>1.4version>
            dependency>
    
            
            <dependency>
                <groupId>javax.xmlgroupId>
                <artifactId>jaxrpcartifactId>
                <version>1.1version>
            dependency>
    
            <dependency>
                <groupId>commons-logginggroupId>
                <artifactId>commons-loggingartifactId>
                <version>1.0.4version>
            dependency>
    
            
            <dependency>
                <groupId>commons-discoverygroupId>
                <artifactId>commons-discoveryartifactId>
                <version>0.5version>
            dependency>
    
            
            <dependency>
                <groupId>wsdl4jgroupId>
                <artifactId>wsdl4jartifactId>
                <version>1.6.3version>
            dependency>
    
        dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                plugin>
            plugins>
        build>
    
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106

    二、服务端代码

    ServerServiceDemo接口代码:

    package com.rh.ws_test;
    
    import javax.jws.WebMethod;
    import javax.jws.WebParam;
    import javax.jws.WebService;
    
    @WebService(name = "ServerServiceDemo", targetNamespace = "http://server.webservice.example.com")
    public interface ServerServiceDemo {
        @WebMethod
        String emrService(@WebParam String data);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    WebService涉及到的有这些 "四解三类 ", 即四个注解,三个类 @WebMethod, @WebService,@WebResult,@WebParam,SpringBus,Endpoint,EndpointImpl

    一般我们都会写一个接口,然后再写一个实现接口的实现类,但是这不是强制性的
    @WebService 注解表明是一个webservice服务。name:对外发布的服务名, 对应于,targetNamespace:命名空间,一般是接口的包名倒序, 实现类与接口类的这个配置一定要一致这种错误Exception in thread “main” org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name xxxx 对应于argetNamespace=“http://server.webservice.example.com”, endpointInterface:服务接口全路径(如果是没有接口,直接写实现类的,该属性不用配置), 指定做SEI(Service EndPoint Interface)服务端点接口, serviceName:对应于, portName:对应于

    @WebMethod表示暴露的服务方法, 这里有接口ServerServiceDemo存在,在接口方法已加上@WebMethod, 所以在实现类中不用再加上,否则就要加上 operationName: 接口的方法名, action: 没发现又什么用处, exclude: 默认是false, 用于阻止将某一继承方法公开为web服务

    @WebResult表示方法的返回值, name:返回值的名称, partName: , targetNamespace:,
    header: 默认是false, 是否将参数放到头信息中,用于保护参数,默认在body中

    @WebParam name:接口的参数, partName:, targetNamespace:
    header: 默认是false, 是否将参数放到头信息中,用于保护参数,默认在body中, model:WebParam.Mode.IN/OUT/INOUT

    ServerServiceDemoImpl接口实现类代码:

    package com.rh.ws_test;
    
    import org.springframework.stereotype.Component;
    
    import javax.jws.WebParam;
    import javax.jws.WebService;
    
    @Component
    @WebService(name = "ServerServiceDemo", targetNamespace = "http://server.webservice.example.com",
            endpointInterface = "com.rh.ws_test.ServerServiceDemo")
    public class ServerServiceDemoImpl implements ServerServiceDemo{
    
        @Override
        public String emrService(@WebParam String data) {
            if(null == data || "".equals(data.trim())){
                return "传入的参数为空";
            }
            return "调用成功";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    WebServiceDemoTwo 代码:

    package com.test.springboot.service;
    
    import javax.jws.WebMethod;
    import javax.jws.WebParam;
    import javax.jws.WebService;
    
    @WebService(name = "WebServiceDemoTwo", targetNamespace = "http://server.webservice.example.com")
    public interface WebServiceDemoTwo {
        @WebMethod
        String emrServiceThree(@WebParam String data);
    
        @WebMethod
        String emrServiceFour(@WebParam String data);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    WebServiceDemoTwoImpl 代码

    package com.test.springboot.service.impl;
    
    import com.test.springboot.service.WebServiceDemoTwo;
    import org.springframework.stereotype.Component;
    
    import javax.jws.WebService;
    
    @Component
    @WebService(name = "WebServiceDemoTwo", targetNamespace = "http://server.webservice.example.com",
            endpointInterface = "com.test.springboot.service.WebServiceDemoTwo")
    public class WebServiceDemoTwoImpl implements WebServiceDemoTwo {
        @Override
        public String emrServiceThree(String data) {
            return null;
        }
    
        @Override
        public String emrServiceFour(String data) {
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Apache CXF 核心架构是以BUS为核心,整合其他组件。Bus是CXF的主干, 为共享资源提供一个可配置的场所,作用类似于Spring的ApplicationContext,这些共享资源包括WSDl管理器、绑定工厂等。通过对BUS进行扩展,可以方便地容纳自己的资源,或者替换现有的资源。默认Bus实现基于Spring架构,通过依赖注入,在运行时将组件串联起来。BusFactory负责Bus的创建。默认的BusFactory是SpringBusFactory,对应于默认的Bus实现。在构造过程中,SpringBusFactory会搜索META-INF/cxf(包含在 CXF 的jar中)下的所有bean配置文件。根据这些配置文件构建一个ApplicationContext。开发者也可以提供自己的配置文件来定制Bus。

    WebServiceConfig配置代码:

    package com.test.springboot.config;
    
    import com.test.springboot.service.WebServiceDemo;
    import com.test.springboot.service.WebServiceDemoTwo;
    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.xml.ws.Endpoint;
    
    @Configuration
    public class WebServiceConfig {
        @Autowired
        private WebServiceDemo serverServiceDemo;
    
        @Autowired
        private WebServiceDemoTwo serverServiceDemoTwo;
    
        @Bean(name = Bus.DEFAULT_BUS_ID)
        public SpringBus springBus() {
            return new SpringBus();
        }
    
        /**
         * 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
         * 此方法被注释后, 即不改变前缀名(默认是services), wsdl访问地址为 http://127.0.0.1:8080/services/ws/api?wsdl
         * 去掉注释后wsdl访问地址为:http://127.0.0.1:8080/soap/ws/api?wsdl
         * http://127.0.0.1:8080/soap/列出服务列表 或 http://127.0.0.1:8080/soap/ws/api?wsdl 查看实际的服务
         * 新建Servlet记得需要在启动类添加注解:@ServletComponentScan
         *
         * 如果启动时出现错误:not loaded because DispatcherServlet Registration found non dispatcher servlet dispatcherServlet
         * 可能是springboot与cfx版本不兼容。
         * 同时在spring boot2.0.6之后的版本与xcf集成,不需要在定义以下方法,直接在application.properties配置文件中添加:
         * cxf.path=/service(默认是services)
         */
    //    @Bean
    //    public ServletRegistrationBean dispatcherServlet() {
    //        return new ServletRegistrationBean(new CXFServlet(), "/aaa/*");
    //    }
        @Bean
        public ServletRegistrationBean newServlet() {
            return new ServletRegistrationBean(new CXFServlet(), "/aaa/*");
        }
    
        @Bean
        @Qualifier("sBEASEASImportClaimChannelServiceInfoSrv")
        public Endpoint endpoint() {
            EndpointImpl endpoint = new EndpointImpl(springBus(), serverServiceDemo);
            endpoint.publish("/bbb");
            return endpoint;
        }
    
        @Bean
        @Qualifier("sBEASEASImportClaimChannelServiceInfoSrx")
        public Endpoint endpointTwo() {
            EndpointImpl endpoint = new EndpointImpl(springBus(), serverServiceDemoTwo);
            endpoint.publish("/ccc");
            return endpoint;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    启动项目后访问: http://localhost:8083/services/
    在这里插入图片描述

    三、客户端编码

    WebServiceTest 代码:

    package com.test.springboot.webservice;
    
    import org.apache.cxf.endpoint.Client;
    import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
    
    public class WebServiceTest {
        public static void main(String[] args) {
            String url1 = "http://localhost:8080/test/bbb?wsdl";
            String url2 = "http://localhost:8080/test/ccc?wsdl";
    //        client2(url2);
            client1(url1);
        }
    
        // 创建动态客户端
        public static void client1(String url) {
            JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
            Client client = dcf.createClient(url);
            Object[] objects = new Object[0];
            try {
                // invoke("方法名",参数1,参数2,参数3....);
                objects = client.invoke("emrService", "zhangsan123456");
                System.out.println("emrService返回数据:" + objects[0]);
                client.destroy();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        // 创建动态客户端
        public static void client2(String url) {
            JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
            Client client = dcf.createClient(url);
            Object[] objects = new Object[0];
            try {
                // invoke("方法名",参数1,参数2,参数3....);
                objects = client.invoke("emrServiceThree", "zhangsan789");
                System.out.println("emrServiceThree返回数据:" + objects[0]);
                client.destroy();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    四、客户端编码(axis方式)

    package com.rh.ws_test.client;
    
    import org.apache.axis.client.Call;
    import org.apache.axis.client.Service;
    import org.apache.axis.encoding.XMLType;
    
    import javax.xml.namespace.QName;
    import javax.xml.rpc.ParameterMode;
    import java.net.URL;
    
    public class TestSoap {
        public static void main(String[] args) throws Exception {
            //一般如果没有注解targetNamespace的话,默认生成的就是接口这个文件的路径名
    //        String nameSpaceURI = "http://service.cm.com";
            String nameSpaceURI = "http://server.webservice.example.com";
    //        String publishUrl = "http://localhost:8087/services/ServiceMonitor?wsdl";
            String publishUrl = "http://localhost:8083/services/ws/api?wsdl";
            Service service = new Service();
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(new URL(publishUrl));
            //指定接口路径,要调用的方法名
    //        call.setOperationName(new QName(nameSpaceURI, "monitor"));
            call.setOperationName(new QName(nameSpaceURI, "emrService"));
            //如果没用@WebParam(name="name")来表明参数名,则方法的入参是啥,这边就必须传一样的参数名才行。不然报错。
            call.addParameter("arg0", XMLType.XSD_STRING, ParameterMode.IN);
    //        call.addParameter("age", XMLType.XSD_INT, ParameterMode.IN);
            call.setReturnType(XMLType.XSD_STRING);
            String name = "zhanglifeng";
            int age = 18;
            Object[] obj = new Object[] { name};
            String result = (String) call.invoke(obj);
    
            System.out.println(result);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    注意:springboot开发webservice和axis组件开发webservice用法上有点区别

    小结

    这里的访问路径的关系梳理:http://localhost:8080/test/ccc?wsdl

    客户端调用时,确定访问路径后,我们调用时,要指定具体的方法名,可以直接在页面上看到。这样,就可以向具体的方法发起请求了。

    参考地址:https://blog.csdn.net/Brave_heart4pzj/article/details/110916127
    https://blog.csdn.net/Brave_heart4pzj/article/details/126709107

  • 相关阅读:
    P1875 佳佳的魔法药水
    关于AbstractQueuedSynchronizer(JDK1.8)的一点理解.
    DeFi 入门必备:你需要了解的 DeFi 重要词语
    Pytorch之ResNet图像分类
    1763. 最长的美好子字符串-贪心算法
    撤销git本地修改(万能)
    强化学习 double DQN 代码注释解析
    助力防疫,基于安防摄像头的人脸佩戴口罩检测
    语音增强——基本谱减法及其python实现
    JavaScript 面试题
  • 原文地址:https://blog.csdn.net/zhanggqianglovec/article/details/127661551