java如何写别接口给人调用(WebService)-XXOO

前言

计算机语言分类有很多,如C、C++、C#、JavaPHPPython等等,她们有各自的特性及擅长的领域,但她们各自又不是全能的。在一个稍微大型一点的项目都会用到多种语言共同完成,那么这些编程语言如何进行通信呢。什么意思呢,就是比如说我Java写的一个方法,其他编程语言要怎么去调用呢?这就是本文要探讨的问题了。

一般来说,方法层面的编程语言通信用的是网络接口形式,只暴露出形参和结果供别人调用。接口一般分为接口定义者和接口调用者,定义者可以规定接收参数的类型及返回形式,而接口定义者则只能完全按照接口定义者规定的参数进行访问。就叫是我们所说的webService(网络服务)。

以前的做法是利用XML作接口格式定义,然后通过Http做通讯和请求,如大名鼎鼎的SOAP,其实现在也是的,只不过现在流行RestFul风格的Rest接口形式,但用的还是XML+HTTP,那这两者有啥区别呢?最大的区别就是SOAP返回的主要是XML格式,有时还需要附带一些辅助文件,而Rest则还可以返回JSON类型的字符串,减少了很多繁乱的XML标签。

由于这篇文章之前是转载的,比较乱,在这里说声抱歉!!!!!

现在重新写一下,见谅。


一、接口给外部调用(举例)

1.我们的CURD暴露到Controller层,让前端调用。外部项目调用一般通过HttpClient/OkHttp等直接调用。这种方式是比较多的。

2.WebService

3.服务间调用(注册中心等等)

......

这里就以WebService示例,服务端如何暴露接口,客户端如何调用。

二、WebService

1.定义

WebService是一种远程调用技术,也叫XML Web Service WebService,是一种可以接收从Internet或者Internet上的其他系统中传递过来的请求,轻量级的独立的通信技术。是通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。

SOAP:全名为(Simple Object Access Protocol)简单对象存取协议。是XML Web Service的通信协议。当用户通过UDDI找到你的WSDL描述文档后,他可以通过SOAP调用你建立的Web服务中的一个或多个操作。SOAP是XML 文档形式的调用方法的规范,他可以支持不同的底层接口,像HTTP/HTTPS或者SMTP。

XML:(Extensible Markup Language)扩展型可标记语言。面向短期的临时数据处理、面向万维网(WWW), 是SAOP的基础。

WSDL:(Web Services Description Language)WSDL是用于说明一组SOAP消息以及如何交换这些消息 的XML文档。

2.实现方式

2.1.Jdk方式

1.服务端 定义接口类 接口实现类 发布类

2.main方法运行(发布)

3.cmd 命令 执行 wsimport -s 生成文件路径 -keep 你的wsdl Url

wsimport -s D:\YlDream\WorkSpace\springbootDevelop\springboot-test\src\client -keep http://localhost:8019/api_server/webservice?wsdl

4.客户端调用

WebService服务端

定义WebService 接口
package com.yl.springboottest.api.webservice.server;

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

/**
 * 描述: 定义WebService 接口
 *
 * @WebService 表示此类是一个元数据注释(JSR 181) 关于JSR181本文不做涉及
 * @WebMethod 表示表示此方法是要被发布出去的方法,
 * 仅支持在使用@WebService注解标注的类中使用@WebMethod注解
 *
 * @author: yanglin
 * @Date: 2020-11-19-10:19
 * @Version: 1.0
 */
@WebService
public interface IWebService {

    @WebMethod
    String firstWebServiceApi(String name);
}
WebService 接口实现
package com.yl.springboottest.api.webservice.server;

import lombok.extern.slf4j.Slf4j;

import javax.jws.WebService;

/**
 * 描述: WebService 接口实现
 *
 * @author: yanglin
 * @Date: 2020-11-19-10:19
 * @Version: 1.0
 */
@Slf4j
@WebService
public class WebServiceImpl implements IWebService{

    @Override
    public String firstWebServiceApi(String name) {
        name = "你好,"+name+",这是我的第一个WebService";
        log.info("firstWebServiceApi start {}", name);
        return name;
    }
}
WebService 服务端发布

三种发布方式

1.main方法运行(测试)

2.使用ServletContextListener监听器发布WebService

3.使用Servlet发布WebService

 

package com.yl.springboottest.api.webservice.server;

import lombok.extern.slf4j.Slf4j;

import javax.xml.ws.Endpoint;

/**
 * 描述: WebService 操作 服务端
 * 1.main方法运行(测试)
 * @author: yanglin
 * @Date: 2020-11-19-10:15
 * @Version: 1.0
 */
@Slf4j
public class WebServiceServerT1 {


    public static void main(String[] args) {
        /**
         * 1.定义一个WebService的发布地址(暴露出来,让外界访问)
         */
        String webAddress = "http://localhost:8019/api_server/webservice";

        /**
         * 2.使用Endpoint类提供的publish方法发布WebService,发布时确保端口没有被占用
         */
        Endpoint.publish(webAddress, new WebServiceImpl());
        log.info("WebService 发布成功,URL= {}", webAddress+"?wsdl");

    }
}
package com.yl.springboottest.api.webservice.server;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.xml.ws.Endpoint;

/**
 * 描述: 2.用于发布WebService的监听器
 * 使用Servlet3.0提供的@WebListener注解将实现了ServletContextListener接口的
 * WebServicePublishListener类标注为一个Listener
 *
 * @author: yanglin
 * @Date: 2020-11-19-10:52
 * @Version: 1.0
 */
@Slf4j
@WebListener
public class WebServicePublishListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        log.info("contextDestroyed start ");
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        /**
         * 1.定义一个WebService的发布地址(暴露出来,让外界访问)
         */
        String webAddress = "http://localhost:8019/api_server/webservice";

        /**
         * 2.使用Endpoint类提供的publish方法发布WebService,发布时确保端口没有被占用
         */
        Endpoint.publish(webAddress, new WebServiceImpl());
        log.info("WebServicePublishListener WebService 发布成功,URL= {}", webAddress+"?wsdl");
    }
}
package com.yl.springboottest.api.webservice.server;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.xml.ws.Endpoint;

/**
 * 描述: 3.用于发布WebService的Servlet
 *
 * 使用Servlet3.0提供的@WebServlet注解将继承HttpServlet类的普通Java类标注为一个Servlet
 *
 * 将value属性设置为空字符串,这样WebServicePublishServlet就不提供对外访问的路径
 * loadOnStartup属性设置 WebServicePublishServlet的初始化时机
 *
 * @author: yanglin
 * @Date: 2020-11-19-10:55
 * @Version: 1.0
 */
@Slf4j
@WebServlet(value = "", loadOnStartup = 0)
public class WebServicePublishServlet extends HttpServlet {

    /**
     * 在WebServicePublishServlet初始化时发布WebService
     * @throws ServletException
     */
    @Override
    public void init() throws ServletException {
        /**
         * 1.定义一个WebService的发布地址(暴露出来,让外界访问)
         */
        String webAddress = "http://localhost:8019/api_server/webservice";

        /**
         * 2.使用Endpoint类提供的publish方法发布WebService,发布时确保端口没有被占用
         */
        Endpoint.publish(webAddress, new WebServiceImpl());
        log.info("WebServicePublishServlet WebService 发布成功,URL= {}", webAddress+"?wsdl");
    }
}

main方法启动成功(监听器/Servlet则是项目启动成功),访问定义的地址 

http://localhost:8019/api_server/webservice?wsdl 

一定要记得加?wsdl 

 WebService客户端

通过wsdl生成对应的客户端文件,复制到项目所在目录

 

新建测试类-客户端调用

package com.yl.springboottest.api.webservice.client;

import lombok.extern.slf4j.Slf4j;

/**
 * 描述: WebService 操作 客户端 直接调用
 *
 * @author: yanglin
 * @Date: 2020-11-19-10:45
 * @Version: 1.0
 */
@Slf4j
public class WebServiceClientT1 {

    public static void main(String[] args) {
        WebServiceImplService factory = new WebServiceImplService();
        WebServiceImpl serviceImpl = factory.getWebServiceImplPort();
        String result = serviceImpl.firstWebServiceApi("张三");
        log.info("WebServiceClientT1 result {}", result);

    }
}

2.2.CXF方式操作WebService

maven pom

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-core</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>3.2.5</version>
        </dependency>

 Cxf服务端

package com.yl.springboottest.api.webservice.server.cxf;


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

/**
 * 描述: CXF 方式操作WebService
 *
 * @author: yanglin
 * @Date: 2020-11-19-11:02
 * @Version: 1.0
 */
@WebService(targetNamespace = "http://yldream.com/" ,name = "cxfPortType")
public interface ICXFWebService {

    /**
     * 获取全部用户信息
     */
    @WebMethod(operationName = "getCxfApi")
    String cxfWebServiceApi(String name);
}
package com.yl.springboottest.api.webservice.server.cxf;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.jws.WebService;

/**
 * 描述: XF 方式操作WebService
 *
 * @author: yanglin
 * @Date: 2020-11-19-11:05
 * @Version: 1.0
 */
@Slf4j
@Service
@WebService(
        targetNamespace = "http://yldream.com/", //wsdl命名空间
        name = "cxfPortType",                 //portType名称 客户端生成代码时 为接口名称
        serviceName = "cxfWebService",           //服务name名称
        portName = "cxfPortName",             //port名称
        endpointInterface = "com.yl.springboottest.api.webservice.server.cxf.ICXFWebService")//指定发布webservcie的接口类,此类也需要接入@WebService注解

public class CXFWebServiceImpl implements ICXFWebService{

    @Override
    public String cxfWebServiceApi(String name) {
        name = "你好,"+name+",这是我的第一个WebService";
        log.info("cxfWebServiceApi start {}", name);
        return name;
    }
}

 

package com.yl.springboottest.api.webservice.server.cxf;

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;

/**
 * 描述: springboot cxf 操作WebService
 *
 * 配置成功,URL访问  http://localhost:8019/api_server/api?wsdl
 *
 * @author: yanglin
 * @Date: 2020-11-19-11:07
 * @Version: 1.0
 */
@Configuration
public class CxfWebServiceConfig {

    /**
     * 这里需要注意  由于springmvc 的核心类 为DispatcherServlet
     * 此处若不重命名此bean的话 原本的mvc就被覆盖了。可查看配置类:DispatcherServletAutoConfiguration
     * 一种方法是修改方法名称 或者指定bean名称
     * 这里需要注意 若beanName命名不是 cxfServletRegistration 时,会创建两个CXFServlet的。
     * 具体可查看下自动配置类:Declaration org.apache.cxf.spring.boot.autoconfigure.CxfAutoConfiguration
     * 也可以不设置此bean 直接通过配置项 cxf.path 来修改访问路径的
     * @return
     */
    @Bean("cxfServletRegistration")
    public ServletRegistrationBean dispatcherServlet(){

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

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

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

 启动项目,访问URL  http://localhost:8019/api_server/api?wsdl

 Cxf客户端

通过cxf-codegen-plugin插件生成客户端文件

<dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-core</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>3.2.5</version>
        </dependency>


<!-- cxf-codegen-plugin -->
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>3.2.5</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>src/main/resources/wsdl/api.wsdl</wsdl>
                                    <wsdlLocation>classpath:wsdl/api.wsdl</wsdlLocation>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

客户端调用代码

package com.yl.springboottest.api.webservice.client.cxf;

import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

/**
 * 描述: CXF 方式Client调用WebService 直接调用
 *
 * @author: yanglin
 * @Date: 2020-11-19-13:11
 * @Version: 1.0
 */
@Slf4j
public class CXFWebServiceClientT1 {

    public static void main(String[] args) {
        // 动态调用
        JaxWsDynamicClientFactory dcflient = JaxWsDynamicClientFactory.newInstance();

        Client client=dcflient.createClient("http://localhost:8019/api_server/api?wsdl");
        try{
            Object[] objects = client.invoke("getCxfApi","ylDream");
            log.info("CXFWebServiceClientT1 getCxfApi 调用结果:{}", objects[0].toString());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

调用结果 

 

 


以上,如果有需要源码可以私信或评论,谢谢!

 

 

  • 14
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 60
    评论
评论 60
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值