jax ws ri 生成java类_基于SOAP的webservice(1)、JAX-WS实现

jax ws ri 生成java类_基于SOAP的webservice(1)、JAX-WS实现因为工作中使用了SOAP进行两个系统的接口调用,所以私下学习一下两种实现,粗略记录于此。本文侧重于实际实现操作,而不是理论原理。个人简单理解:SOAP(SimpleObjectAccessProtocol简单对象访问协议)是基于XML和HTTP的用于实现网络连通的程序之间远程调用的协议(但是SOAP1.2中也可以使用非HTTP协议进行传输)。两个通过网络连接的程序体,通过一定规范的XML进…

大家好,又见面了,我是你们的朋友全栈君。

因为工作中使用了SOAP进行两个系统的接口调用,所以私下学习一下两种实现,粗略记录于此。本文侧重于实际实现操作,而不是理论原理。

个人简单理解:SOAP(Simple Object Access Protocol 简单对象访问协议)是基于XML和HTTP的用于实现网络连通的程序之间远程调用的协议(但是SOAP1.2中也可以使用非HTTP协议进行传输)。两个通过网络连接的程序体,通过一定规范的XML进行远程调用。更详细一点的可以参考浅谈 SOAP。

方式1、JAX-WS实现

JAX-WS是JDK自带的Web服务的API,它可以用于提供REST式或基于SOAP的服务。SOAP的JAX-WS实现有两种部署方式,一种是直接在应用程序中使用Endpoint发布;另一种是在web工程的web.xml中配置监听器,随着web工程的启动而启动。为了两种方式都使用,并且便于使用依赖,我这里创建的是一个maven web工程,工程名为SOAPServer,JDK版本是1.8。

1. 编写服务端。

用于提供服务的服务端类ServerDemo :

package demo;

import javax.jws.WebMethod;

import javax.jws.WebService;

@WebService

public class ServerDemo {

@WebMethod

public String sayHi(String name){

return “Hi: “+name+”,this is SOAPServer”;

}

@WebMethod

public String doSth(){

return “do some thing”;

}

}

这个类很简单,只有两个方法,一个有参数,一个无参数。类名前面加了@WebService注解,方法名前面加了@WebMethod注解(SOAP还有许多其他的注解)。

2. 发布服务。

前面提到发布服务有两种方式。

(1)、使用Endpoint发布,编写用于发布的类:

package demo;

import javax.xml.ws.Endpoint;

public class Publisher {

public static void main(String[] args) {

String url = “http://localhost:8080/fistSoap”;

Endpoint.publish(url, new ServerDemo());

}

}

运行main方法,使用浏览器访问http://localhost:8080/fistSoap, 如果有如下所示,即说明发布正常。

94addb458778

访问服务

(2)、使用web项目监听器发布。

首先需要添加依赖:

com.sun.xml.ws

jaxws-rt

2.2.10

然后在WEB-INFO目录下添加名为sun-jaxws.xml(默认名称)的文件:

然后在web.xml中添加监听器和servlet(此处url-pattern为/*,拦截所有请求):

com.sun.xml.ws.transport.http.servlet.WSServletContextListener

jaxws

com.sun.xml.ws.transport.http.servlet.WSServlet

1

jaxws

/*

然后在浏览器中访问http://localhost:8080/SOAPServer/firstSoap, 出现与Endpoint方式一样的web服务的概述页面,说明发布正常。如果有多个服务,那么只需要在sun-jaxws.xml中增加一条endpoint即可。例如我在sun-jaxws.xml增加了一个如下服务,那么我访问http://localhost:8080/SOAPServer/firstSoap或者 http://localhost:8080/SOAPServer/randService 会显示两个服务的信息。

94addb458778

多个服务信息

3. 生成客户端代码并调用。

服务发布后使用浏览器访问http://localhost:8080/SOAPServer/hello?wsdl 即可获得该服务的wsdl文档——描述服务调用信息(wsdl文档的详细结构在后续结合XML报文格式进行分析):

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://demo/”

xmlns:xsd=”http://www.w3.org/2001/XMLSchema”

xmlns=”http://schemas.xmlsoap.org/wsdl/” targetNamespace=”http://demo/” name=”ServerDemoService”>

获取到wsdl文档之后,我们使用JDK自带的wsimport实用程序来生成客户端代码。(与之相反的是,wsgen实用程序可以通过服务端代码来生成wsdl文件,wsgen和wsimport命令详解可参考wsgen和wsimport命令讲解)

在本例中使用的是windows系统,打开CMD,输入

wsimport -s D:\work_eclipse\SOAPClient\src\main\java -p my.client http://localhost:8080/SOAPServer/firstSoap?wsdl

即在D盘work_eclipse\SOAPClient\src\main\java目录下的my.client目录中生成了客户端代码(工程SOAPClient是新建的用来调用SOAPServer的工程),目录如图所示:

94addb458778

根据wsdl文件生成的客户端代码(client包下)

在服务端代码中,ServerDemo服务类,对应客户端中生成的ServerDemo接口和ServerDemoService类;服务类中的方法sayHi()对应客户端代码中的SayHi和SayHiResponse实体类;服务类中的方法doSth()对应客户端代码中的DoSth和DoSthResponse实体类。客户端中还生成了ObjectFactory类和package-info类。此处先不关心生成的类的结构,先尝试进行调用(当然,此时要保证SOAP服务处于已发布的状态)。

在SOAPclient的call目录下创建调用类:

package call;

import my.client.ServerDemo;

import my.client.ServerDemoService;

public class ClientDemo {

public static void main(String[] args) {

ServerDemoService server = new ServerDemoService();

ServerDemo serverDemo = server.getServerDemoPort();

System.out.println(serverDemo.sayHi(“erver body”));

System.out.println(serverDemo.doSth());

}

}

执行main方法之后,会输出“Hi: erver body,this is SOAPServer”与“do some thing”两句话,即说明调用成功,实现了远程调用。

4. SOAP报文和WSDL文档简要解析。

为了直观,我们先只分析调用sayHello.sayHi()时候的报文,在HelloClient 中注释掉sayHello.doSth(),然后发起请求,调用sayHi()方法。通过tcpTrace截获的SOAP请求报文如下:

GET /SOAPServer/firstSoap?wsdl HTTP/1.1

User-Agent: Java/1.8.0_60

Host: localhost:8080

Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2

Connection: keep-alive

POST /SOAPServer/firstSoap HTTP/1.1

Accept: text/xml, multipart/related

Content-Type: text/xml; charset=utf-8

SOAPAction: “http://demo/ServerDemo/sayHiRequest”

User-Agent: JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e

Host: localhost:8080

Connection: keep-alive

Content-Length: 187

erver body

通过tcpTrace截获的SOAP返回报文如下:

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Content-Type: text/xml;charset=utf-8

Transfer-Encoding: chunked

Date: Sat, 29 Jul 2017 17:07:52 GMT

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://demo/”

xmlns:xsd=”http://www.w3.org/2001/XMLSchema”

xmlns=”http://schemas.xmlsoap.org/wsdl/” targetNamespace=”http://demo/” name=”ServerDemoService”>

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Content-Type: text/xml;charset=utf-8

Transfer-Encoding: chunked

Date: Sat, 29 Jul 2017 17:07:52 GMT

Hi: erver body,this is SOAPServer

从报文格式可以看出,明显的HTTP+XML格式,对于SOAP1.1和SOAP1.2相比,在HTTP格式的请求头里面会有些区别,主要是命名空间的区别。可以粗略参考SOAP1.1和SOAP1.2报文差异。从报文里面可以看出,虽然ClientDemo只调用sayHi()方法,但是请求有两段,第一个get请求,是请求返回的wsdl文档;第二个请求是post请求,才是真正调用sayHi()方法,并返回了结果。实际上,发起get请求去获得对应的wsdl文档这个动作,是在客户端创建ServerDemoService这个对象的时候发起的,也就是下面这行代码:

ServerDemoService server = new ServerDemoService();

显然,在soap中,wsdl文档至关重要,包含了服务端的所有调用信息。从结构上看,最顶层是definitions根节点,根节点下面分为以下几部分:

types部分

从wsdl文档中可以看出,types节点指向了一个地址:“http://localhost:8080/SOAPServer/firstSoap?xsd=1”,而这个地址是一个schema文件(即一个描述XML格式的文件),该文件内容如下:

文件里规定了元素名称、元素类型。以sayHi为例,

说明了有一个元素名为sayHi,这个元素的类型是“tns:sayHi”,而“tns:sayHi”指向下面这段:

说明sayHi是一个复杂类型,而这个复杂类型再包含了一个元素,元素名为arg0,arg0的类型是String类型(minOccurs表示这个元素“最小出现次数”)。

结合请求报文中的Body节点:

erver body

可以看出,上面的type就是描述了请求报文和返回报文的节点名称、节点内容的类型。

portType和message

portType节点中主要包含若干个operation节点(每一个operation节点与服务方的方法对应)。operation节点中包括input和output,input在output之前,即是请求/响应模式。input和output都有一个message属性,这个message属性指向了相应的message节点。而这个message节点中又包含一个part,part的element属性指定了这个operation节点的输入值的参数名以及类型。简而言之,portType和message分别指定了这个服务拥有的方法,以及每个方法需要的参数和返回值的类型以及名称。

binding

transport的值“http://schemas.xmlsoap.org/soap/http”可以概括为基于HTTP的SOAP,这个值还可以是其他的值,如SMTP、TCP。style为document,指定这个服务的style为document(意味着消息格式是XML格式或者等价的文档格式)。style还有一个选项是“rpc”,这个名称容易引起误解,这个值意味着消息本身不是类型化的(没有type部分),而use=”literal”是WSDL中定义的服务的类型遵循WSDL的模式,决定了数据类型被如何编码和解码。

service

以上的部分更多的是在指定服务的名称、类型等等规范。而service提供了服务的相关实现细节。service中包含port子元素(数量由binding部分的数量,因为明显看出port是指向相应的binding元素的),最重要的还是address子元素,指定了一个location,即发布服务的地址,通过解析这个地址进行调用。

通过这个WSDL文档,描述了完整的服务信息。这些信息是可以在服务类里面通过注解进行配置的。例如@ SOAPBinding可以将binding部分的style属性由“document”更改为“rpc”。详细的配置本文就不深入了,因为现实中已经很少会使用这种JAX-WS实现,JAX-WS实现已经被其他的框架所扩展。下一篇文章将简单介绍基于SOAP的webservice的Axis2框架实现。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159678.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • poe交换机可以当网络交换机吗_家用需要网管交换机吗

    poe交换机可以当网络交换机吗_家用需要网管交换机吗PoE交换机是一种新型的多功能交换机,随着PoE交换机的广泛应用,人们对PoE交换机有了一定的了解。然而,很多人认为PoE交换机可以自行发电,这种说法并不正确,通常所讲的PoE交换机供电指的是PoE交换机通过网线来给其他设备供电,与此同时也不丢失传输数据的功能。那么,PoE交换机可以当普通交换机用吗?下面就由飞畅科技的小编为大家来详细介绍下这个问题,一起来看看吧!PoE交换机是具有PoE功能的交换机,与普通的交换机之间可以进行连接。它可以在供电的同时传输数据,而普通交换机的主要作用是交换数据,并不具备供

  • 产品经理面试内容_产品专员简历

    产品经理面试内容_产品专员简历前言经过深思熟路后,本渣决定参加放弃研发转投产品了。本科,硕士所学的东西也不能说可惜,这些都会帮助我在产品岗位更进一步。那么在研究与学习之下,我来研究一下产品经理的简历如何投能不当炮灰。(现在写好加深一下印象,也方便一下一年后写简历参加秋招的小周。)思路:PM的面试简历,就是一份产品产品用户:HR,业务主管简历被HR的阅读时间很短,15S左右,且较为粗略。所以就需要满足d…

    2022年10月28日
  • 其实就是为了能有字幕特效,用MeGUI + AVS压制PSP MP4AVC视频01 – 基础知识篇

    其实就是为了能有字幕特效,用MeGUI + AVS压制PSP MP4AVC视频01 – 基础知识篇A、需要准备的软件: .netframework2.0运行库(下面两个软件都是.net写的)MeGUI(AVS等软件的集合GUI)LiteMP4Tool(批处理AVS转换的GUI)通用解码器包,能够播放各类视频文件即可,包括K-LiteCodec、完美解码甚至暴风影音(这个不推荐)之类。avisynth2.58,这个我自己用的完美解码附…

    2022年10月16日
  • 微信小程序 springwebsocket 报错: Error during WebSocket handshak 403

    微信小程序 springwebsocket 报错: Error during WebSocket handshak 403

  • 微信公众平台卡券功能_微信账号上的领劵是真是假

    微信公众平台卡券功能_微信账号上的领劵是真是假文章目录1.微信卡券功能介绍2.申请方式2.1公众平台申请2.2开放平台申请3.申请条件3.1公众平台条件3.2开放平台条件4.申请种类、类目、商户类型4.1开放种类4.2开放类目4.3开放商户类型5.申请流程及步骤5.1申请流程5.2申请步骤5.2.1公众平台申请步骤5.2.2开放平台申请步骤6.开发流程6.1制作普通卡券通过微信公众平台制作(免开发)6.2卡券投放6.3卡券核销扩展微信《卡券功能申请类目与资质审核要求》微信《卡券违规处罚及清退规则》1.微信卡券

  • sql数据库查询语句大全_sql基本语句大全

    sql数据库查询语句大全_sql基本语句大全1、今天select*from表名whereto_days(时间字段名)=to_days(now());2、昨天SELECT*FROM表名WHERETO_DAYS(NOW())-TO_DAYS(时间字段名)<=13、近7天SELECT*FROM表名whereDATE_SUB(CURDATE(),INTERVAL7DAY)<=date(时间字段名)4、近30天SELECT*FROM表名where

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号