JWS(Java Web Service) 第一个案例入门

目录

JWS 简介

第一个案例

ws 服务端

浏览器访问

客户端

调用测试


JWS 简介

Java Web Service 是 Java 语言对 WebService 服务的一种实现,用来开发和发布服务,为 Java 开发者提供便捷发布和调用WebService服务的功能。无需借助任何第三方库。

Java 1.6 开始推出 JWS,在 javax.jws 包下,在线 JDK 文档:https://docs.oracle.com/javase/6/docs/api/

开发过程十分简单:

1、服务端创建接口

2、服务端创建接口具体实现

3、服务端开启服务

4、客户端调用

编码也十分简单,因为整个 javax.jws 包一共也没多少 API。

因为 webservice 以 xml 格式进行传输数据,同时也会涉及一些 javax.xml 包下的 API。

第一个案例

创建一个服务器项目(Java SE)、同时创建一个客户端项目(Java SE),服务端创建一个接口和其实现类,其中提供数据相加与数据相乘的两个方法,然后对外提供这个数据计算的服务,客户端通过 webService 技术可以直接调用服务端系统中的计算方法。

无论是 Java SE 应用还是 Java Web 应用,对于使用 jws 的 API 都是一样的,这里为了简单以创建 Java SE 项目进行演示。

ws 服务端

新建一个 Java SE 项目如下,名称 web_server,其中的代码结构如下。

1、第一步创建 CalculatorService 接口,这是需要对外提供服务的接口,客户端需要知道其中的内容。

2、第二步创建实现类 CalculatorServiceImpl,这是接口的具体实现,客户端是无法知道其中的内容的。

3、第三步创建 Web_Service 类,用于启动 webService 服务。

具体的 API 已经在注释解释的很详细了。

1、CalculatorService 接口内容如下:

import javax.jws.*;

/**
 * Created by Administrator on 2019/1/25 0025.
 * 计算器接口
 * SEI(Service Endpoint Interface):服务终端接口,即webService提供的服务接口
 * SIB(Service Implemention Bean):服务实现类,即webService提供的服务接口的实现类
 *
 * @javax.jws.WebService : 将 Java 类标记为实现 Web Service,或者将 Java 接口标记为定义 Web Service 接口
 * 不过是服务端还是客户端,接口上都必须写上此注解
 */
@WebService
public interface CalculatorService {

    //加法
    //@WebService 中的方法上可以加上 @WebMethod 注解,也可以不加
    //@WebMethod 注解写或不写,服务端都会将 @WebSerivce 中的所有方法提供给客户端掉
    //写上的好处就是看起来更加直观而已,如同 @Override 重写注解意义,删除也无影响
    public float addition(float a, float b);

    //乘法
    public float multiplication(float a, float b);
}

2、CalculatorServiceImpl 实现类内容如下:

import javax.jws.WebService;
import java.util.logging.Logger;

/**
 * Created by Administrator on 2019/1/25 0025.
 * SEI(Service Endpoint Interface):服务终端接口,即webService提供的服务接口
 * SIB(Service Implemention Bean):服务实现类,即webService提供的服务接口的实现类
 *
 * @javax.jws.WebService : 将 Java 类标记为实现 Web Service,或者将 Java 接口标记为定义 Web Service 接口
 * endpointInterface:终端接口,定义服务抽象 Web Service 协定的服务端点接口的完整名称,通常设置为服务实现类的全路径
 * 接口要写,实现类也必须写 @WebService
 * @WebService 接口一共提供了以下属性,而且都有默认值,它们将来都会出现在 wsdl 的 xml 文件中
 * String name() default "";
 * String targetNamespace() default "";
 * String serviceName() default "";
 * String portName() default "";
 * String wsdlLocation() default "";
 * String endpointInterface() default "";
 */
@WebService(endpointInterface = "com.lct.web_service.CalculatorService")
public class CalculatorServiceImpl implements CalculatorService {
    //日志记录器
    public static final Logger logger = Logger.getGlobal();

    @Override
    public float addition(float a, float b) {
        logger.info("加法计算:" + a + " + " + b + " = " + (a + b));
        return a + b;
    }

    @Override
    public float multiplication(float a, float b) {
        logger.info("乘法计算:" + a + " x " + b + " = " + (a * b));
        return a * b;
    }
}

3、Web_Service 启动 webService 服务类内容如下:

import javax.xml.ws.Endpoint;

/**
 * Created by Administrator on 2019/1/25 0025.
 * webServer 启动类
 */
public class Web_Service {
    public static void main(String[] args) {
        /**webService服务器提供给客户端访问的地址
         * 192.168.1.20 为服务器 ip、3333为指定的端口号、web_server 为应用名称、calculator为标识
         * 这个地址符合 http 地址即可,为了看起来更像是 web访问,所以才写了应用名,其实 http://192.168.1.20:3333/xxx 都是可以的
         */
        String wsUrl = "http://192.168.1.20:3333/web_server/calculator";

        /**
         * javax.xml.ws.Endpoint 表示一个 web service 终端,这是一个抽象类,其中提供了静态方法可以直接调用
         * Endpoint publish(String address, Object implementor)
         * address:传输协议的 url 地址;
         * implementor(实现者):web service 终端的实现类,因为一个 ws 接口可能会有多个实现类
         */
        Endpoint.publish(wsUrl, new CalculatorServiceImpl());
    }
}

浏览器访问

webService 服务启动成功之后,根据提供 wsdl 地址,直接通过浏览器即可访问,看到服务端提供的接口(服务),客户端只需要解析这个 xml 文件即可进行服务调用。

注意地址最后的 wsdl 参数必须加上。

此 xml 文件全部内容如下:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<!--
 Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. 
-->
<!--
 Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. 
-->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://web_service.lct.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://web_service.lct.com/" name="CalculatorServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://web_service.lct.com/" schemaLocation="http://192.168.1.20:3333/web_server/calculator?xsd=1"/>
</xsd:schema>
</types>
<message name="multiplication">
<part name="parameters" element="tns:multiplication"/>
</message>
<message name="multiplicationResponse">
<part name="parameters" element="tns:multiplicationResponse"/>
</message>
<message name="addition">
<part name="parameters" element="tns:addition"/>
</message>
<message name="additionResponse">
<part name="parameters" element="tns:additionResponse"/>
</message>
<portType name="CalculatorService">
<operation name="multiplication">
<input wsam:Action="http://web_service.lct.com/CalculatorService/multiplicationRequest" message="tns:multiplication"/>
<output wsam:Action="http://web_service.lct.com/CalculatorService/multiplicationResponse" message="tns:multiplicationResponse"/>
</operation>
<operation name="addition">
<input wsam:Action="http://web_service.lct.com/CalculatorService/additionRequest" message="tns:addition"/>
<output wsam:Action="http://web_service.lct.com/CalculatorService/additionResponse" message="tns:additionResponse"/>
</operation>
</portType>
<binding name="CalculatorServiceImplPortBinding" type="tns:CalculatorService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="multiplication">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="addition">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="CalculatorServiceImplService">
<port name="CalculatorServiceImplPort" binding="tns:CalculatorServiceImplPortBinding">
<soap:address location="http://192.168.1.20:3333/web_server/calculator"/>
</port>
</service>
</definitions>

客户端

调用别人发布的 WebService 服务,例如调用天气预报 WebService 服务、调用门票服务、地图服务等。因为是远程调用服务端的对象方法,所以需要在客户端也生成与服务器一致的服务接口,这通常有如下几种方式:

1、使用第三方如 Apache 的 CXF wsdl2java 工具既能生成服务端代码,也能生成客户端代码;

2、Java JDK 在 bin 目录下提供了一个 wsimport.exe 程序,用于根据 wsdl 文件生成 WebService 客户端代码,然后调用 WebService;

3、直接使用服务提供商的提供的客户端编程 API 接口;

简单的说就是客户端调用 webService 服务器的接口,客户端自己也要有与服务器一致的接口,但是客户端不需要服务端接口的实现类,显然人家服务提供商自然也不会连实现类都提供出来,再者说,如果连接口和实现都提供了,则远程调用就没有意义了,就是再调用自己了。

新建客户端项目(Java SE )如下,其中 CalculatorService 是与服务端一样的接口,Web_service 类用于调用服务器上的方法。

1、CalculatorService 接口内容如下,如果服务端、客户端都是 Java 开发,则完全可以联系服务器开发人员直接把这个接口的代码发过来即可。所以下面的代码与服务端完全是一样的。

import javax.jws.WebService;

/**
 * Created by Administrator on 2019/1/25 0025.
 * 计算器接口
 * SEI(Service Endpoint Interface):服务终端接口,即webService提供的服务接口
 * SIB(Service Implemention Bean):服务实现类,即webService提供的服务接口的实现类
 *
 * @javax.jws.WebService : 将 Java 类标记为实现 Web Service,或者将 Java 接口标记为定义 Web Service 接口
 * 无论作为服务端还是客户端都必须写 @WebService 注解
 */
@WebService
public interface CalculatorService {

    //加法
    public float addition(float a, float b);

    //乘法
    public float multiplication(float a, float b);
}

2、Web_service 类用于调用 webService 服务,内容如下:

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Logger;

/**
 * Created by Administrator on 2019/1/25 0025.
 */
public class Web_service {
    //日志记录器
    public static final Logger logger = Logger.getGlobal();

    public static void main(String[] args) {
        try {
            /** url:webservice 服务端提供的服务地址,结尾必须加 "?wsdl"*/
            URL url = new URL("http://192.168.1.20:3333/web_server/calculator?wsdl");

            /** QName 表示 XML 规范中定义的限定名称,QName 的值包含名称空间 URI、本地部分和前缀。
             * QName(final String namespaceURI, final String localPart):指定名称空间 URI 和本地部分的 QName 构造方法。
             * 如下所示的两个数据都可以浏览器访问服务端时返回 xml 中第一行找到,如:
             * <definitions xmlns:wsu=xxxxxxx targetNamespace="http://web_service.lct.com/" name="CalculatorServiceImplService">
             */
            QName qName = new QName("http://web_service.lct.com/", "CalculatorServiceImplService");

            /**
             * Service 对象提供 Web 服务的客户端视图
             * Service 作为以下内容的工厂:1、目标服务端点的代理,2、用于远程操作的动态面向消息调用的 javax.xml.ws.Dispatch 实例。
             * create(java.net.URL wsdlDocumentLocation,QName serviceName):创建 Service 实例。
             * wsdlDocumentLocation : 服务 WSDL 文档位置的 URL
             * serviceName : 服务的 QName
             */
            Service service = Service.create(url, qName);

            /**
             * 使用 getPorts 方法可以对服务上可用的端口/接口进行枚举
             * getPort(Class<T> serviceEndpointInterface):获取支持指定服务端点接口的对象实例
             * serviceEndpointInterface:指定返回的代理所支持的服务端点接口
             */
            CalculatorService calculatorService = service.getPort(CalculatorService.class);
            float added = calculatorService.addition(100, 80);
            float multied = calculatorService.multiplication(2.5F, 100);

            logger.info("added:" + added);
            logger.info("multied:" + multied);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

    }
}

调用测试

先运行服务器开启 webService 服务,然后运行客户端看是否能调用服务端上的实现类进行计算,如果可以则说明 webService 服务提供成功。

由上可见完全成功。

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/86646656