1.主要是为了加强对SOAP远程方法调用的学习,特意自己写了一个SOAP Client端.
2.要求环境:JDK1.6 以上,Axis2 以上
3.主要代码
- 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")) {
- thisthis.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;
- }
- }
- }
- ackage 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();
- ww.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;
- thisthis.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;
- thisthis.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) {
- thisthis.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();
- thisthis.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;
- }
- thisthis.status = this.waiting;
- }
- }
- }
- }
- ackage 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();
- }
- }
- 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://www.nicaipu.com: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,即可测试