加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

WebService学习之路四

发布时间:2020-12-16 22:10:33 所属栏目:安全 来源:网络整理
导读:? WebService学习之路一 :http://trylin.iteye.com/blog/1906819 ? WebService学习之路二 :http://trylin.iteye.com/blog/1907883 ? WebService学习之路三 :http://trylin.iteye.com/blog/1908269 ? SOAP 的理解使用 ? 不论是以那种形式实现WS服务,axis

?

WebService学习之路一 :http://trylin.iteye.com/blog/1906819

?

WebService学习之路二 :http://trylin.iteye.com/blog/1907883

?

WebService学习之路三 :http://trylin.iteye.com/blog/1908269

?

SOAP 的理解使用

?

不论是以那种形式实现WS服务,axis也好,xfire,CXF也好 ,服务进行消息传替都是基于SOAP格式的。

?

这里简单理解一下SOAP信息,和实现使用SOAP格式的调用我们发布的WS.

?

1、SOAP消息格式。

打开之前的第一个简单示例的服务。

?

eclipse的视图模式改为javaee,并且打开wsdl浏览



?选择WSDL视图

?



?

?

选择一个WSDL MAIN,并输入我们发布的WSDL地址。


?看到我们发布的两个方法了吧,选择add然后输入两个参数,点击go,然后点击下发status项的 Source,

?

?



?

?

?

这样就可以看到我们请求WS的请求和返回的SOAP消息,上面是请求,下面是返回 。请求的参数都是被包裹在一个Body的对象中,然后是方法,再是方法下的参数。

?



?

?看到SOAP消息,有没有觉得和我们发布的WSDL的types的格式很像,下面截图做个简单的比较,一目了然。

?

?

?



?

2、使用SOAP消息访问WS

?

上面看到了我们请求返回的SOAP消息,那当然我们也可以根据SOAP的消息格式访问我们发布的WS服务,这就要使用到jdk扩展包下的 soap 包。

?

?

?

在我们客户端的项目中新建一个类 SOAPImpl(具体代码有注释,更多的可以看视频的中的解释哦)

学习视频地址:http://trylin.iteye.com/blog/1907289

?

WS服务端代码:(由于之前有测试过命名空间相关的东西,下面的测试都是基于默认命名空间,如果按照第一章的示例来直接用下面的客户端访问 可能会出现找不到方法的情况,或者你可以把我的测试代码的命名空间修改下,都是可以的,这里我把除去命名空间的服务端代码也贴上。。。)

?

Java代码??

收藏代码

  1. @WebService()??
  2. public?interface?ITest?{??
  3. ????int?add(@WebParam(name="a")int?a,?@WebParam(name="b")int?b);??
  4. ????int?minus(int?b);??
  5. }??
  6. @WebService(endpointInterface="com.trylin.ws.service.ITest")??
  7. class?TestImpl?implements?ITest{??
  8. ????int?add(int?b)?{??
  9. ????????System.out.println(a+"+"+b+"="+(a+b));??
  10. ????????return?a+b;??
  11. ????}??
  12. ????int?minus(int?b)?{??
  13. ????????return?a-b;??
  14. ????}??
  15. }??

?

?客户端:

Java代码??
  • class?SOAPImpl?{??
  • ??????
  • ????/**?服务地址?*/??
  • ????public?URL?url?=?null;??
  • ????/**?服务命名空间?*/??
  • ????public?String?ns?=?"http://impl.service.ws.trylin.com/";??
  • ????/**?命名空间变量?*/??
  • ????public?String?xlns?=?"nn";??
  • ??????
  • ????public?SOAPImpl(){??
  • ????????try?{??
  • ????????????url?=?new?URL("http://localhost:8888/WS");??
  • ????????}?catch?(MalformedURLException?e)?{??
  • ????????????//?TODO?Auto-generated?catch?block??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • ??????
  • ????/**?
  • ?????*?创建add方法的SOAP消息?
  • ?????*?@return?
  • ?????*?@throws?Exception?
  • ?????*/??
  • ????protected?SOAPMessage?add()?throws?Exception{??
  • ????????MessageFactory?factory?=?MessageFactory.newInstance();//创建消息工厂??
  • ????????SOAPMessage?message?=?factory.createMessage();//创建消息类型??
  • ????????SOAPPart?part?=?message.getSOAPPart();//创建Part元素??
  • ????????SOAPEnvelope?envelope?=?part.getEnvelope();//创建envelope元素???SOAP的根节点??
  • ????????SOAPBody?body?=?envelope.getBody();//body对象??
  • ????????//指定body下节点?请求的方法add元素??
  • ????????SOAPBodyElement?bodyElement?=?body.addBodyElement(new?QName("http://service.ws.trylin.com/","add",xlns));??
  • ????????//设置add方法的参数??
  • ????????bodyElement.addChildElement("a").setValue("1");??
  • ????????bodyElement.addChildElement("b").setValue("2");??
  • ????????message.writeTo(System.out);??
  • ????????return?message;??
  • ????}??
  • ??????
  • ?????????*?通过Service将SOAP消息提交到WS服务端,并返回服务端的SOAPMessage?
  • public?SOAPMessage?getSOAPWS()?throws?Exception{??
  • ????????//创建发送Service??设定Qname?TestImplService??服务名??
  • ????????Service?service?=?Service.create(url,85)">new?QName(ns,"TestImplService"));??
  • ????????//通过dispatch发送请求??设置请求格式为Service.Mode.MESSAGE??
  • ????????Dispatch<SOAPMessage>?dispath?=?service.createDispatch("TestImplPort"),??
  • ????????????????SOAPMessage.class,?Service.Mode.MESSAGE);??
  • ????????SOAPMessage?request?=?this.add();??
  • ????????System.out.println("n.......");??
  • ????????SOAPMessage?response?=?dispath.invoke(request);??
  • ????????response.writeTo(System.out);??
  • ????????return?response;??
  • ????}??
  • ??????
  • ?????????*?解析服务端的SOAPMessage?
  • ?????*?@param?message?
  • void?parseSOAPMessage(SOAPMessage?message)?throws?Exception{??
  • ????????System.out.println();??
  • ????????Document?document?=?message.getSOAPPart()??
  • ????????????.getEnvelope().getBody().extractContentAsDocument();//获取Body节点元素文本对象??
  • ????????Element?element?=?document.getDocumentElement();??
  • ????????System.out.println((element.getElementsByTagName("return").item(0).getTextContent()));//打印返回值??
  • ????}??
  • }??
  • ?

    ?

    然后在写客户端测试用例:

    ?

    Java代码?? class?TestSOAP?{??
  • ????@Test??
  • ????void?test01()?throws?Exception{??
  • ????????SOAPImpl?soap?=?new?SOAPImpl();??
  • ????????soap.parseSOAPMessage(soap.getSOAPWS());??
  • ????}??
  • }??
  • ?运行后,查看我们定义的soap输出和服务的返回 soap 还有返回的计算结果

    ?

    ?

    ?




    ?这个是简单的服务访问,我们添加一个自定义的User对象,在服务中再添加一个用户登录的方法,然后发布后,通过WSDL浏览器,请求login服务,看下这时的soap消息是啥样的。

    首先创建一个User

    ?

    Java代码?? class?User?{??
  • ????private?String?userName;?//名字??
  • ????private?int?age;//年龄??
  • ????boolean?isBoy;//??
  • ????double?money;//??
  • ……省略get?set??
  • }??
  • ?服务类中 添加login方法

    ?

    ?

    Java代码?? int?b);??
  • ????@WebMethod(operationName="login")??
  • ????public?@WebResult(name="user")User?login(@WebParam(name="user")User?user);??
  • }??
  • return?a-b;??
  • ????}??
  • ????public?User?login(User?user){??
  • ????????if("hiboy".equals(user.getUserName())){??
  • ????????????user.setAge(12);??
  • ????????????user.setBoy(true);??
  • ????????????user.setMoney(100);??
  • ????????????return?user;??
  • ????????}??
  • ????????return?null;??
  • ????}??
  • }??
  • ?这里用到了几个注释,简单说明一下:

    ?

    ?

    @WebService()? 标记创建WS服务,可以设置命名空间,实现接口,服务名称等。

    ?

    @WebParam() 表示参数在wsdl中显示的名称,默认参数名是按照arg0.. argN,可以手动设定,如@WebParam(name="a")int?a?? 这样a元素在wsdl中就显示成a而不是 arg0

    ?

    @WebResult这个表示返回参数在wsdl显示的名称,默认返回参数名称为return,如@WebResult(name="user")User 这样在wsdl中login的返回参数名就是user了

    ?

    @WebMethod 表示wsdl中显示的方法名,默认是按照原方法名显示,这里可以修改。

    ?

    ?

    ?

    然后启动服务,通过WSDL浏览器访问我们的login方法,查看SOAP消息。仔细看下User的格式哦。


    ?

    ?

    看到SOAP消息了,然后我们在用客户端去按照SOAP消息的格式访问WS。

    ?

    这里的访问有两种方法,第一种就是前面说的,给body对像手动的添加节点,这样比较死,一个一个的添加,也比较累。第二种方法,可以通过JAXB 将一个User对象格式化成类似上面soap消息的xml。可以先试下第一种方法,我这里写第二种。

    ?

    ?在客户端,我们也要生成XMl对应的user对象

    ?

    Java代码?? @XmlRootElement//注意这个注解??不加下面使用jaxB的时候会报错??
  • class?User?{??
  • ??????
  • ????//是否??
  • ????//??
  • ?????//...get??set??
  • }??
  • ?在SOAPImpl类中新增加几个方法

    ?

    ?

    ?

    Java代码??
  • ?????*?设置Login的?Source对象??Source简单理解为数据源?
  • protected?Source?login()?throws?Exception{??
  • ????????User?user?=?new?User();??
  • ????????user.setUserName("hiboy");//设置参数?User??
  • ????????JAXBContext?context?=?JAXBContext.newInstance(User.class);//创建JAXB文档对戏那个??
  • ????????Marshaller?mar?=?context.createMarshaller();??
  • ????????mar.setProperty(Marshaller.JAXB_FRAGMENT,85)">true);//设置生成的xml不包含xml头????
  • ????????StringWriter?writer?=?new?StringWriter();??
  • ????????mar.marshal(user,?writer);//处理User??
  • ????????//JAXBContext??只处理User对像?所以方法声明的部分?还是的自己手写??
  • ????????String?payLoad?=?"<"+xlns+":login?xmlns:"+xlns+"=""+"http://service.ws.trylin.com/"+"">"+writer.toString()+"</nn:login>";??
  • ????????System.out.println(payLoad);??
  • ????????//穿件?Source流对象??
  • ????????Source?source?=?new?StreamSource(new?StringReader(payLoad));??
  • ????????return?source;??
  • ????}??
  • ?????????*?通过Service将Source发送到服务端??并且返回服务端的Source?
  • public?Source?getSOAPLoginWS()?throws?Exception{??
  • ????????Service?service?=?Service.create(url,"TestImplService"));??
  • ????????Dispatch<Source>?dispath?=?service.createDispatch(????????????????Source.????????Source?request?=?this.login();??
  • ????????Source?response?=?dispath.invoke(request);??
  • ????????return?response;??
  • ????}??
  • ?????????*?解析Source?
  • ?????*?@param?source?
  • void?parseSOAPSource(Source?source)?throws?Exception{??
  • ????????System.out.println();??
  • ????????//解析的时候?需要获得节点对象??所以此处用?Transformer转换??
  • ????????Transformer?transformer??=?TransformerFactory.newInstance().newTransformer();??
  • ????????DOMResult?result?=?new?DOMResult();??
  • ????????transformer.transform(source,?result);??
  • ????????//第一层?获取response节点???
  • ????????Node?nl?=??result.getNode().getFirstChild().getFirstChild();??
  • ????????JAXBContext?context?=?JAXBContext.newInstance(User.class);??
  • ????????Unmarshaller?umar?=?context.createUnmarshaller();??
  • ????????User?user?=?(User)umar.unmarshal(nl);??
  • ????????System.out.println(user.getMoney());??
  • ????}??
  • ?

    编写测试类:

    Java代码?? @Test??
  • void?test02()?throws?Exception{??
  • ????SOAPImpl?soap?=?new?SOAPImpl();??
  • ????soap.parseSOAPSource(soap.getSOAPLoginWS());??
  • }??
  • ?运行 输出 : ?100.0就是我们在服务端 给User加的一个值,这样表示通过SOAP调用成功。



    ?

    还是那句话,本人技术不牢靠,可能整理的这些有点乱,也没有按照视频上的原样规规矩矩的记录所有。也有一些内容都是自己的理解,肯定有理解有误的地方。这里解释不详细的,有错误的,还行看到博客的大神在回复中留下你们的间接,如果有幸有童鞋模仿上面的示例,有问题的也可以提出,我们一起解决。。。

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

      推荐文章
        热点阅读