Contents Home Previous Next

 

3.1 Oracle Web Agent如何工作

Oracle Web Agent使你能用开发工具箱创建PL/SQL存储过程来存取Oracle7的数据,
动态生成来自那些数据的HTML文档,并将文档返回给客户端。
 
下面描述一下Oracle Web Agent是如何一步一步工作的:

Web Agent服务 Service

因为人们希望单个Web Listener能够访问多个数据库或一个数据库里的多个模式,
Oracle Web Agent支持服务的概念。我们用下面的例子描述一下服务的概念:

  公司A想让他们存储在Oracle7数据库中的数据可以被公众通过Oracle Web Listener
访问。然而公司内不同部门对数据库以用户名为分割的不同部分(模式)有访问权限。
所以,人力资源部和财务部使用不同的用户名/口令组合来登录数据库。如果他们都想
用使用Oracle Web Agent的CGI应用访问他们的数据,Web Agent需要使用正确的用户
名/口令来登录数据库。采用这种方案,含有配置信息的owa.cfg文件中包含两个服务,
HR 服务和AP服务。每个服务有相关的用户名/口令,ORACLE_HOME参数,和ORACLE_SID
参数。当一个来自浏览器的请求到来时,Web Listener从URL中抽取出服务名并读取
owa.cfg文件找出将使用的参数。

  为连接到Oracle7服务器,Web Agent需要在Web Agent服务中指明以下信息: 

Administration Utility允许管理员显示,创建,修改或删除Web Agent服务。用创建
Web Agent的表格,你不需要直接修改配置文件owa.cfg。参见 "Creating or Modifying Web Agent Services,"[*]

   下面是一个owa.cfg文件中Web Agent服务项的例子,每个参数有相应的解释。
 

 Developer's T#

(
owa_service = es
(
owa_user = www_es
)
(
owa_password = tiger 
)
(
oracle_home = /opt/oracle7
)
(
oracle_sid = esprod
)
(
owa_err_page = /es_err.html
)
(
owa_valid_ports = 8000 8888
)
(
owa_log_dir = /opt/oracle7/ows/log
)
(
owa_nls_lang = AMERICAN_AMERICA.US7ASCII
)
)
owa_service 
Web Agent 服务的名字

 
owa_user 
Web Agent连接数据库用的数据库用户名。
 
owa_password 
Web Agent连接数据库用的数据库口令。
 
oracle_home 
Oracle7代码树在文件系统中的位置。它应该是Web Agent服务连接到的数据库的
ORACLE_HOME,除非Web Agent设置为通过SQL*NET连接到一个远程数据库。这种情况
下,指定Web Agent所在的ORACLE_HOME。Web Agent总是安装在ORACLE_HOME目录或
其子目录下。
 
oracle_sid 
将连接到的数据库的系统ID名。连接到远程数据库时,不要使用。

 
owa_err_page 
Web Agent调用的PL/SQL过程发生错误时,Web Agent返回的HTML文档的路径。这是个
实际路径,而非Web Listener配置中的那种虚拟路径。

owa_valid_ports
  Web Agent将服务的有效的Web Listener网络端口。

 
owa_log_dir 
Oracle Web Agent写出错文件的目录。出错文件的名字为service_name.err。

owa_nls_lang
  Web Agent连接的Oracle7数据库的NLS_LANG。若不指定,Web Agent管理程序当服
务执行时寻找数据库的NLS_LANG。
 

Web Agent如何使用CGI环境变量

Web Agent使用的环境变量见表3-1:
 
变量  包含
REQUEST_METHOD  GET 或 POST 
PATH_INFO  将调用的PL/SQL过程的名字。
SCRIPT_NAME  包含登录Oracle7时用的Web Agent和服务 。
QUERY_STRING  PL/SQL过程的参数(仅对GET方法。POST方法的参数通过标准输入      
传递。)
3 - 1. Oracle Web Agent使用的CGI 变量

  下面是一个典型的URL如何被与CGI 1.1说明书兼容的Web Listener解析的例子。

http://www.nhl.com:8080/ows-bin/nhl/owa/hockey.pass?person=Gretzky
注意: 使用环境变量QUERY_STRING 即表明这是个GET请求. 你也可以用POST方法传递
参数。如何使用POST方法传递参数的例子,见下一节, "传递参数给PL/SQL".
 

传递参数给PL/SQL

为了执行和生成相应的HTML文档,一个PL/SQL过程通常需要参数。以下几节讨论一下
一个PL/SQL开发员在参数如何得以传递到指定的PL/SQL例程方面应该理解的几个关键
概念和要领。

 这些关键概念和要领为:

从Web浏览器到Web Agent的参数获取

 依赖使用REQUEST_METHOD 的不同, 参数由Web浏览器到Web Listener的传递有两种方法:

从Web Listener到Web Agent的参数传递方法对于PL/SQL过程这个参数的实际消费者
来说是透明的。这是Oracle Web Agent的一个重要特性:PL/SQL程序员不需要知道使
用何种方法,不需要关心从环境变量QUERY_STRING还是标准输入进行解析。PL/SQL程
序员因而精力集中在他们最精通的方面:开发从Oracle数据库提取数据的逻辑,基于
从Oracle Web Agent传来的预解析的参数。

  建议:可能的情况下,使用POST。GET方法用于链接和非表格URL。对于HTML表格,
可以有个选择。因为GET方法使用操作系统环境变量,QUERY_STRING有长度限制。

使用HTML表格传递参数

 下例模拟前一节,除非它使用HTML表格使用POST REQUEST_METHOD。
 

<FORM METHOD="POST" ACTION="http://www.nhl.com:8080/ows-bin/nhl/owa/hockey.pass">
Please type the name of the person you wish to search for:
<INPUT TYPE="text" NAME="person"><P>
To submit the query, press this button: 
<INPUT TYPE="submit" VALUE="Submit Query">. <P>
</FORM>
上面的表格使得Oracle Web Listener与前一个例子的行为一样,只是不再使用"person=Gretzky"填环境变量QUERY_STRING,Web Listener把"person=Gretzky"写到
标准输出。这里当然假设了用户在表格的字段里输入了"Gretzky"。

注意:HTML输入变量的名字,此处为"person",必须和与它相匹配的PL/SQL参数完全
相同。
  上述参数的接收的PL/SQL过程如下:
 

create or replace
procedure hockey_pass (person in varchar2) is
   n_assists integer;
begin
   select num_assists into n_assists
      from hockey_stats
   where name=person;
   htp.print(person||' has '||to_char(n_assists)||' assists this      season');
end;
参数排序

 总的来说, PL/SQL开发员不需要关心Oracle Web Agent以什么顺序从HTML表格或
通过一个URL接收参数. 它仅在从一个表格字段传递多个值时才有关系。参见本节
后面的"多个HTML表格字段使用相同的名字"。

参数缺省值

 如果PL/SQL开发员不能保证对于特定的PL/SQL过程参数必然有从Web浏览器传来的值
的话,建议给此参数一个缺省值,例如:

create or replace procedure showvals(a in varchar2 DEFAULT NULL,
                   b in varchar2 DEFAULT NULL) 
is 
begin 
   htp.print('a = '||a||htp.br);
   htp.print('b = '||b||htp.br); 
end;
如果Web Agent收到一个调用过程showvals的请求,没有给"a"的值,"b"的值为"Hello
",如果过程定义中没有DEFAULT NULL子句,请求将得到如下错误信息:
OWS-05111: Agent : no procedure matches this call
  OWA SERVICE: test_service 
  PROCEDURE: showvals 
 PARAMETERS: 
  =========== 
  B: 
   Hello
通过为参数设缺省值,上述请求被正常输出:
a = <BR> 

b = Hello<BR>
对于最终用户它看起来象:
a = 
b = Hello
多个HTML表格字段使用同一个名字

有些情形下,人们想。为处理这种想用相同HTML字段即PL/SQL参数传递多个值的情
况,可以用PL/SQL表创建值的数组。

要用相同HTML字段传递多个值的一种情况是HTML表格的"SELECT"标记的使用。如果设
参数SIZE为比1大的值,用户将能从同一个表格字段选择多个值。
  另一种情况是人在单个表格字段选择一组相应的值:

-- QUERY_FORM prints an HTML page with all the columns for the   
-- specified table.  Invoke the procedure from a Web Browser with
-- a URL like:
http://yourhost:port_num/service_name/owa/query_form?the_table=emp

create or replace procedure query_form(the_table in varchar2) is  
   cursor cols is 
   select column_name   
       from user_tab_columns 
   where table_name = upper(the_table); 
begin
   htp.htmlOpen; 
   htp.headOpen; 
   htp.htitle('Query the '||the_table||' table!'); 
   htp.headClose; 
   htp.bodyOpen; 
   -- Use owa_util.get_owa_service path to automatically retrieve 
   htp.formOpen(owa_util.get_owa_service_path||'do_query');
   -- Put in the table as a hidden field to pass on to do_query   
   htp.formHidden('the_table', the_table);
   -- Put in a dummy value, as we cannot DEFAULT NULL a PL/SQL table. 
htp.formHidden('COLS', 'dummy'); 
   for crec in cols loop
      -- Create a checkbox for each column. The form field name   
      -- will be COLS and the value will be the given column name.
      -- Will need to use a PL/SQL table to retrieve a set of 
      -- values like this. Can use the owa_util.ident_arr type    
      -- since the columns are identifiers.
      htp.formCheckbox('COLS',crec.column_name); 
      htp.print(crec.column_name); 
      htp.nl; 
   end loop; 
   -- Pass a NULL field name for the Submit field; that way, a 
   -- name/value pair is  not sent in.  Wouldn't want to do this  
   -- if there were multiple submit buttons.
   htp.formSubmit(NULL, 'Execute Query');    
   htp.formClose; 
   htp.bodyClose; 
   htp.htmlClose; 
end;
调用此过程将带来如下的一个页面:

 
此例中,用户已经选择了查询EMPNO,ENAME,JOB,和SAL列 :

这里是处理此表格提交的过程:

-- DO_QUERY executes the query on the specified columns and 
-- tables.The OWA_UTIL.IDENT_ARR datatype is defined as: 
--  -- type ident_arr is table of varchar2(30) index by binary_integer
--
create or replace procedure do_query(the_table in varchar2,
 cols in owa_util.ident_arr) is

   column_list varchar2(32000); 
   col_counter integer;
   ignore      boolean;
begin 
-- For PL/SQL tables, have to just loop through until you hit 
-- no_data_found. Start the counter at 2 since we put in 
-- a dummy hidden field. 
   col_counter := 2; 
   loop 
      -- build a comma-delimited list of columns 
      column_list := column_list||cols(col_counter)||','; 
      col_counter := col_counter + 1; 
   end loop; 
exception 
   when no_data_found 
   then 
       -- strip out the last trailing comma 
       column_list := substr(column_list,1,length(column_list)-1); 
        -- print the table - assumes HTML table support 
       ignore := owa_util.tablePrint(the_table, 'BORDER',               
                                                        OWA_UTIL.HTML_TABLE,
 column_list); 
end;
选择按钮"Execute Query"后,用户将见到:


使用隐藏的站位变量作为第一个值是个好想法,如果你不能保证至少一个值被提交到
PL/SQL表的话。其原因是不能为PL/SQL表设缺省值。并且,调用这个仅一个参数(the_table)的过程将导致Web Agent产生一个错误。

注意:Web Agent只可以传递基本类型为VARCHAR2的参数到PL/SQL表。这有个限制,
PL/SQL类型VARCHAR2作为最大的PL/SQL数据类型,最大长度限制为32767字节。值在
存储过程里被显式地转换到NUMBER, DATE,或LONG。(使用TO_NUMBER或TO_DATE-LONG
不需转换)。
 

过程重载

PL/SQL允许开发员重载在PL/SQL包中的过程和函数(但不能是独立的函数和过程)。
create or replace package overload is 
     procedure proc1(charval in varchar2); 
     procedure proc1(numval  in number); 
end; 
 
create or replace package body overload is 
     procedure proc1(charval in varchar2) is 
     begin 
        htp.print('The character value is '||charval); 
     end; 
 
     procedure proc1(numval  in number); 
        htp.print('The number value is '||numval); 
     end; 
end;
此机制可以被Web Agent利用,但要求重载的过程的数据类型不能有相同的参数名。
例如:
 
create or replace package overload is 
     procedure proc1(val in varchar2); 
     procedure proc1(val in number); 
end;
当Web Agent试图判断调用哪些过程,它将不能分辨二者并生成错误。

这个限制受HTML-表格数据类型较少的影响,但不会有明显的限制,PL/SQL类型VARCHAR2作为最大的PL/SQL数据类型,最大长度限制为32767字节。值在存储过程里被
显式地转换到NUMBER, DATE,或LONG。(使用TO_NUMBER或TO_DATE-LONG不需转换)。

存取CGI环境变量

Oracle Web Listener遵守通用网关接口(CGI)1.1说明书。因此,所有此说明书包含
的CGI环境变量Oracle Web Listener都将传递给Web Agent。Web Agent也让PL/SQL访
问所有的相关变量。
Web Agent有效的CGI环境变量见表3 - 2.

 
Variable 变量 Variable Meaning 变量意义
AUTH_TYPE  Method used to validate user  
校验用户的类型。
GATEWAY_INTERFACE  The revision of the CGI specification to which the server complies  
服务器兼容的CGI说明书的版本。
HTTP_USER_AGENT  The browser the client is using to send the request  
客户端用来发送请求的浏览器。
PATH_INFO  Extra path information given by the client  
客户端给出的额外的路径信息。
PATH_TRANSLATED  Translated version of PATH_INFO provided by server for mapping. This consists of the document root concatenated to the PATH_INFO.  
服务器提供的映射用的PATH_INFO的翻译版本。
REMOTE_HOST  Hostname making the request if it can be determined  
发出请求的主机名,如果它可以判断的话
REMOTE_ADDR  IP address of the remote host making the request  
发出请求的远程主机IP地址
REMOTE_USER  Used to authenticate user  
用于鉴别用户
REMOTE_IDENT  Set to the remote username retrieved from the server  
设置由服务器检索出的远程用户名
SERVER_PROTOCOL  Name and revision of the information protocol used in the request  
请求使用的信息协议的名称和版本
SERVER_SOFTWARE  Name and version of information server software answering the request  
回答请求的信息服务器软件的名称和版本。
SERVER_NAME  The server's hostname, or IP address  
主机名或IP地址
SERVER_PORT  Port number on which the server is running  
服务器所运行的端口
SCRIPT_NAME  Virtual path to the script being executed, used for self-referencing URL  
将执行脚本的虚拟路径,用于自引用URL。
3 - 2. CGI 环境变量
  这些环境变量可在PL/SQL里用函数owa_util.get_cgi_env获得。参见[*],"The Oracle WebServer Developer's Toolkit".


  译自Oracle7.3联机帮助,不当之处敬请批评指正。

Contents Home Previous Next