zoukankan      html  css  js  c++  java
  • 客户端soap【JAXWS入门系列】第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
    ---------------------------------

  • 相关阅读:
    linux系统swap分区容量扩展
    linux系统lv_root分区容量扩展
    linux系统创建新LV,挂载新分区。
    linux 服务器重启后lvm 变成inactive状态解决
    Linux下使用fdisk扩大分区容量
    go语言 调用飞书群消息机器人接口
    SpringCloud Sentinel 学习笔记
    Git 笔记整理
    SpringBoot 整合 RabbitMQ 学习笔记
    js递归生成树形结构-vue
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3113057.html
Copyright © 2011-2022 走看看