Java远程调用WebService接口

时间: 2023-08-15 admin 互联网

Java远程调用WebService接口

Java远程调用WebService接口

WebService简介

Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。

简单的说,WebService就是一种跨编程语言和跨操作系统平台的远程调用技术。所谓跨编程语言和跨操作平台,就是说服务端程序采用java编写,客户端程序则可以采用其他编程语言编写,反之亦然。跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上运行。 远程调用,就是一台计算机的应用可以调用其他计算机上的应用。例如:支付宝,支付宝并没有银行卡等数据,它只是去调用银行提供的接口来获得数据。还有天气预报等,也是气象局把自己的系统服务以webservice服务的形式暴露出来,让第三方网站和程序可以调用这些服务功能。

WebService原理

XML,SOAP和WSDL就是构成WebService平台的三大技术 。

  • WebService采用Http协议来在客户端和服务端之间传输数据。WebService使用XML来封装数据,XML主要的优点在于它是跨平台的。

  • WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议规定的。

  • WebService服务器端首先要通过一个WSDL文件来说明自己有什么服务可以对外调用。简单的说,WSDL就像是一个说明书,用于描述WebService及其方法、参数和返回值。 WSDL文件保存在Web服务器上,通过一个url地址就可以访问到它。客户端要调用一个WebService服务之前,要知道该服务的WSDL文件的地址。WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址:1.注册到UDDI服务器,以便被人查找;2.直接告诉给客户端调用者。

WebService实例

本实例演示在服务端创建接口并在客户端调用的过程,创建两个不同项目用来模拟两台机器,一个项目代表服务端,另一个代表客户端

本实例模拟调用端口来获得一些学生的信息

服务端

1.先编写一个接口

import java.util.List;

public interface Test {
    //查询学生成绩
    List scores(String stuName);
    //查询学生年龄
    int age(String stuName);
    //查询学生老师
    String teacher(String stuName);

}

2.编写接口的实现类

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import java.util.ArrayList;
import java.util.List;

@WebService(
        targetNamespace = "http://test",
        name = "TestSOAP",
        portName = "ComputerSOAPPort",
        serviceName = "TestWSS"
)
public class TestImpl implements Test{
    @WebMethod(
            operationName = "queryScores",
            exclude = false
    )
    @Override
    public @WebResult(name = "scoresResult") List scores(@WebParam(name = "stuName") String stuName) {
        List list = new ArrayList();
        list.add("语文:99");
        list.add("数学:95");
        list.add("英语:100");
        return list;
    }
    @WebMethod(
            operationName = "queryAge",
            exclude = false
    )
    @Override
    public @WebResult(name = "ageResult") int age(@WebParam(name = "stuName") String stuName) {
        return 8;
    }
    @WebMethod(
            operationName = "queryTeacher",
            exclude = false
    )
    @Override
    public @WebResult(name = "teacherResult") String teacher(@WebParam(name = "stuName") String stuName) {
        return "嘵奇老师";
    }
}

3.发布服务

import javax.xml.ws.Endpoint;

public class TestServer {
    public static void main(String[] args) {
        Endpoint.publish("http://127.0.0.1:2222/test",new TestImpl());
        System.out.println("服务端启动成功");
    }
}

4.测试服务是否发送成功

通过阅读wsdl,确定客户端调用的接口、方法、参数和返回值存在,证明服务发布成功

我们在浏览器输入 http://127.0.0.1:2222/test?wsdl 来获取wsdl文件进行阅读

wsdl,是以XML文件形式来描述WebService的”说明书”,有了说明书,我们才可以知道如何使用或是调用这个服务.

现在我们还不知道怎么去阅读,后面我们会详解,只要能获取到,就能确定WebService服务发布成功

服务端完成,接下来就是客户端

客户端

客户端调用服务有很多种方法,我们先用工具生成客户端代码,后面会详解
wsimport是jdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码).当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码。

1.创建一个客户端空项目,cmd命令行进入此项目的src目录
使用以下命令生成客户端代码

wsimport -p com.cad.demo -s . http://127.0.0.1:2222/test?wsdl

 com.cad.demo是路径-s是指编译出源代码文件,后面的.(点)指將代码放到当前目录下.
 最后面的http….是指获取wsdl说明书的地址


可以看到已经下载进来了

2.编写客户端

package com.cad.test;

import com.cad.demo.TestSOAP;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.io.IOException;
import java.net.URL;
import java.util.List;

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //创建WSDL文件的URL
        URL url = new URL("http://127.0.0.1:2222/test");
        //创建服务名称  namespaceURL 命名空间 localPart服务视图名
        QName name = new QName("http://test","TestWSS");
        Service service = Service.create(url,name);
        //获取服务实现类
        TestSOAP testSOAP = service.getPort(TestSOAP.class);
        //调用方法
        List list = testSOAP.queryScores("小明");
        int age = testSOAP.queryAge("小红");
        String teacher = testSOAP.queryTeacher("小张");
        System.out.println(list);
        System.out.println(age);
        System.out.println(teacher);
    }
}

结果:

分析

以上这种方式需要我们下载到本地类,这样的话如果服务端修改了接口我们还需要重新下载,这样就不太方便,于是我们可以利用下面这种方法,不需要下载到本地就能实现远程接口的调用

1.创建一个Maven项目导入如下依赖

<dependencies>
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-discovery</groupId>
            <artifactId>commons-discovery</artifactId>
            <version>0.2</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis-jaxrpc</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis-saaj</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>

2.编写客户端
这里要说明的是没写服务端的原因是服务端的代码正常写就可以。不需要改动,我这里写的是模拟获取城市天气的功能

package com.www;


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 javax.xml.rpc.ServiceException;
import java.rmi.RemoteException;

public class Demo01Client {

    public static void main(String[] args) throws ServiceException, RemoteException {
        //远程调用路径
        String url = "http://127.0.0.1:12345/weather?wsdl";
        Service service = new Service();
        try {
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(url);
            //nameSpaceURL是要指向的命名空间的名称 localPart是要调用的方法名
            call.setOperationName(new QName("", "getWeather"));
            //paramName是参数名 参数类型:spring  参数模式:IN或者OUT
            call.addParameter("cityName", XMLType.XSD_STRING, ParameterMode.IN);
            //返回值类型:Spring
            call.setReturnType(XMLType.XSD_STRING);
            //传入参数
            String temp = "长春";
            Object[] objects = new Object[]{temp};
            //远程调用
            String result = (String) call.invoke(objects);
            System.out.println(result);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

结果:

WSDL文档

可以看到我们没有下载到本地类就实现了远程接口的调用,大家可以自行测试一下