前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebService: SpringBoot集成WebService实践二

WebService: SpringBoot集成WebService实践二

作者头像
Freedom123
发布2024-03-29 13:38:55
880
发布2024-03-29 13:38:55
举报
文章被收录于专栏:DevOpsDevOps

简介

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

一、Pom文件配置

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

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.rh</groupId>
    <artifactId>ws_test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ws_test</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <!-- 核心启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- web启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- webService-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>

        <!-- CXF webservice -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.2.1</version>
        </dependency>
        <!-- CXF webservice -->
		
		<!-- 一下是客户端开发所需jar包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.18.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.axis/axis -->
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis</artifactId>
            <version>1.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.xml/jaxrpc -->
        <dependency>
            <groupId>javax.xml</groupId>
            <artifactId>jaxrpc</artifactId>
            <version>1.1</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.0.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-discovery/commons-discovery -->
        <dependency>
            <groupId>commons-discovery</groupId>
            <artifactId>commons-discovery</artifactId>
            <version>0.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-discovery/commons-discovery -->
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.6.3</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

二、服务端代码

ServerServiceDemo接口代码:

代码语言:javascript
复制
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);
}

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

一般我们都会写一个接口,然后再写一个实现接口的实现类,但是这不是强制性的 @WebService 注解表明是一个webservice服务。name:对外发布的服务名, 对应于<wsdl:portType name=“ServerServiceDemo”></wsdl:portType>,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:对应于<wsdl:service name=“ServerServiceDemoImplService”></wsdl:service>, portName:对应于<wsdl:port binding=“tns:ServerServiceDemoImplServiceSoapBinding” name=“ServerServiceDemoPort”></wsdl:port>

@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接口实现类代码:

代码语言:javascript
复制
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 "调用成功";
    }
}

WebServiceDemoTwo 代码:

代码语言:javascript
复制
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);
}

WebServiceDemoTwoImpl 代码

代码语言:javascript
复制
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;
    }
}

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配置代码:

代码语言:javascript
复制
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;
    }
}

启动项目后访问: http://localhost:8083/services/

三、客户端编码

WebServiceTest 代码:

代码语言:javascript
复制
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();
        }
    }
}

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

代码语言:javascript
复制
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);
    }
}

注意: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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 一、Pom文件配置
  • 二、服务端代码
  • 三、客户端编码
  • 四、客户端编码(axis方式)
  • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档