SOAP客户端

1.主要是为了加强对SOAP远程方法调用的学习,特意自己写了一个SOAP Client端.
2.要求环境:JDK1.6 以上,Axis2 以上
3.主要代码
3.1 SimpleService类
import java.util.ArrayList;
import java.util.List;

public class SimpleService {

	public String getGreeting(String name) {

		long time = System.currentTimeMillis();

		try {

			Thread.sleep(19000); 

		} catch (Exception e) {
             
		}
		long cost = System.currentTimeMillis() - time;
		System.out.println("cost " + cost);
		return "你好 " + name;
	}

	public int getException(){
		System.out.println("getException");
		if(true){
			throw new RuntimeException("Exception");
		}	
		return -1;
	}
	 
	public int getPrice(int price) {
		System.out.println("getPrice");
		return price*2;
	}
	 
	public float getFloatPrice(float price) {
		System.out.println("getFloatPrice");
		return price*2.0f;
	}  

	public People getPeople() {
		return new People("zhangkunlie", "boy");
	}

	
	public People[] getPeoples() {
		People peoples[] = new People[3];
		peoples[0] = new People("zhangkunlie", "boy");
		peoples[1] = new People("xiaoniu", "girl");
		peoples[2] = new People(null, "girl"); 
		return peoples;
	}

	 
	public List<People> getPeopleList() {
		People peoples[] = new People[3];
		peoples[0] = new People("zhangkunlie", "boy");
		peoples[1] = new People("xiaoniu", "girl");
		peoples[2] = new People(null, "girl");
		List<People> list = new ArrayList<People>();
		for (int j = 0; j < peoples.length; j++) {
			list.add(peoples[j++]);
		}
				
		return list;
	}


	
	public void sayHi(){
		System.out.println("sayHi");
	}
	
	

}

3.2 MethodInvocation类
package com.googlecode.soap.client;

public class MethodInvocation {
	
	private String methodName;
	

	private Object[] arugments;
	
	private Class  returnType;


	public MethodInvocation(String methodName,Object[] arugments,Class returnType){
		this.methodName = methodName;
		this.arugments  = arugments;
		this.returnType =returnType;
	}
	

	
	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public Object[] getArugments() {
		return arugments;
	}

	public void setArugments(Object[] arugments) {
		this.arugments = arugments;
	}

	public Class getReturnType() {
		return returnType;
	}

	public void setReturnType(Class returnType) {
		this.returnType = returnType;
	}
    
	
}

3.3 SoapEnvelope类
package com.googlecode.soap.client;

import com.googlecode.soap.util.XmlUnitl;

class SoapEnvelope {
   
	public static final String xmlns_soapenv = "http://schemas.xmlsoap.org/soap/envelope/";
	
	public static final String default_namespace_uri = "http://ws.apache.org/axis2";
	
	public String namespaceUri; 
	
	
	public SoapRequest requestContext;
	
	
	public SoapRequest getRequestContext() {
		return requestContext;
	}


	public void setRequestContext(SoapRequest requestContext) {
		this.requestContext = requestContext;
	}


	public SoapEnvelope(String namespaceUri){
		this.namespaceUri = namespaceUri;
	}
	
	
	public SoapEnvelope(){
		this.namespaceUri = this.default_namespace_uri;
	}
	
	
  
	public String getNamespaceUri() {
		if( namespaceUri == null ) {
			this.namespaceUri = default_namespace_uri;
		}
		return namespaceUri;
	}

    public void setNamespaceUri(String mh) {
		this.namespaceUri = mh;
	}
    
    String getBegin(){
		return "<soapenv:Envelope xmlns:soapenv=\""+xmlns_soapenv+"\" xmlns:mh=\"" + this.getNamespaceUri()+ "\"><soapenv:Body>";
	}
	
    String getEnd(){
		return "</soapenv:Body></soapenv:Envelope>\r\n";
	}

	String getBody(){
		MethodInvocation invocation = this.requestContext.getInvocation(); 
		StringBuffer buffer = new StringBuffer("<mh:"+invocation.getMethodName()+">");
		for (int i = 0; invocation.getArugments() != null
				&& i < invocation.getArugments().length; i++) {  
			buffer.append("<arg"+i+">"+XmlUnitl.toXml(invocation.getArugments()[i])+"</arg"+i+">");         
		} 
		buffer.append("</mh:"+invocation.getMethodName()+">");
		return buffer.toString();
	}
	
    public String getEnvelopeContent(){ 
    	return this.getBegin() + this.getBody()+ this.getEnd();
    }
	
	
} 

3.4 SoapRequest类
package com.googlecode.soap.client;

public class SoapRequest {

    SoapServiceClient context;
	
	private MethodInvocation invocation;

	private String code;
	
	public final static String defualt_code ="utf-8";
	
	public SoapServiceClient getContext() {
		return context;
	}

	public SoapRequest(MethodInvocation invocation) {
		this.invocation = invocation;
	}

	public MethodInvocation getInvocation() {
		 return this.invocation;
    }

	public String getCode() {
		return code==null ? defualt_code:code;
	}

	public void setCode(String code) {
		this.code = code;
	}
    
	public String toString(){
		
		SoapEnvelope envelope = (context.getNamespace() == null) ? new SoapEnvelope(): new SoapEnvelope(context.getNamespace());
    	envelope.setRequestContext(this);
		String content = envelope.getEnvelopeContent();
		return "POST " + context.url.getPath() + " HTTP/1.1\r\n" 
		        + "Host: "+ context.url.getHost() + ":" + context.url.getPort() + "\r\n"
				+ "Content-Type: text/xml; charset="+this.getCode()+"\r\n"
				+ "Connection: close\r\n"
				+ "Content-Length: "+ (content.length() + (2 * 2)) + "\r\n"
				+ "SOAPAction: \042\042\r\n" + "\r\n" + content;
	}
 
}

3.5 SoapResponse类
package com.googlecode.soap.client;

public class SoapResponse {
    
	public enum Status {

		OK(1, "OK"), ServerError(2, "ServerError"), TIMEOUT(3, "TIMEOUT");

		public String detail;

		int status;

		Status(int status, String detail) {
			this.status = status;
			this.detail = detail;
		}
	};
	
	private Status status;
	
	private String text;
	
	private String serverVersion;
	
	private Object object;
	
	Class  returnType;

	SoapResponse(String text,Class returnType){ 
    	 this(text, Status.OK, returnType);
	}
	
	SoapResponse(String text,Status status,Class returnType){
		   this.text = text;	
		   this.status = status;
		   this.returnType =returnType;
		   this.object = this.text;
		   this.parse();
	}
	
    public Object getObject(){
    	return object;
    }
    
    public Status getStatus(){
          return this.status;	
    }
    
    
	private void parse() {
		if (this.status != Status.OK) {
			return;
		}
		String texts[] = this.text.split("\r\n");
		if (texts.length < 7) {
			return;
		}
		String text0 = texts[0];
		if( text0.contains("OK") ) {
			this.status = Status.OK;
			String soapText = texts[texts.length - 1];
			if (soapText == null || soapText.length() == 0) {
				return;
			}
			if( returnType == String.class ) {
				int begin =soapText.indexOf("<return>")+"<return>".length();
				int end   = soapText.indexOf("</return>"); 
				if( end <=0){ return; }
				String returnstring = soapText.substring(begin,end);
				this.object = returnstring;
			}
			
		} else if ( text0.contains("Accepted") ){
			  ; 			
		} else {
			String soapText = texts[texts.length - 1];
			if ( soapText == null || soapText.length() == 0) {
				return;
			} 
			int begin =soapText.indexOf("<faultstring>")+"<faultstring>".length();
			int end   = soapText.indexOf("</faultstring>");
			if( end <=0){ return; }
			String faultstring = soapText.substring(begin,end);
			this.status = Status.ServerError;
			this.object = this.status.detail = faultstring ;
		}
		this.serverVersion = texts[1].split(":")[1];
	 }
       
    
    public String getServerVersion() {
		return serverVersion;
	}

	public void setServerVersion(String serverVersion) {
		this.serverVersion = serverVersion;
	}

    
    
	
	
}

3.6 SoapServiceClient类
package com.googlecode.soap.client;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.URL;

import com.googlecode.soap.client.SoapResponse.Status;
import com.googlecode.soap.util.ExecuteThreadPool;

public class SoapServiceClient {

	private String address;

	private String namespace;

	 
	public static long MAX_TIME_OUT = 10000; // 10秒 

	private SoapResponse response;

	static ExecuteThreadPool executor = new ExecuteThreadPool(5);
	 
	public final Object lock = new Object();

	 URL url = null;
	 
	 Socket socket = null;
		
	private void init(SoapRequest request){
		this.response = null; 
		request.context = this;
	}
	
	public SoapServiceClient(String address) throws Exception, IOException {
		this.address = address;
		if (!this.address.endsWith("?wsdl")) {
			this.address = this.address + "?wsdl";
		}
		this.url = new URL(this.address);
		socket = new Socket(url.getHost(), url.getPort());
	}

	public String getNamespace() {
		return namespace;
	}

	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}

	public void sendRequest(final SoapRequest request) {
		
		this.init(request);
        // 多线程环境下发送
		executor.execute(new Runnable() {

			public void run()  {
				
                OutputStream os = null;
        		InputStream input = null;
				PrintStream ps = null;
				ByteArrayOutputStream bos = null;
        	    try {
					String send = request.toString();
					if( socket.isClosed()) {
					  socket = new Socket(url.getHost(), url.getPort());
					}
                    socket.setSoTimeout((int)MAX_TIME_OUT);
					os = socket.getOutputStream();
					ps = new PrintStream(os, true, request.getCode());
					ps.println(send);
					input = socket.getInputStream();
					int available = input.available();
					if (available <= 0) {
						     long current= System.currentTimeMillis(); 
						     for(;;){ 
						    	 input = socket.getInputStream();
								 available = input.available();
								 if(available  > 0 ) {
									 break; 
								 }
						    	 if(System.currentTimeMillis()-current >= MAX_TIME_OUT ) { 
						    		 synchronized(lock) {
						    		      response = new SoapResponse("TimeOut Exception", Status.TIMEOUT,null);
						    		   
						    		      return ;
						    		 }
						    	}
						     }
					 }
					bos = new ByteArrayOutputStream();
					byte[] buffer = new byte[256];
					int totalRead = 0;
					while (true) {
						int nRead = input.read(buffer);
						totalRead += nRead;
					    bos.write(buffer, 0, nRead);
						if (totalRead >= available) {
							break;
						}
					}
					String responseString = bos.toString(request.getCode());
					System.out.println("response=\r\n" + responseString);
					synchronized(lock) {
					   response = new SoapResponse(responseString,request.getInvocation().getReturnType());
					  
					}
				} catch (Exception e) {
					e.printStackTrace();
					synchronized(lock) {
					  response = new SoapResponse("RequestError", Status.ServerError,null);
					
					}
				}  finally {
					try {
						if (ps != null) {
							ps.close();
						}
						if (os != null) {
							os.close();
						}
						if (input != null) {
							input.close();
						}
						if (bos != null) {
							bos.close();
						}
						if (socket != null) {
							socket.close();
						}

					} catch (Exception e) {
						e.printStackTrace();
					} finally {
                        ps = null; os =null; input = null; bos =null; 
					}
				}
			}
		});

	}

	public SoapResponse getResponse() {
 	if (this.response == null) {
			long current = System.currentTimeMillis();
			for (;;) {
				if (System.currentTimeMillis() - current >= MAX_TIME_OUT) {
					synchronized (lock) {
						return this.response;
					}
				}
				if (this.response != null) {
					synchronized (lock) {
						return this.response;
					}
				}
			}
		}
		synchronized (lock) {
			return this.response;
		}
		

	}

	

}

3.7 ExecuteThreadPool工具类
package com.googlecode.soap.util;

import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ExecuteThreadPool implements Executor {

	private final int maxPoolSize ;
    
	private long idelTime = 0 ;
	
	private int realSize = 0 ;
    
	//线程池是否关�?
	private boolean poolClosed = false;
	
	private final HashSet<Worker> workers = new HashSet<Worker>();

	private final ReentrantLock mainLock = new ReentrantLock();

   //工作队列
	private final BlockingQueue<Runnable> workQueue  = new LinkedBlockingQueue<Runnable>();;

	public ExecuteThreadPool(int maxPoolSize) {
		this.maxPoolSize = maxPoolSize;
	}
	
	/**
	 * @param maxPoolSize int 线程池中可用的线程的大小
	 * @param idelTime 单位毫秒,当线程池所有的线程忙的时�?�?
	 *                 �?��等待的时�?超出这个等待时间,抛出异�?
	 * 	 
	 * */
	public ExecuteThreadPool(int poolSize,long idelTime) {
		this.maxPoolSize = poolSize;
		this.idelTime =  idelTime;
	}
	
	@Override 
	public void execute(Runnable command) {
		if (command == null) {
			throw new IllegalArgumentException("command argument can't be null");
		}
		if(this.poolClosed) {
			throw new RuntimeException("Current pool was closed.");
		}
		//线程池还没有满,新建线程直接运行
		if (realSize < maxPoolSize) { 
			this.newThread(command).start();
		} else { 
	    //主线程负责workQueue工作队列。准备战斗
		    this.workQueue.offer(command);   
	    }
    }
	
	//强制关闭线程
	public void shutdown(){
		 this.mainLock.lock();
		 Iterator<Worker> it  = workers.iterator();
	     while(it.hasNext()) {
	        	 Worker w = it.next();
	             w.status = w.exited;
	        	 w.shutdown(); 
	      }
	     workers.clear();
	     workQueue.clear();
	     this.poolClosed = true; 
	     this.mainLock.unlock();
	}

	private Thread newThread(Runnable command){
		//用Worker来封�?command,因为Worker也继承Runnable.
		Worker worker = new Worker(command);
		Thread t = new Thread(worker); 
		worker.thread = t;
		this.realSize = this.realSize + 1;
		t.setName("pool-" + this.realSize);
		workers.add(worker);
		return t;
	}

	// 线程工作执行
	private class Worker implements Runnable {
		
		//已准备
		public final int  ready = 1;
		
		//在工作
		public final int  working = 2;
		
		//在等待
		public final int  waiting = 3;
		
	    //已退出
		public final int  exited = 4;
		
		//当前线程工作执行者的状态,默认是 ready
		public int status = ready;

		private final ReentrantLock runLock = new ReentrantLock();

		private Runnable task;

        Thread thread = null;
	
    	Worker( Runnable task) {
			this.task = task;
			this.status = this.ready; 
		} 
        
		@Override
		public void run() {
			Runnable runTask = this.task;
			for (;;) {
				if (runTask != null) {
				try {
					   this.runTask(runTask);
					 } catch (RuntimeException e) {
						 ;
					 }
					 runTask = null;
				}
				try {
					 runTask = getTask();
				    } catch (InterruptedException ie) {
					     this.status = this.exited;
					     break;
				   }
			}
		}

		void shutdown(){
			 if ( thread != Thread.currentThread()) {
				    thread.interrupt();
			 }
		}
		
		private void runTask(Runnable task) {
			try {
				 final ReentrantLock runLock = this.runLock;
				 runLock.lock();
				 this.status = this.working; 
				 task.run();
			   } catch (Exception e) {
				 throw new RuntimeException(e);
			   } finally {
				 runLock.unlock();
			   }
    	}

    	private Runnable getTask() throws InterruptedException {
			for (;;) {
				Runnable task = null;
				//工作队列非空,直接调用poll方法获取.
				if (!workQueue.isEmpty()) {
					task = workQueue.poll();
				} else {
				    try {
				        //如果设置了idelTime 的�?,调用poll方法获取元素,超出idelTime时间,抛�?InterruptedException
					    if( idelTime != 0L ) {
							task = workQueue.poll(idelTime, TimeUnit.MILLISECONDS);
						} else { 
						//Worker线程负责获取方法,从工作队列头获取对象并删除队列中要获取的对象,如果队列为空,一直等�?
							task = workQueue.take();
						} 
				    } catch (InterruptedException e) {
					    	throw e;
					} catch(Exception e) {
						    ;
					}
			   }
			   if (task != null) {
					return task;
			   }
			   this.status = this.waiting;
		  }
	   }
    	
	}
}

3.8 XmlUnitl工具类
package com.googlecode.soap.util;

import java.lang.reflect.Field;

public final class XmlUnitl {

	public static final String SPACE_CHAR = "";

	public static final String LEFT_SEQ = "<";

	public static final String RIGHT_SEQ = ">";

	public static String toXml(Object object) {
		if (object == null) {
			return SPACE_CHAR;
		}
		if (object.getClass().getName().equals(String.class.getName())) {
			return object.toString();
		} else if (object.getClass().getName().equals(Integer.class.getName())) {
			return object.toString();
		} else if (object.getClass().getName().equals(Float.class.getName())) {
			return object.toString();
		} else if (object.getClass().getName().equals(Double.class.getName())) {
			return object.toString();
		} else if (object.getClass().getName().equals(Long.class.getName())) {
			return object.toString();
		} else if (object.getClass().getName().equals(Long.class.getName())) {
			return object.toString();
		}
		Field fields[] = object.getClass().getDeclaredFields();
		if (fields == null || fields.length == 0) {
			return SPACE_CHAR;
		}
		StringBuffer buffer = new StringBuffer();
		for (Field field : fields) {
			String name = field.getName();
			field.setAccessible(true);
			try {
				Object value = field.get(object);
				if (value != null) {
					buffer.append(LEFT_SEQ + name + RIGHT_SEQ + value
							+ LEFT_SEQ + "/" + name + RIGHT_SEQ);
				}

			} catch (Exception e) {
				;
			}
		}
		return buffer.toString();
	}

}


3.9 测试类SoapTest
package com.googlecode.soap.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.googlecode.soap.client.MethodInvocation;
import com.googlecode.soap.client.SoapRequest; 
import com.googlecode.soap.client.SoapResponse;
import com.googlecode.soap.client.SoapServiceClient;

public class SoapTest {
     
	 
	public static void main(String[] args) throws Exception { 
		SoapServiceClient client = new SoapServiceClient("http://localhost:8099/axis2/services/SimpleService?wsdl");
		MethodInvocation method = new MethodInvocation("getPrice",new Object[]{44},null); 
		SoapRequest request = new SoapRequest(method); 
		request.setCode("utf-8");  
		//client.setNamespace("http://webservice.chapter1.book/client");
		BufferedReader systemIn=new BufferedReader(new InputStreamReader(System.in));
		boolean flag=true;
		while(flag){
			String command=systemIn.readLine();
			if( command==null || "quit".equalsIgnoreCase(command.trim())){
				flag=false;
				System.out.println("Client quit!");
			    continue; 
			} else if( "send".equalsIgnoreCase(command.trim())) {
				System.out.println("send command..");
				client.sendRequest(request);	
				SoapResponse response = client.getResponse();
				System.out.println(response.getObject());
		 	}
			 
		}
	
	}
    
}

4.测试
4.1 先把 SimpleService.class和People.class发布到$AXIS_HOME$\WEB-INF\pojo\下,启动Axis2
4.2 运行 SoapTest,在控制台下输入send,即可测试

你可能感兴趣的:(多线程,thread,socket,OS,SOAP)