您的位置:首页 > 编程语言 > Java开发

java应用中如何捕抓SAS存储过程输出的流信息

2007-06-28 15:17 796 查看
java应用中如何捕抓SAS存储过程输出的流信息
 
这个指南演示如何在存储过程中使用ods格式化输出流并被用某种语言编写的应用所接收,如java语言
 

例子报告

首先我们引用一个简单例子,其用ods格式化输出2个html报表,由于其使用的是sashelp中的数据,故下面例子你可以直接运行在你的环境中,例子如下
 
l       注:宏 ®ION 用于指示取数据的一个子集
%let REGION=Pacific;
ods html body="shoe_sales.html";
title Shoe Sales by Subsidiary;
title2 Region: ®ION;
proc report data=sashelp.shoes(where=(region="®ION")) nowd;
    column subsidiary sales;
    define subsidiary / group;
    define sales / analysis sum;
run;
title Shoe Sales Detail;
title2 Region: ®ION;
proc report data=sashelp.shoes(where=(region="®ION")) nowd;
    column subsidiary product stores sales;
    define subsidiary / order;
    define product / order;
    define sales / analysis sum;
run;
ods html close;
 

转换上面例子报告到存储过程

只需要下面3个简单步骤就可以
1、  每一个存储过程应该有一个标志用来指示其是存储过程,如下行,该行应该在%let 和 第一个ods输出之间
*ProcessBody;
2、  转换宏符号作为存储过程的参数,如下
%global REGION;
3、  我们应该初始化ods的开始和结束句子,在存储过程中,我们可以使用下面宏帮助我们自动初始化
%stpbegin
%stpend
 
改后的代码如下:
%global REGION;
*ProcessBody;
%stpbegin;
title Shoe Sales by Subsidiary;
title2 Region: ®ION;
proc report data=sashelp.shoes(where=(region="®ION")) nowd;
    column subsidiary sales;
    define subsidiary / group;
    define sales / analysis sum;
run;
title Shoe Sales Detail;
title2 Region: ®ION;
proc report data=sashelp.shoes(where=(region="®ION")) nowd;
    column subsidiary product stores sales;
    define subsidiary / order;
    define product / order;
    define sales / analysis sum;
run;
%stpend;

调用存储过程

 
我们把该后的程序部署到存储过程服务器上去

 
一旦部署完成,我们就可以使用外部工具来访问该存储过程,如用excel (需要装Add-In for Microsoft Office)

 
当然,也可以通过浏览器来访问该存储过程
 

 

从java调用存储过程

 
你可以使用SAS IT APIS 来调用存储过程,你甚至可以使用SAS8.2来完成这一步骤
在开始写java代码前,我们应该明白下面概念
Integrated Object Model (IOM) 是我们远端调用SAS的API.
当我们连接到SAS时,我们将从SAS会话中获得workspace对象.
然后我们从Workspace.中取得其他服务对象
 
简单的java代码
要调用一个存储过程,你应该包含一个  IStoredProcessService 对象的引用并告诉它:
repository 位置,它是一个定位存储过程的目录路径,格式如 "file:/some/directory".  如果我们异步调用存储过程,那java将不会等待存储过程执行完
存储过车文件的名字
存储过程参数,如"name1=value1 name2=value2 …"
 
下面通过java定义了一个方法,用于设置且执行存储过程,代码如下:
 

executeImpl方法

 
private SocketListener executeImpl(
        String stpName, 
        Properties params, 
        IWorkspace workspace) 
throws IOException, GenericError
{
    // create a socket for SAS to send result stream
    // SocketListener is an AppDev Studio utility
    SocketListener socket = new SocketListener();
    int port = socket.setup();
    socket.start();
 
    // get IOM objects from Workspace
    ILanguageService languageService = workspace.LanguageService();
    IStoredProcessService stpService = 
    languageService.StoredProcessService();
 
    // get stored process call info
    String repository =     
        LocalEnvironment.getProperty("stp.repository");
    String stpParams = buildParamString(params);
    Log.debug("repository = "+repository);
    Log.debug("stpName = "+stpName);
    Log.debug("stpParams = "+stpParams);
 
    // define fileref for socket and issue startup statements
    initWorkspace(languageService, port);
    // call stored process
    stpService.Repository(repository);
    languageService.Async(false);
    Log.debug("calling stp");
    stpService.Execute(stpName, stpParams);
    
    // send SAS log to web app log
    Log.debug("checking log");
    dumpLog(languageService);
    return socket;
}    
 
在上面的代码中,使用了下面3个iom的接口
IWorkspace, ILanguageService, IStoredProcessService
 
SocketListener类用于监听SAS输出信息,通过端口号和SAS建立联络
 
该类还使用了2个实用类
LocalEnvironment 类用于环境信息初始和输出
Log类用于简单的记录输出
 
其他有用的方法,我们将在下面列出

绑定参数字符串

一个存储过程可以接收0个或者多个参数,如下
private String buildParamString(Properties params)
{
    StringBuffer paramBuff = new StringBuffer();
    Iterator iter = params.keySet().iterator();
    while (iter.hasNext())
    {
        String key = (String) iter.next();
        paramBuff.append(key);
        paramBuff.append('=');
        paramBuff.append('/"');
        paramBuff.append(params.getProperty(key));
        paramBuff.append('/"');
        paramBuff.append(' ');
    }
    String stpParams = paramBuff.toString();
    return stpParams;
}
 

初始化SAS会话

如同通过api直接调用存储过程,SAS本身不知道是如何输出到指定的socket端口中取,而在默认情况下会输出到_webout中取,故我们可以在初始化时分配好_webout并指向指定的socket端口
 
private void initWorkspace(ILanguageService languageService, int port) 
throws IOException, GenericError
{
    // create fileref to my server socket
    // CHEAT ALERT: using localhost as host name for socket!
    StringBuffer block = new StringBuffer();
    block.append("filename _WEBOUT SOCKET ");
    block.append('/'');
    block.append("localhost");
    block.append(':');
    block.append(port);
    block.append('/'');
    block.append(';');
    block.append("/n");
 
    String startupStatement = 
        LocalEnvironment.getProperty("stp.startupStatement");
    if (startupStatement != null)
        block.append(startupStatement);
    
    Log.debug("submitting "+block.toString());
    languageService.Submit(block.toString());
}
 

获得SAS输出日志

直接调用languageService的flushlog方法可以及时地把日志输出
 
private void dumpLog(ILanguageService languageService)
throws GenericError
{
    int count = 0;
    String log = null;
    Log.sas("/nLOG START/n/n");
    do 
    {
        log = languageService.FlushLog(BUFFSIZE);
        Log.sas(log);
        count++;
    }
    while (log.length() == BUFFSIZE);
Log.sas("/nLOG END (" + count + ")/n");
}
 
 
 
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息