Web Services应用实例 -- Java Web App远程调用SAS程序的解决方案

最近要做个小项目WebView,让客户能通过浏览器看他的文件(由公司SAS程序产生的一些报表)。 这算是我做的第二个AJAX应用。其实做个类似于Windows资源管理器的界面是很简单的,在ExtJS的examples基础上改改就好了--我一直是这么做的。当然还要实现的就是访问控制,对这个小项目而言都不值一提。幕后英雄是SAS程序,它将被我的Java程序调用。至于SAS到底是什么东西,我不太了解,也不需要太了解,我只从公司SAS程序员那里知道,它是用来分析数据的。我只需要知道那个SAS命令的调法就足够了。

问题是,SAS程序部署在SAS Server上,而我要开发的Java Web App将部署在另一台Server上。如果在同一台机器上,用Runtime.getRuntime().exec就可以直接调用SAS程序了。现在这种情况,宜用Web Services来做。

1. 在SAS Server上安装JDK和Tomcat.
2. SASWebServices开发。同样,改改Google来的一个demo就好了(看来Google是软件开发人员的必备工具)

代码不多,多的是配置和依赖的JARs

Java代码
package com.grs.webview.webservices.sas;

import java.io.IOException;

import javax.jws.WebService;

@WebService
public interface ISASService {
 public void process() throws IOException;
}

package com.grs.webview.webservices.sas;

import java.io.IOException;

import javax.jws.WebService;

@WebService
public interface ISASService {
 public void process() throws IOException;
}


Java代码
package com.grs.webview.webservices.sas;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import javax.jws.WebService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@WebService(
 serviceName = "SASService",
 endpointInterface = "com.grs.webview.webservices.sas.ISASService"
)
public class SASServiceImpl implements ISASService {

 private static Log log = LogFactory.getLog(SASServiceImpl.class);

 /**
 * invoke SAS command
  */
 public void process() throws IOException {
  log.info("invoking SAS program...");

  StringBuffer cmd = new StringBuffer("cmd");

// String[] cmds = new String[]{"mkdir sam_tmp_0", "cd sam_tmp_0", "mkdir sam_tmp_1", "cd sam_tmp_1", "mkdir sam_tmp_2"};
// String[] cmds = new String[]{"cd D:\\wwwroot", "d:", "mkdir sam_tmp_1", "cd sam_tmp_1", "mkdir sam_tmp_2"};

  String[] cmds = new String[]{
   new StringBuilder()
    .append("\"C:\\Program Files\\SAS\\SAS 9.1\\SAS.EXE\" ")
    .append("D:\\wwwroot\\TEST.sas ")
    .append("-CONFIG \"C:\\Program Files\\SAS\\SAS 9.1\\nls\\en\\SASV9.CFG\" ")
    .append("-nosplash ")
    .append("-nologo ")
    .append("-noautoexec ")
    .append("–icon")
    .toString()};

  Process p = Runtime.getRuntime().exec(cmd.toString());

  new OutputStuffThread(p, cmds).start();

  BufferedInputStream buffer = new BufferedInputStream(p.getErrorStream());
  BufferedReader commandResult = new BufferedReader(new InputStreamReader(buffer));
  try {
   for (int count = 0; count < cmds.length + 1;count++) {
    String s = commandResult.readLine();
    log.info("Command output #" + (count + 1) + " : " + s);
   }
   commandResult.close();
  } catch (java.io.IOException e) {
   e.printStackTrace();
  }

  log.info("SAS program invoked.");

 }

}


/**
* the class is needed for interactive commands
*
* @author Sam Chen
* @version 1.0 08/09/2007
*/
class OutputStuffThread extends Thread {
 private Process m_process;
 private String[] m_rest;

 public OutputStuffThread(Process process, String[] rest) {
  m_process = process;
  m_rest = rest;
 }

 public void run() {
  try {
   BufferedOutputStream bufferout = new BufferedOutputStream(m_process.getOutputStream());
   PrintWriter commandInput = new PrintWriter((new OutputStreamWriter(bufferout)), true);
    if (null == m_rest || m_rest.length == 0) {
    commandInput.println("exit");
   } else {
     for (int i = 0; i < m_rest.length; i++) {
    commandInput.println(m_rest[i]);
    }
    if (!"exit".equals(m_rest[m_rest.length - 1])) {
     commandInput.println("exit");
    }
   }
   commandInput.close();
  } catch( Exception e ) {
   System.err.println(e);
  }
 }

}

package com.grs.webview.webservices.sas;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import javax.jws.WebService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@WebService(
 serviceName = "SASService",
 endpointInterface = "com.grs.webview.webservices.sas.ISASService"
)
public class SASServiceImpl implements ISASService {

 private static Log log = LogFactory.getLog(SASServiceImpl.class);

 /**
 * invoke SAS command
  */
 public void process() throws IOException {
  log.info("invoking SAS program...");

  StringBuffer cmd = new StringBuffer("cmd");

// String[] cmds = new String[]{"mkdir sam_tmp_0", "cd sam_tmp_0", "mkdir sam_tmp_1", "cd sam_tmp_1", "mkdir sam_tmp_2"};
// String[] cmds = new String[]{"cd D:\\wwwroot", "d:", "mkdir sam_tmp_1", "cd sam_tmp_1", "mkdir sam_tmp_2"};

  String[] cmds = new String[]{
   new StringBuilder()
    .append("\"C:\\Program Files\\SAS\\SAS 9.1\\SAS.EXE\" ")
    .append("D:\\wwwroot\\TEST.sas ")
    .append("-CONFIG \"C:\\Program Files\\SAS\\SAS 9.1\\nls\\en\\SASV9.CFG\" ")
    .append("-nosplash ")
    .append("-nologo ")
    .append("-noautoexec ")
    .append("–icon")
    .toString()};

    Process p = Runtime.getRuntime().exec(cmd.toString());

    new OutputStuffThread(p, cmds).start();

    BufferedInputStream buffer = new BufferedInputStream(p.getErrorStream());
    BufferedReader commandResult = new BufferedReader(new InputStreamReader(buffer));
    try {
     for (int count = 0; count < cmds.length + 1;count++) {
      String s = commandResult.readLine();
      log.info("Command output #" + (count + 1) + " : " + s);
     }
     commandResult.close();
    } catch (java.io.IOException e) {
     e.printStackTrace();
    }

    log.info("SAS program invoked.");

   }

}


/**
* the class is needed for interactive commands
*
* @author Sam Chen
* @version 1.0 08/09/2007
*/
class OutputStuffThread extends Thread {
 private Process m_process;
 private String[] m_rest;

 public OutputStuffThread(Process process, String[] rest) {
  m_process = process;
  m_rest = rest;
 }

 public void run() {
  try {
   BufferedOutputStream bufferout = new BufferedOutputStream(m_process.getOutputStream());
   PrintWriter commandInput = new PrintWriter((new OutputStreamWriter(bufferout)), true);
   if (null == m_rest || m_rest.length == 0) {
    commandInput.println("exit");
   } else {
    for (int i = 0; i < m_rest.length; i++) {
     commandInput.println(m_rest[i]);
    }
    if (!"exit".equals(m_rest[m_rest.length - 1])) {
     commandInput.println("exit");
    }
   }
   commandInput.close();
  } catch( Exception e ) {
   System.err.println(e);
  }
 }

}


Java代码
package test;

import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.annotations.AnnotationServiceFactory;

import com.grs.webview.webservices.sas.ISASService;
import com.grs.webview.webservices.sas.SASServiceImpl;

import java.io.IOException;
import java.net.MalformedURLException;

public class TestRunner {

 public static void main(String[] args) throws IOException {

  Service serviceModel = new AnnotationServiceFactory().create( SASServiceImpl.class);

// String url = "http://localhost:8888/SASWebServices/services/SASService";
  String url = "http://assasii.grs-cro.com:8080/SASWebServices/services/SASService";

  try {
   ISASService service = (ISASService)new XFireProxyFactory().create(serviceModel, url);
    service.process();
  } catch (MalformedURLException e) {
   e.printStackTrace();
  }

 }
}