rainy_2004 发表于 2013-1-28 18:21:29

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;peoples = new People("zhangkunlie", "boy");peoples = new People("xiaoniu", "girl");peoples = new People(null, "girl"); return peoples;} public List<People> getPeopleList() {People peoples[] = new People;peoples = new People("zhangkunlie", "boy");peoples = new People("xiaoniu", "girl");peoples = new People(null, "girl");List<People> list = new ArrayList<People>();for (int j = 0; j < peoples.length; j++) {list.add(peoples);}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 ClassreturnType;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())+"</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;ClassreturnType;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;if( text0.contains("OK") ) {this.status = Status.OK;String soapText = texts;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;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.split(":"); }               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;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 intready = 1;//在工作public final intworking = 2;//在等待public final intwaiting = 3;    //已退出public final intexited = 4;//当前线程工作执行者的状态,默认是 readypublic 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; }         @Overridepublic 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,即可测试
页: [1]
查看完整版本: SOAP客户端