JWS服务开发使用指南.doc_第1页
JWS服务开发使用指南.doc_第2页
JWS服务开发使用指南.doc_第3页
JWS服务开发使用指南.doc_第4页
JWS服务开发使用指南.doc_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1. 概述1.1. 目的本文档的目的是提供JAX-WS 规范的WebService服务开发和使用指南,在服务开开发和使用过程中介绍相关事项,提供一些一般性的原则约束。1.2. 依赖条件1、 从JDK5开始,JAVA为WebService提供了Jax-ws(更多关于JAX-WS的信息参考“了解JAX-WS”章节)支持,所以使用该指南需要具备JAVA 的JDK5版本2、 Servlet2.5,Jax-ws最终实现依赖Servlet2.5以上版本,Tomcat6.0、Weblogic10以上版本均支持该版本,主要你的web.xml文件中必须制定2.5版本 WebServiceDevGuide 3、 该指南默认将开发的服务部署在Weblogic10以上版本,对于Tomcat6.0以上的不完全J5EE容器,需要使用CXF来提供额外的WebService支撑功能。2. 开发WebService2.1. WebService开发真的很简单一个简单的WebService示例如下:1、首先定义一个HelloServivce接口:package gov.szpl.ws.hello;import javax.jws.WebService;WebServicepublic interface HelloService /* * 最简单的sayHello方法. * return 返回:Hello name! */public String sayHello(String name);注意:引入了WebService来注释HelloService接口,它属于JAX-WS2、定义HelloService的实现类package gov.szpl.ws.hello;import javax.jws.WebService;WebService(serviceName=HelloService,endpointInterface=gov.szpl.ws.hello.HelloService)public class HelloServiceImpl implements HelloService public String sayHello(String name) / return Hello +name+!;注意:HelloServiceImpl类使用再次用了WebService声明,并添加服务名和端点接口来描述即将发布的WebService属性。3、不要紧张,完了,就这么多。如果上面的接口和类是放到Dynamic Web工程中,该工程导出为War包,输出到Weblogic10自动部署文件夹,即可你就成功发布了HelloWebService这个服务了。什么,不需要依赖任何Jar包吗?不需要不是更好吗?Weblogic老板在后台把所有的事情自动张罗好了。那Weblogic都做了些啥?扫描WEB-INFO/classes目录类,发现有WebService修饰了类,启动JAX-WS对于的模块,动态创建WSDL文件,并将其发布为WebService可以部署在Tomcat吗?YES,这个可以有,不过需要添加CXF的支持,CXF是个什么东东呢,他的前身是XFire,现在是一个非常广泛使用的WebService框架。2.2. 渐进演化2.2.1. Wsdl中参数和返回值描述为arg0、arg1后台自动创建的WSDL中默认情况下,参数均是arg0,arg2. 确实令人难堪,即使是用户Eclipse创建客户程序,接口也非常不可读,那么怎么处理这个问题呢,JAX-WS已经帮你想好了这一问题的解决方案,就是使用WebParam注解来标识参数。还是以HelloService来演示,HelloServiceImpl服务接口实现类不需要任何改动,这也充分体现了面向接口编程的思想,也说明了为什么需要在服务实现类中指定endpointInterface的原因。package gov.szpl.ws.hello;import javax.jws.WebParam;import javax.jws.WebService;WebServicepublic interface HelloService /* * 最简单的sayHello方法. * return 返回:Hello name! */public String sayHello(WebParam(name=name)String name);重新发布一次,试一试,注意到变化了吗?参数名称已经发生变化了,我所做的仅仅是参数前面多加了WebParam(name=name)这用一小段2.2.2. Web方法中的参数和返回值是对象1、 作为参数的对象,仅仅是一个普通JAVA 类(POJO)package anization.dept;public class Dept private int deptId;private String deptName;private String code;private String burea;public int getDeptId() return deptId;public void setDeptId(int deptId) this.deptId = deptId;public String getDeptName() return deptName;public void setDeptName(String deptName) this.deptName = deptName;public String getCode() return code;public void setCode(String code) this.code = code;public String getBurea() return burea;public void setBurea(String burea) this.burea = burea;不过这里还是要强调一下的是,关于Web方法的参数问题,可以支持基本类型(int,long),基本类型的包装类型(Integer,Long.)String、List 等,但不可用使用Map,因为Map类型太不确定了,会抛出异常的。2、 定义服务接口package anization.dept;import javax.jws.WebParam;import javax.jws.WebService;WebServicepublic interface DeptService public String getDeptCode(WebParam(name=deptId)int deptId);public String getDeptCodeByDept(WebParam(name=dept)Dept dept);public Dept getDept(WebParam(name=deptId)int deptId);关于WebService和WebParam前面已经介绍过,你懂的。3、 定义服务接口实现package anization.dept;import javax.jws.WebService;WebService(endpointInterface=anization.dept.DeptService,serviceName=DeptService)public class DeptServiceImpl implements DeptService public String getDeptCode(int deptId) / TODO Auto-generated method stubreturn deptCode for dpetId (+String.valueOf(deptId)+) is x1 ;public String getDeptCodeByDept(Dept dept) / TODO Auto-generated method stubreturn deptCode for dpetId (+String.valueOf(dept.getDeptId()+) is x2 ;public Dept getDept(int deptId) / Dept dept = new Dept();dept.setDeptId(deptId);dept.setDeptName(test dept name );return dept;Ok,搞定,打包部署,同样非常简单吧2.2.3. 如何出处理SOAP Header 这一章节的内容相对高级一点,不过放心好了,理解了之后一点也不复杂,同样So Easy. 认识JAX-WS Handlerpackage javax.xml.ws.handler;import javax.xml.ws.ProtocolException;import javax.xml.ws.handler.MessageContext;/* JAX-WS 处理器接口 * since JAX-WS 2.0*/public interface Handler /* * 可调用 handleMessage 方法进行普通的入站和出站消息处理。 * 有关完整信息,请参阅 JAX-WS 规范中处理程序框架的描述。 * param context - 消息上下文。 * return 指示处理程序是否应该继续处理当前消息。 * 返回 true 表示继续处理。 * 返回 false 表示停止处理。 */ public boolean handleMessage(C context); /* 可调用 handleFault 方法进行错误消息处理 * * param context - 消息上下文 * return 指示处理程序错误处理是否应该继续处理当前消息 * 返回 true 表示继续处理。 * 返回 false 表示停止处理。 */ public boolean handleFault(C context); /* * 消息交换模式结束时调用,正好发生在 JAX-WS 运行时指派消息、错误或异常之前。 * * param context - 消息上下文。 */ public void close(MessageContext context);JAX-WS中的Handler和Servlet中的Filter非常相似,这使得我们可以在真实的服务方法调用之前实现拦截。. 定义自己的Handlerpackage gov.szpl.ws.lookhandler.handler;import java.util.Collections;import java.util.Iterator;import java.util.Set;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import javax.servlet.http.HttpServletRequest;import space.QName;import javax.xml.soap.SOAPBody;import javax.xml.soap.SOAPConstants;import javax.xml.soap.SOAPEnvelope;import javax.xml.soap.SOAPException;import javax.xml.soap.SOAPFault;import javax.xml.soap.SOAPHeader;import javax.xml.soap.SOAPHeaderElement;import javax.xml.soap.SOAPMessage;import javax.xml.transform.OutputKeys;import javax.xml.transform.Result;import javax.xml.transform.Source;import javax.xml.transform.Transformer;import javax.xml.transform.TransformerException;import javax.xml.transform.TransformerFactory;import javax.xml.transform.dom.DOMSource;import javax.xml.transform.stream.StreamResult;import javax.xml.ws.ProtocolException;import javax.xml.ws.handler.MessageContext;import javax.xml.ws.handler.soap.SOAPHandler;import javax.xml.ws.handler.soap.SOAPMessageContext;import javax.xml.ws.soap.SOAPFaultException;/* * 实现了SOAPHandler,SOAPHandler是Handler的子接口 */public class AuthHandler implements SOAPHandler / lifecycle method invoked when this Handler is constructed.PostConstructvoid init() System.out.println(SOAPHandler:t + this.getClass() + has been constructed);/ lifecycle method invoked this Handler is to be destroyed.PreDestroyvoid destroy() System.out.println(SOAPHandler:t + this.getClass() + will be destroyed);public Set getHeaders() return Collections.emptySet();public boolean handleMessage(SOAPMessageContext smc) return parseHeader(smc);public boolean handleFault(SOAPMessageContext smc) /return true;/ nothing to clean uppublic void close(MessageContext messageContext) / 不需任何处理./* * 分析SOAPHeader. * * param smc * return */private boolean parseHeader(SOAPMessageContext smc) / 获取客户端IP,do something.HttpServletRequest request = (HttpServletRequest) smc.get(MessageContext.SERVLET_REQUEST);System.out.println(客户端IP = + request.getRemoteAddr();boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);if (outboundProperty) System.out.println(nOutbound SOAP Headers:); else System.out.println(nInbound SOAP Headers:);SOAPMessage soapMessage = smc.getMessage();try SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();SOAPHeader soapHeader = soapEnvelope.getHeader();if (soapHeader = null | !soapHeader.hasChildNodes() /generateSoapFault(soapMessage, No Message in Header.);generateSoapFault(soapMessage, 消息头中没有授权用户信息,拒绝访问.);Iterator iter = soapHeader.extractHeaderElements(SOAPConstants.URI_SOAP_1_2_ROLE_NEXT);SOAPHeaderElement element = iter.next();String value = element = null ? null : element.getValue();if (value = null) generateSoapFault(soapMessage,No authentication info in header blocks);/ 后台输出.print(new DOMSource(soapMessage.getSOAPHeader();/ 从Value中解析username passwordString params = value.split(,);String username = params0;String password = params1;return authValidate(username, password); catch (SOAPException ex) / throw new RuntimeException(ex);throw new ProtocolException(ex.getMessage();private boolean authValidate(String username, String password) return admin.equals(username) & admin.equals(password);/* * 抛出SOAP失败异常. * * param soapMessage * param reasion */private void generateSoapFault(SOAPMessage soapMessage, String reasion) try SOAPBody soapBody = soapMessage.getSOAPBody();SOAPFault soapFault = soapBody.getFault();if (soapFault = null) soapFault = soapBody.addFault();soapFault.setFaultString(reasion);throw new SOAPFaultException(soapFault); catch (Exception e) /转换为可处理异常.throw new ProtocolException(e);private static void print(Source payload) try TransformerFactory factory = TransformerFactory.newInstance();Transformer tf = factory.newTransformer();tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, yes);tf.setOutputProperty(OutputKeys.METHOD, xml);tf.setOutputProperty(OutputKeys.INDENT, yes);Result result = new StreamResult(System.out);tf.transform(payload, result); catch (TransformerException e) e.printStackTrace();. 将定义的Handler应用到服务上1、 在服务接口上添加HandlerChainpackage gov.szpl.ws.lookhandler;import javax.jws.HandlerChain;import javax.jws.WebParam;import javax.jws.WebService;WebServiceHandlerChain(file=handler-chain.xml)public interface HelloHandlerService /* * 最简单的sayHello方法. * return 返回:Hello name! */public String sayHello(WebParam(name=name)String name);注意:服务接口仅仅多了行HandlerChain(file=handler-chain.xml)。2、 在服务接口所在的目录创建HandlerChain配置文件。 gov.szpl.ws.lookhandler.handler.AuthHandler Handler-cclass 执行之前定义的Handler类。3、 完毕,部署运行试一试,看到不一样的效果了吧。. 不得不说的异常处理Handler接口没有提到异常,但是在它的API文档中有提到两个异常:RuntimeException, ProtocolException,SoapFaultException是ProtocalException的子类。如果需要在Handler方法中抛出异常显示到服务调用的客户端,直接抛出这几类异常即可。2.3. 原则与约束2.3.1. 服务接口和业务接口如何界定可以有两种方法来来处理这一问题1、 提供Decorator模式来处理服务接口的暴露2、 通过WebMethod(exclude=”true”) 来标服务接口推荐使用第一种方式来处理,这样有利于分离变化,保障接口的相对稳定性。2.3.2. 发布的服务需要将一系列的对象暴露到接口发布的服务接口设计到模型对象,而这些模型对象又不在服务接口所在的包。如:Package com.szpl.ws;Public interface UserSanization.User getUser(String userId);这里的User类和服务类不再同一个package中,可以考虑在com.szpl.ws下创建一个User类,这样的好处是,方便客户端使用服务接口,隔离依赖,当然也带来了一定的工作量。2.4. more and more接口中的某些方法真的不想将它暴露出去REST2.5. 还有其他方式?会更简单吗?基于JAVA发布WebService,基本上这就是最简单的了。3. 使用WebService3.1. SoapuisoapUI是一个开源测试工具,通过SOAP/HTTP来检查、调用、实现Web Service的功能/负载/符合性测试。该工具可以作为一个单独的测试工具来使用,也可以基础到Eclipse开发工具中3.2. Weblogic console发布在Weblogic上的WebService,可以在控制台的deployment- Monitoring Web Service 查看到所有成功发布的WebService,点击列表中的WebService,显示WebService,再点击Testing继续。3.3. 裸调(和XML干上了)JAX-WS提供了直接用XML调用WebService的接口,还算简洁,麻烦一点的是对XML文档的拼装。package gov.szpl.ws.hello.client;import java.io.InputStream;import .URL;import space.QName;import javax.xml.soap.MessageFactory;import javax.xml.soap.SOAPMessage;import javax.xml.transform.OutputKeys;import javax.xml.transform.Result;import javax.xml.transform.Source;import javax.xml.transform.Transformer;import javax.xml.transform.TransformerException;import javax.xml.transform.TransformerFactory;import javax.xml.transform.dom.DOMSource;import javax.xml.transform.stream.StreamResult;import javax.xml.ws.Dispatch;import javax.xml.ws.Service;/* * 基于JAX-WS接口调用WebService的客户端示例。 */public class HelloServiceJwsClient public static void main(String args) try URL wsdlURL = new URL(3:7001/WebServiceDevGuide/HelloService?WSDL);QName serviceName = new QName(/,HelloService);QName portName = new QName(/,HelloServiceImplPort);MessageFactory messageFactory = MessageFactory.newInstance();Service service = Service.create(wsdlURL, serviceName);/Dispatch disp = service.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);Dispatch disp = service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);/xml请求保存在文件中。InputStream is1 = HelloServiceJwsClient.class.getResourceAsStream(sayHelloRequest1.xml);/Source request = new StreamSource(is1);SOAPMessage request = messageFactory.createMessage(null, is1); /执行SOAP调用。SOAPMessage response = disp.invoke(request);/将Message转换为SourceDOMSource responseSource = new DOMSource(response.getSOAPBody();print(responseSource); catch (Exception e) e.printStackTrace();private static void print(Source payload) try TransformerFactory factory = TransformerFactory.newInstance();Transformer tf = factory.n

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论