【JAX-WS入门系列】第04章_SOAP异常处理和Handler处理

来源:互联网 发布:税务数据质量检查报告 编辑:程序博客网 时间:2024/05/15 23:53

完整版见https://jadyer.github.io/2013/05/31/jaxws-soap-handler/


客户端和服务端都是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 {@Overridepublic String sayHello(String name) {System.out.println("Receive the name=[" + name + "]......");if(null==name){return "Hello,World";}else{return "Hello," + name;}}@Overridepublic 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> {@Overridepublic Set<QName> getHeaders() {return null;}@Overridepublic void close(MessageContext context) {}@Overridepublic 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 nameString 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> {@Overridepublic Set<QName> getHeaders() {return null;}@Overridepublic void close(MessageContext context) {}@Overridepublic boolean handleFault(SOAPMessageContext context) {System.out.println("\nClient.handleFault() is invoked.....");return false;}@Overridepublic 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......协议有效......JadyerReceive 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]认证通过
原创粉丝点击