客户端soap【JAX-WS入门系列】第04章_SOAP异常处理和Handler处理
这段时间一直在查找客户端soap之类的问题,下午恰好有机会和大家共享一下.
客户端和服务端都是Java Project,首先列出服务端代码
首先是SEI,即服务端接口类HelloService.java
package com.jadyer.service; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import com.jadyer.exception.UserException; @WebService(targetNamespace="http://blog.csdn.net/jadyer") public interface HelloService { @WebResult(name="sayHelloResult") public String sayHello(@WebParam(name="name")String name); @WebResult(name="loginResult") public String login(@WebParam(name="username")String username, @WebParam(name="password")String password) throws UserException; }
然后是SIB,即服务端接口实现类HelloServiceImpl.java
package com.jadyer.service; import javax.jws.HandlerChain; import javax.jws.WebService; import com.jadyer.exception.UserException; @WebService(endpointInterface="com.jadyer.service.HelloService", targetNamespace="http://blog.csdn.net/jadyer") @HandlerChain(file="myHandlerChain.xml") public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { System.out.println("Receive the name=[" + name + "]......"); if(null==name){ return "Hello,World"; }else{ return "Hello," + name; } } @Override public String login(String username, String password) throws UserException { System.out.println("Receive the username=[" + username + "],password=[" + password + "]......"); if("admin".equals(username) && "hongyu".equals(password)){ return "用户[" + username + "]认证通过"; } throw new UserException("用户[" + username + "]认证未通过"); } }
下面是自定义的服务端异常类UserException.java
package com.jadyer.exception; //这里不要用RuntimeException //因为RuntimeException会致使服务端在抛异常给客户端时,服务端自身也会抛相同的异常 //所以WebServices开辟中定义异常时要注意这一点 public class UserException extends Exception { private static final long serialVersionUID = 6252203957834273236L; public UserException() { super(); } public UserException(String message) { super(message); } }
下面是自定义的服务端Handler类LicenseHandler.java
package com.jadyer.handler; import java.util.Iterator; import java.util.Set; import javax.xml.namespace.QName; import javax.xml.soap.SOAPBody; 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.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; import javax.xml.ws.soap.SOAPFaultException; /** * Handler编写步调 * 1)创建一个实现了SOAPHandler<SOAPMessageContext>的类 * 2)在handleMessage()方法中编写代码 * 3)配置Handler,自定义一个名字随意的xml * 4)在服务上启动过滤链 * 在服务端或者客户端的Service实现类上应用@HandlerChain(file="myHandlerChain.xml")便可 * @create May 17, 2013 12:07:54 AM * @author 玄玉<http://blog.csdn.net/jadyer> */ public class LicenseHandler implements SOAPHandler<SOAPMessageContext> { @Override public Set<QName> getHeaders() { return null; } @Override public void close(MessageContext context) { } @Override public boolean handleFault(SOAPMessageContext context) { System.out.println("Server.handleFault() is invoked......"); return false; } @Override @SuppressWarnings("unchecked") public boolean handleMessage(SOAPMessageContext context) { System.out.println("Server.handleMessage() is invoked......"); //从服务端角度看:inbound表示接收客户端消息,outbound表示响应消息给客户端..从客户端角度看时恰好与之相反 Boolean isOutBound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if(isOutBound){ return true; } SOAPMessage message = context.getMessage(); SOAPHeader header = null; SOAPBody body = null; try { SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); header = envelope.getHeader(); body = envelope.getBody(); } catch (SOAPException e) { e.printStackTrace(); } //获得Body中的part name String partName = body.getChildNodes().item(0).getLocalName(); //只对服务端开放的login()方法进行验证,否则它会对服务端开放的全部方法进行验证 if(!"login".equals(partName)){ return true; } if(null==header){ System.out.println("未找到头信息......"); this.throwHeaderInvalid(body, "未找到头信息......"); } Iterator<SOAPHeaderElement> iterator = header.extractAllHeaderElements(); if(!iterator.hasNext()){ System.out.println("头信息不能为空......"); this.throwHeaderInvalid(body, "头信息不能为空"); } System.out.println("协议有效......"); while(iterator.hasNext()){ System.out.println(iterator.next().getTextContent()); } return true; } private void throwHeaderInvalid(SOAPBody body, String causeInfo){ try { //添加一个错误信息 SOAPFault fault = body.addFault(); fault.setFaultString("协议无效:" + causeInfo); throw new SOAPFaultException(fault); } catch (SOAPException e) { e.printStackTrace(); } } }
接下来是用于配置Handler的myHandlerChain.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <javaee:handler-chain> <javaee:handler> <javaee:handler-class>com.jadyer.handler.LicenseHandler</javaee:handler-class> </javaee:handler> </javaee:handler-chain> </javaee:handler-chains>
最后是宣布WebService服务的ServerApp.java
package com.jadyer.server; import javax.xml.ws.Endpoint; import com.jadyer.service.HelloServiceImpl; /** * SOAP异常处置和Handler处置 * @see ---------------------------------------------------------------------------------------------- * @see 手工指定命名空间时,提议在SEI和SIB都应用@WebService注解,如下所示 * @see @WebService(targetNamespace="http://blog.csdn.net/jadyer") * @see ---------------------------------------------------------------------------------------------- * @see 通过Handler处置SOAP消息(Handler类似于过滤器,它分为SOAPHandler和LogicalHandler) * @see SOAPHandler-----可以获得SOAPMessage信息 * @see LogicalHandler--只能获得SOAPBody信息 * @see 客户端发出的消息始终都是LogicalHandler先处置,然后才是SOAPHandler处置,服务器端的消息处置顺序则与之相反 * @see ---------------------------------------------------------------------------------------------- * @create May 16, 2013 6:14:10 PM * @author 玄玉<http://blog.csdn.net/jadyer> */ public class ServerApp { public static void main(String[] args) { Endpoint.publish("http://127.0.0.1:8888/myHelloService", new HelloServiceImpl()); } }
至此,服务端代码宣布完毕,下面是客户端代码
首先是客户端自定义的Handler类HeaderHandler.java
package com.jadyer.handler; import java.io.IOException; import java.util.Set; import javax.xml.namespace.QName; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPMessage; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; public class HeaderHandler implements SOAPHandler<SOAPMessageContext> { @Override public Set<QName> getHeaders() { return null; } @Override public void close(MessageContext context) { } @Override public boolean handleFault(SOAPMessageContext context) { System.out.println("\nClient.handleFault() is invoked....."); return false; } @Override public boolean handleMessage(SOAPMessageContext context) { System.out.println("\nClient.handleMessage() is invoked....."); Boolean isOutBound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if(isOutBound){ SOAPMessage message = context.getMessage(); try { SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); SOAPHeader header = envelope.getHeader(); String partName = envelope.getBody().getChildNodes().item(0).getLocalName(); // System.out.println("------------------------------------"); // NodeList nan = envelope.getBody().getChildNodes(); // System.out.println("nan.getLength()=" + nan.getLength()); // for(int i=0; i<nan.getLength(); i++){ // System.out.println(nan.item(i).getLocalName()); // } // System.out.println("------------------------------------"); //只在访问服务端login()方法时才加头信息 if("login".equals(partName)){ if(null == header){ header = envelope.addHeader(); } QName qname = new QName("http://blog.csdn.net/jadyer", "licenseInfo", "ns"); header.addHeaderElement(qname).setValue("Jadyer"); message.writeTo(System.out); } } catch (SOAPException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } return true; } }
下面是用于配置客户端Handler的myHandlerChain.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <javaee:handler-chain> <javaee:handler> <javaee:handler-class>com.jadyer.handler.HeaderHandler</javaee:handler-class> </javaee:handler> </javaee:handler-chain> </javaee:handler-chains>
最后是客户端调用服务端代码
注:客户端代码由wsimport生成,详见http://blog.csdn.net/jadyer/article/details/8692108
package com.jadyer.client; import javax.xml.ws.soap.SOAPFaultException; import net.csdn.blog.jadyer.HelloService; import net.csdn.blog.jadyer.HelloServiceImplService; import net.csdn.blog.jadyer.UserException_Exception; public class ClientApp { public static void main(String[] args) { HelloService server = new HelloServiceImplService().getHelloServiceImplPort(); try { System.out.println(server.sayHello("玄玉")); System.out.println(server.login("admin", "hongyu")); } catch (UserException_Exception e) { //捕获服务端login()方法可能抛出的用户认证未通过的异常 System.out.println("UserException:" + e.getMessage()); } catch (SOAPFaultException e) { //捕获服务端可能抛出的SOAPHeader为空的异常 System.out.println("SOAPFaultException:" + e.getMessage()); } } }
最后把示例运行时,控制台的输出也贴出来
下面是服务端的控制台输出
Server.handleMessage() is invoked...... Receive the name=[玄玉]...... Server.handleMessage() is invoked...... Server.handleMessage() is invoked...... 协议有效...... Jadyer Receive the username=[admin],password=[hongyu]...... Server.handleMessage() is invoked......
下面是客户端的控制台输出
Client.handleMessage() is invoked..... Client.handleMessage() is invoked..... Hello,玄玉 Client.handleMessage() is invoked..... <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Header><ns:licenseInfo xmlns:ns="http://blog.csdn.net/jadyer">Jadyer</ns:licenseInfo></S:Header><S:Body><ns2:login xmlns:ns2="http://blog.csdn.net/jadyer"><username>admin</username><password>hongyu</password></ns2:login></S:Body></S:Envelope> Client.handleMessage() is invoked..... 用户[admin]认证通过
文章结束给大家分享下程序员的一些笑话语录: 据说有一位软件工程师,一位硬件工程师和一位项目经理同坐车参加研讨会。不幸在从盘山公路下山时坏在半路上了。于是两位工程师和一位经理就如何修车的问题展开了讨论。
硬件工程师说:“我可以用随身携带的瑞士军刀把车坏的部分拆下来,找出原因,排除故障。”
项目经理说:“根据经营管理学,应该召开会议,根据问题现状写出需求报告,制订计划,编写日程安排,逐步逼近,alpha测试,beta1测试和beta2测试解决问题。”
软件工程说:“咱们还是应该把车推回山顶再开下来,看看问题是否重复发生。”
---------------------------------
原创文章 By
客户端和soap
---------------------------------