开发者学堂课程【高校精品课-上海交通大学-企业级应用体系架构:Web Service2】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/75/detail/15840
Web Service2
内容介绍
一.WebService 的编译及访问
二.如何编写客户端
三.如何写 Web Service
四.Restful Web Service
五.Web Service 的使用场景
一.WebService 的编译及访问
Web service 开发好之后,要在配置文件里面配置一下,最重要的是它的位置,即在这个位置上能访问到这个 web 服务。
编译完之后一定要对着这个包再去执行一次编译才能产生 WSCL 文件。一定要打开这个 pom 文件,在右边一定要去编译这一个任务,编译它之后才能生成 WSCL 文件。其实只有接口是没有用的,还要有接口生成、 soap 消息这个辅助类,所以要通过这个编译才能生成相应的东西。
编译完之后你就可以去访问它,访问它有两种方式,一种是自己组一个信封,我们是要发一个叫 get country request 的东西,因为在这个类里面,我们看到的它叫 get country request 是从 soap 里面解析内容过来的。这个里面有一个叫做 name 的东西,所以我们可以直接在这个 request 上面 get name ,把它的 name 取出来,根据这样的一个映射关系,我们可以组一个这样的soap 消息。
用 postman 这样的方法去 post 一下,如图, url 是我们在这里配的,它在8080端口的这个位置上等着。
这个 HP request 体里面放的是个信封,这个信封就是图中所示的,然后你会得到一个返回的值,这个返回的值也是一个信封,这个信封也有信封体和信封头。信封体,就是我们返回 get country request 里面放进去了一个我找到的这个 country ,所以返回的信封里面有一个 get country request ,这里面放了一个 country ,这个 country 有 name 也有 population capital 和 currency ,这样,双方就实现了一次交互。用 postman 来执行的含义是说我没有写一个 Java 的代码,只要是能够发出这样请求的客户端,都可以得到这样的一个结果。如果要写Java的代码,在客户端这边,比如我也去写spring boot 的一个工程,它要使用 web service 来引用这些东西(如下图),
它这边同样需要去产生这些辅助类,所以也要用到这个运行式的东西。
这边仍然是用一个插件,这个插件的名字跟上面不太一样,它的作用就是生成,从( http://localhost:8080/ws/countries.wsdl )生成,前一段的 service再加上“ /countries. ” 就能拿到这个 wsdl 。拿到它之后,这是一个 wsdl 的文件,它是由这种语言(schemaLanguage )编写的,我们说到这个位置( http://localhost:8080/ws/countries.wsdl )去拿一个 wsdl 的文件,然后去编译、生成这个动作,就会产生 java 这一端的端口和 provce 。
二.如何编写客户端
我们真正的客户端是如何编写的呢?
它说,我要继承( WebServiceGatewaySupport),这是 spring 里面写好的,一旦拿到它,我们就可以去在上面进行相应的调用,比如我们定义一个叫做 getCountry 的方法, WSDL 生成之后就会有两种消息,一种是 get country request ,另一种是 get country response ,我们创建一个 get country request 对象,然后设置一下,它的名字是某一个 country 。然后就直接说我要得到一个country,即( get country response )。
它是如何得到的呢?就是去执行 getWebServiceTemplate , 这个里面是 spring包装好的、给我们定义的一个方法。它说我要去对着这个 web 服务( http://localhost:8080/ws/countries )去生成。我们去发出请求,然后在返回了结果之后,就得到了这个 response 。
这个位置是如何生成的?如图,在这个位置( “/ws”)上,它对应的是这个 countries ,这样的话就连起来了。在客户端这一端,你要想做这一次调用,如果同样要有一个配置,就要配( “http://localhost:8080/ws” ),它默认为在哪里要创建 country ,它的 client 就从这里来创建。在运行中也是同样的道理,你要在客户端这端先去执行 generate goal ,它才能生成客户端这端需要的接口和代理,然后去执行。我们是想获取西班牙的位置,它会返回“它在欧洲”。
如图为它的代码(上面)。
web service 跑起来之后,可以看到 WSDL 文件的样子(如图所示),这是另外一个 web service 。
这一边是服务器端的,先定义 Endpoint,然后再指定它,要去通过 countryRepository 得到它想要的东西,然后它要从客户端的 Getcountryrequest 消息里面,去通过 get name 得到客户端想获取什么。如图为服务器端跑起来的样子。
然后看 web 服务器的客户端,我们希望得到一个 client 。我们先发送一个 get country 请求,然后对着这个位置( http://localhost:8080/ws/countries )去发,就能得到一个 response 。我们其实只写这几个类(代码结构),但是在这个 target 生成的里面,它运行完 generate 之后会帮我们生成一系列的东西。
如图,这是生成的一系列的类,是从 WSDL 文件里面去生成的。这个类是如何生成的,我们在配置文件里面去获取客户端,然后在这个客户端里面,根据这个 WSDL 文件去生成相应的底下的这些段。然后我们就跑一下整个的这个应用,跑了之后,这边的服务器也有输出。我们发了一个 SOAP 的消息过去,然后服务器在解析它,产生了一个结果。
然后这一边,我们想知道西班牙的位置,它返回了一个欧洲,这就是soft 服务的执行的一个过程。
如图为具体的代码,这是基于 spring 来写的,它封装了很多的类,我们写起来就要用这些类,有很多事情可能就会少。但是也可以什么都不用,自己写一个原生的 WebService 。
三.如何写 WebService
如何写 WebService 呢?我这里写了一个例子(如图),这是 Java 企业版定义的 inoation ,那用只要支持 webservice ,只要支持Java 企业版 webservice 的这种工具,它就能够去生成相应的 point ,这样的一些辅助类。
这个 warehouse 里面,它初始化时会有一个 prices ,类似于我们在讲 RMI 的例子里面,出现过的这个类。现在我们把它定义成一个 webservice ,那它会有一个 getprice 方法,会暴露出去给别人用,就是在 webservice 里面的 operation ,它有一个是来自于用户的参数,用叫做 description ,就是通过网络传递。那我们用 description 再到 price 这个集合类里面去找,看它应该是返回,如果有就返回它的 price 对应的 price ,如果没有就返回零,底下的 main 函数是说创建一个东西,把它放到这个位置上( http://localhost:9000/Warehouse ),那用 underpoint 就是 Java 企业版自己带的接口,这样一个类。它里面有个 publish 方法,就把我们定义的这一个实现类发布到这个接口上,这个位置上( address,implementor ),在这个位置( address,implementor )就可以访问到它,这就是什么工具都不用,自己写一个 webservice 的样子。那就是我们刚才看到的这个Webservice ,我什么都没用,就只有一个类,这是发布一个 service 最简单的方法。
那他就跑起来,这上面报错是因为我没有装 Log 工具,他报错了,
这就是我们让它跑在 LOCALHOT9000BYHO 这个地方,后面再加上 wspi 就是它生成的。加了之后,它自动帮我们生成 wspi 的文件,可以看到这和刚开始讲的是一样的,它会定义一个 message , 即 getprice 。
有一个叫做参数的东西,放到这个getprice 里面,然后它的参数是这个返回消息,是找 get price response,然后有一个put ,它是 firehouse have operation ,是 get price ,它的 include 就是我们刚才的这个消息,这是个get price消息,然后 output 就是 get price response ,funding 就是我们要把它绑到 SOAP 上面去,用的是 document ,具体的逻辑可以详细查询一下。
我们用成本的方式,然后这个 web service 在哪里,就在我们指定的这个位置上,这就是它帮我们生成的 WSDL 而不是我们编辑的,是我们是生成的。这样的话,就没有用到 spring 自身的任何东西,直接用 Java 的企业版就可以自动去生成这样的东西,这是我们实现webservice 一个更简单的方法。然后就可以去写一些前端的东西来实验,客户端的写法跟上面的写法是一样的,代码本身是这样写的。我们现在要讨论的是,用 SOAP 类型的 service 可以实现什么。我们实现了这个跨平台的这种通信,可以是一个 Java 和一个 C# 之间的通信。但是我们带来了一些什么问题,第一个就是我们和消息的格式是耦合起来,比如一开始讲的 make reservation ,它有四个参数,那就必须在 message 里面定义好这四个参数,如果四个参数发生了变化,那 webservice 即使用它的客户端就要跟着变。第二点,我们和编码机制绑定了,比如刚才我们说它是 rpc 的还是 document, 你是跟它绑定的。第三个就是我们要解析和组装 SOAP 消息,虽然这件事情不是自己做的,而是靠一个工具,比如 exit 这样的工具,刚才我们引入了 coldhouse 这样的工具来做的,但是不管怎么说,它产生了组装、解析和组装 SOAP 这样的工作,那即使是这个工具在做,我们在执行时它有一个性能上的开销。然后就是我们还需要一个 WSDL 文件来描述这个 web 的一些细节,从里面还得要去生成 proxy ,所以我们在编译的时候多了要用一个编译工具去编译生成 proxy 这样的东西。虽然它确实实现了异构语言跨网络的空间,但是它带来了许多问题。
总的来说,这种 webservice 是一种非常耗时的方式,上面的每一样要么是系统可维护性比较差,要么是比较耗时,那么如何解决这个问题呢?那就是用了 restful web service 。
四.Restful Web Service
1.Restful Web Service 的介绍
Restful Web Service 这个矢量是一个缩写,它表达的意思有几个,表示是说,在所有的数据里,它叫表述性状态转移。表示或者表述性是什么意思呢?就是,在这种服务里都是针对数据来进行驱动或者编程的,那么数据就是客户端和服务器端,也就是在 web 服务和这个客户端之间传递的内容。这个数据如何表示?在客户端中,比如web service 提供一个 data ,对 A 客户是把它展示成了表,对 B 用户是展示成了饼图,具体的做法会推到客户端来做,服务器端不会直接生成它的一种表示,这种表示需要客户端来做。然后服务端是数据驱动的,只传数据,那么所有的数据都是资源,那每一种资源,即每一项数据都可以有不同的表示,它可以是表示成表或者表示成饼图,这件事情要靠客户端来做。
那么,每一个数据要有一个唯一的标识,这个标识是指在网络上标识,所以我们有一个 URI 去描述它,体现在访问一个数据时出现在浏览器里面的那个地址里,后面要有一个唯一标识它的一个东西,比如它的ID,然后状态就指的是客户端的状态。也就是说,我服务器端是不需要知道你每一个客户端都是谁,你反正任何一个人针对的某一个资源,就是某一个 URI 进行编程,我返回的数据都相同,所以服务器端是状态。至于这个状态如何去展示出来,就是客户端自己的事情。整个程序,我们就可以理解为,就是整个客户端的状态,从一种迁移到另外一种,在整个操作程序就是这样。举个例子,你看到了所有的书,这是一种状态,当你要看一个细节的时候,这也是一种状态,当你把它放入购物车这又是一种状态,那无论哪一个,在 restful web service 眼里就是你要看到所有的书,或者某一本书,或者是某一个购物车,它就只把这个数据推给你,客户端如何去呈现是它自己的事情。所以 restful 实际上就是一种新的结构,它完全是靠数据驱动的。
2.数据驱动的好处
数据驱动有什么好处呢?首先我们传递的是纯数据,不是方法调用。所以我给你方法调用,也就是消息的格式去交,也就是说,今天你要给我传一个购物车信息,你用的是方法 A,明天改换成方法 B,这件事情对客户端不会产生任何影响,因为我本身就没有去调 A 或者 B ,我只是想知道这个购物车在哪里,比如我的 UIR 写成 local host8080,然后 cart ,我传进去125,这就是我的 ID (8080/cart/125),那你就应该把我的购物车返回给我,至于这个购物车是靠 A 方法得到的,还是 B 方法得到的,我不用去关心。第二,因为我们在传纯数据,这个数据通常来说是 Jason ,所以我不需要到 SOAP ,自然就没有解析和组装 SOAP 的开销,既然没有 SOAP 的开销,那也就没有 SOAP 的编码开销,直接对这个 Jason 对象传递就可以。
然后,因为都是 URL 来访问,所以我不需要一个WSDL 文件来告诉我这消息的格式是什么,我应该怎么传消息。然后,因为它就是 Jason 对象,所以它不需要有一个 proxy 把 SOAP 的消息转换成 Java 的调用,或者把 Java 返回的结果翻译成 SOAP 的消息,这些问题全部都可以解决。所以 restful 不存在这些缺陷,这个是它为什么现在使用更多的一个原因。在 restful 里面,我们看到每一种资源都会有一个唯一的标识,然后我们的处理过程就是在不断的转换客户端和服务器端之间的状态,那么,服务器端和客户端之间传递的消息, Jason 消息,它不需要一个 WSDL 文件再去描述它,所以它就自描述了。
那它就是非常适合,比如想要去抵消掉 SOAP Service 缺陷的这种场景。
3.设计原则
它设计的原则是什么呢?
首先要把所有的数据都抽象成资源,接着每个资源都要有唯一的标志符,然后就是要针对着 HTTP 的协议来处理。因为现在我们只有 URI 表示资源,而本质上来说,我们操作一个资源就是增删改查,即 CRUD 的四个动作。这四个动作因为我们没有在 SOAP 里面调用消息,所以你要依赖于 HTTP 协议本身来告诉它,我想对你的资源增删改查里面的某一种。如何做到呢?
那就是用 HTTP 中, GET 表示“读”, POST 表示 create ,PUT 表示update ,DELETE 表示删除。第一个和第四个比较容易记,中间两个就记住 POST 比较长,所以它工作比较多,就新增。其实 ACB 协议本身就是这样定义的,于是你就发现,你对着同样一个 URI ,用不同的方法去访问就表示,你想新增一个元素,还是更新一个元素等等。如果是购物车,我第一次应该是 GET, 得到它购物车的状态;在得不到的时候我就去 POST 一个购物车;以后每一次往购物车里面放东西,我就应该用 PUT 方法给他操作,往里面去加一个东西;如果购物车就是用户登出,那最后用 DELETE 把它删除掉。就是这样一个逻辑。
4.例子——在星巴克喝咖啡
举一个例子,就是在星巴克喝咖啡这个动作,你分一个前台和后台,前台说用户下订单,这个订单只要没有去付账之前,他都可以做修改,但是前提是后台还没有开始做,所以你可以去修改。那修改时有两种可能,一种是被拒绝,因为后台已经开始做了,比如你已经定了一杯卡布奇诺,你想要在里面加一个 shop ,但是后台已经开始做了,就不能更改,如果还没开始做就可以更改。后台做完之后,你想要拿到咖啡就要去付账,付账之后就可以把它拿走,这杯咖啡被拿走后结束。
后台是怎么做的呢?后台就在一堆咖啡里面排队去找,那就找这上面的单子去做,做完之后把咖啡给前台,然后再找下一个,不断的这样做。
在这个世界里面,我们重点要看 restful webservice 是怎么实现的。首先下订单,我们知道 create 是 POST 所以下订单的动作是对着 starbucks.example.org/order 这个位置上去发一个 POST 方法,那它就会知道,你要去下一个订单,然后订单里面的内容是什么呢?内容可以自己去写,因为到了服务器那边,它要去解析,你可以写成 Jason 的,也可以像这边的 XMU ,它里面包含一个具体的订单数据,这个数据将来会在后台去解析处理,无论是哪一次都要处理这个。首先它就没有信封的存在,必须要放到一个 soft 的消息里,它说这是个 order ,顾客要一杯拿铁,然后客户端这个请求 POST 过来之后,星巴克这个 web 服务它就去做处理,比如它产生了一个订单消息,如果产生成功,它就返回一个消息回来,返回的是 HTTP 协议里面的消息,也就是200是 OK ,201就是 create 大家比较熟悉的,比如404、500,把这些返回201 creative 成功之后会告诉它那个订单的位置在这
( http://starbucks.example.orq/order/1234 ),即1234是这个订单的 ID ,把它拼起来,如果你要想访问这个订单,就应该用这样的一个 URI 。这是订单里面返的内容,这内容由前端去处理,比如下面还有一个除了拿铁,它就增加了一个 cost ,表示它的价格是多少,三块钱。如果想付账怎么办呢?
它告诉 next ,next 说如果你想付账,应该对着这样一个 URI 操作( uri=”http://starbucks.example.com.payment/order/1234” ),它就表示1234这个订单的付账信息应该在这儿,你对着这个地方进行操作,这就完成了一次交互。
5.交互说明的问题
这个交互虽然非常简单,但是它说明了几个问题。第一,它不存在 XSOAP 。第二,在传递的过程当中,只是纯数据,没有像 message这样的东西,也就是说,没有看见像 operation 这样的方法以及它里面的那些参数比如 parts, 没有这些东西。第三,我们是纯粹靠 HTTP 协议来传递的,没有在cost SOAP ,也就不存在 SOAP 的编码,比如 rpc,document 。我们对着 order 这个位置发了一个请头过去,这个请求实际上是纯粹的数据,至于这个 order 是怎么产生,写入到数据库,或者是放到内存里,这些事情客户端不用关心,无论是发出的数据还是返回的结果都不包含这个信息。所以服务器端是用哪一个 operation 在处理这件事情,对用户来说并不需要知道。
这是下好了一个订单,用返回码来判断操作是否成功。我们经常看到500,404,如果看到的是201,说明操作成功了。
6.如何更新订单
如何更新订单呢?我们写的简单一点,发出请求,先看一下我当前能否更新,因为这个逻辑是说有可能不能更进,有可能能更进,这取决于这个订单是否被操作。所以我们发一个 options 请求出去,Options 就在说,它会返回,你对的这个主机加 URL 能进行什么操作,它的返回值就会包括有get和put ,put 对应的就是 update ,说明现在我们可以更新。所以我们去 put 一下,对着这个地方( starbucks.example.com )去put 。我要put一下,100-Continue ,即可以继续给我发消息,告诉我如何去 put 。当它确实返回这个消息时,我们就可以去做 PUT ,那么如何做呢?
你要带这样的信息,在 order 上加一点 shot 使它变浓一些。然后这边它处理好了,现在这个 order 除了拿铁,还多加了一个 shot ,变得更浓了一些,价格也变贵了。下一步原来是支付这个动作,也有可能正在这个过程当中,后台去处理了,这时请求发生了冲突,后台就会告诉你这个拿铁还是三元,没有办法去加一个 shot ,后台已经做了,也就是你会得到两种不同的响应,那我们就可以根据这个客户端的响应码来控制前端,前端应该展示什么样的页面给用户,409 conflict 表示:对不起,请求不允许。
付账的时候,它已经通过 next 告诉我付账应该往哪儿发。所以,我们先看对着这样的一个位置( OPTIONS/payment/order/1234 HTTP 1.1 )能做什么,回应:能 GET ,PUT。
显然,这个付账的这个信息已经有了,它还是未付的状态,我要给它改成已经付款的状态。所以我就要去对着这个位置( OPTIONS/payment/order/1234 HTTP 1.1 ),去做 PUT,去做更新,可能会涉及到一系列的认证的信息,把这些信息推过去。推过去之后它会告诉你,它会先去生成 payment ,然后在处理完即 update 之后,就会返你支付完成的这个消息。
再看后台,它想要获取所有的请求,就是所有的订单。它同样对着那个 Update 去做处理,然后返回里面。它会说,这里面有多少内容,包含的一个一个的订单有多少个。(如下图所示)
于是就拿到了所有的订单。之后,它说我要开始做了,要去改写一个订单,那改写订单的时候我就要去把订单现在的状态改一下,于是,状态就变成了正在处理。那当时处理完之后还可以再改写,变成操作完成。(下图为这一步的代码)
这就是后台在拿一个订单去做处理和改变状态。然后,就在检查订单,有可能是成功了,或者是失败了等等,基本上都是一类的。
7.删除订单
最后是删除订单,要用 Delete 方法。通过这个例子,可以看到,我们现在是完全数据驱动,就在解决 SOAP 这种方式所带来的缺陷。
8.与 SOAP 相比的优点
如果要去看如何做开发,仍然是看 spring boot 里面如何来做。我们写一个 RestController,那它叫做 greeting controller ,然后它就会有一个 greeting 方法,然后我们可以看到它里面都在映射这个 greeting 路径,但是它一个是 get, 一个是 post, 这里面都会有参数,无论是 get 还是 post 过来的参数,有一个参数是 name 。然后,如果没有传递,我就给它附一个初始值,一个叫做 WERE,一个叫做 Spring 。
不管是哪一个方法过来,我就要返回我前面这一个 template,加上这个参数拼进去以后的字符串,这是一个比较常规的 controller 写法,那其实跟之前 spring 的 control 没有什么区别。
然后 greeting 这个类,它里面就会有一个叫 content ,一个 ID ,有 GET 的方法。
然后,它就会因为我们在前面这写了一个,它是 rest 的 controller ,所以它就可以通过这样的方法去访问,你就能看到它会返你什么样的东西。那如果你用 get 方法访问,它会返回“hello ,word”。 用 post 方法访问,它会返回 “hello,spring”。这就是两个的差异以及支持它的,那这就是我们所谓的 restful web service 。
为了去考虑这个问题,直接去展示比较方便。我们写个 React 前端,它的前端非常简单,先获取它8080端口的 greeting ,然后我会得到一个响应,把这个响应转成 json ,然后提取里面的内容 Data 。提取 data 把它转出来之后,会把它替换掉,提交我们这个 H 1标签里的英语 test, 然后在 council 里面会写相应的动作。
这就是web service,我们跑一下。
然后这边是客户端,客户端写了一个 controller 的东西,它这个 react 的东西要对着这个地方( http://localhost:8080/greeting )去访问,就这样一个东西。
这个 ra 跑起来就返回了这个结果
( “id”:1,”content”:”Hello,World!” ),但是这里面有一个小坑就是,现在我写成两个工程了,所以是有跨域的问题。我现在要讲的就是跨域的问题,在后台,在 spring 里面它可以这么做,就是你允许哪一些跨域的操作。如果是按这个里面的写法,就是你允许所有的来自于跨域的用性和都可以来访问,于是,我们现在虽然是两个工程,而这两个工程起来以后端口号不一样,这个在3000,这个在8000,虽然都在 local host, 但是它们两个的端口不一样,所以存在跨域问题。但是因为我允许所有的脚本的这个模式出现,所以现在我们看到的它就是解决了一个跨越的问题,要靠这种方式来解决跨域,所以这里有个小坑就可以解决跨域。
从这个例子可以看到实现restful web service 反而很简单,如果用 spring 的这个写法的话,就直接是一个 restful 的一个 controller, 它就能实现这样的动作。在这里面要注意的是,Restful 的 controller,它默认情况下,在这里返回一个 greeting 对象,这个对象会被转成 Jason 返回。所以,尽管这里是一个 Java 类型的对象,Greating,它也会被自动转成一个 Jason 返回。
这就是为什么在前台我们得到的东西是一个 Jason的原因,这是有关跨域的定义的。那我们实际上是允许了所有的,都可来访问我的方法,所以我们跨域成功了,当然,跨域有前台的解决方法,也有后台的解决方法。现在是在后台来支持所有跨域操作,知道了 web service 之后,我们可以看到 web service 的好处。
9.SOAP 和 restful web service 的优缺点
它好处主要来说是跨平台,也是异构系统交互,缺点主要是生产率比较低。就是,无论是数据驱动的 restful 还是 SOAP ,生产率都比较低。 restful 涉及到数据的解析的问题,就是仍然还要对数据进行解析,它不如直接跟一个接口绑定一样效率那么高。但是我们要在效率和代码可维护性之间做平衡,所以我们认为 restful 还是可以的。
五.Web Service 的使用场景
那关键的问题就是,什么时候应该用 web service, 什么时候不应该用。比如有异构系统集成的这种需求、跨越防火墙、甚至要做远距离的异构系统的时候,应该考虑用 web service 。那什么时候不太应该用呢?比如单机系统肯定没有必要用,因为它要走 HTTP 协议,这个协议不算是一个高效的协议,跟我们之前讲的 RMI 或者是 GMS 相比,它的效率明显要低。然后在同构的应用里也不需要,尤其是在一个局域网内部之间、程序之间,没有必要用 web service 。虽然 web service 能解决很多问题,但关键的问题是要学会取舍,即知道什么时候要使用。在这里面要强调一点,在开发 web service的时候,如果是在原来的系统上增加功能,就像我提要求,比如要把下订单的功能封装成一个 web service, 其实不需要重新写任何东西,你是在现有的基础上去做封装,它的道理就是实际上你已经有了这个接口和时间类,只需要把某一层封装出来。当然前提是,这是个 SOAP 消息,如果是一个 restful 的消息,改造起来可能会更简单。也就是说,如果你原来用的是 spring ,把原来的 controller 转成 restful controller 就可以了,而唯一带来的一个变化就是,它返回的东西是 Jason 。
尽管写的是一个类或者其他的东西,无论怎样,它一定会转成一个 Jason 。所以,你在前端要稍微修改一下,要说这是一个 Jason 对象,拿来之后要怎么进行处理,其他的没有什么更复杂的地方。
按道理,如果你做的是一个功能齐全的电子书,那么现在要求你做的 web service 作业,不需要做大的改动,只需要在原来的基础上做一些小的修改,做一些扩展就可以了。如果是用 spring 的,要把 controller 改成 restful controller ,在前端改成返回的是 Jason ,要对 Jason 进行处理。
如果你用的是其他的,想要用 SOAP 方式来暴露的话,你只要多加一个, SOAP 上面多去编译一次,生成 WSDL 就可以了,其他的不需要做大的更改。而且支持 service 的后端,你可以用coldhouse,其实还有别的常用的,像 Axis 也可以,不是唯一的,只要能实现就行。