发新话题
打印

Oracle Web应用开发之Apache架设与PL/SQL页面设计

本主题由 admin 于 2007-11-4 12:11 移动

Oracle Web应用开发之Apache架设与PL/SQL页面设计

Oracle有多种方法在网页上显示数据库中的数据,如JSP或XML编程。在Oracle8i/9i中应用开发人员可以自由使用Java或PL/SQL,把PL/SQL代码嵌入网页中实现业务逻辑的页面就是PSP页面。



PSP页面及其运行环境Apache mod_plsql模块


Oracle 数据库中的Oracle HTTP Server组件就是Apache服务器,在Oracle8i/9i中接受PL/SQL调用的Web组件就是Apache的mod_plsql模块,该模块为Oracle数据库产品,在Oracle9iAS中的Oracle Portal中同样包含,本文不介绍Oracle9iAS中的Web服务。mod_plsql模块模块提供了在Apache、Oracle Portal和数据库之间的严密的综合性和安全性,并改善交互作用和经Web请求调用的程序的执行情况。 Portal开发工具箱(Portal Development Kit,PDK)的两个主要特点是完全用PL/SQL实现的PDK -PL/SQL和用Java实现调用接口的PDK-Java。它们都能访问Web资源或数据库服务器,两者都能调用Java程序,如果Java程序被导入数据库中,可以从PL/SQL调用它们。下面是构成全部Portal环境的组件列表: 1.Oracle Database Aerver 2.HTP/HTF包和工具(PL/SQL Web Toolkit) 3.Portal procedures(Portal进程) 4.Portal Schema(数据库表) 5.Oracle 9iAS Application Server(及Logon Server) 6.Apache HTTP Server 7.Mod_PLSQL Apache Plug-in 8.Portalets 9.External images(外部图象) 10.建立应用程序需要的Tables和数据 Oracle 9iAS Application Server和Apache HTTP Server是结构中的底层部分,它们成为开发中的最重要的部分之一。Listener和Mod_PLSQL网关是配对的,Listener自身是个完整的Apache HTTP Server,它的作用是管理HTTP样式请求的进程。Mod_PLSQL网关负责交换数据进出数据库。Mod_PLSQL网关包括为了和Net8交流的全部必要信息。Oracle把Apache HTTP Server和Mod_PLSQL网关都作为Oracle9iAS和数据库安装的一部分进行安装。


下面说明当在浏览器浏览网址http://localhost/pls/simpledad/show时(结果如图1所示)服务器的响应过程。




图1Apache监听器是一个HTTP服务,处理所有通过请求端口(默认端口为80)的请求,请求首先路由到本地主机。因为请求字符串中包含"pls",即虚拟目录,该字符串(表示请求的实际字符串是可配置的,此处为默认配置)的定义在$ORACLE_HOME\apache\modplsql\cfg\plsql.conf文件中,Apache根据这一文件识别出"pls"是一个PL/SQL请求并且把执行任务传递给PL/SQL模块(mod_plsql)。mod_plsql随后查看网址字符串的剩下部分。"simpledad"是数据库访问描述符(Database Access Descriptor,DAD),它给出关于mod_plsql怎样被连接到数据库中去执行请求的信息,可以配置多个DAD,它包含用户名、密码、认证方式、路径别名等信息。“show”为mod_plsql执行的PL/SQL过程,如果在URL的最后没有指定过程名,则mod_plsql会查找默认的过程名,此默认过程名也可在DAD中设置。过程运行并发送结果(使用PL/SQL Web Toolkit生成的)到HTTP缓冲区中,当过程执行完后,HTTP缓冲区的内容通过mod_plsql和Apache返回到浏览器。过程可以直接使用PL/SQL Web Toolkit编程,也可以通过loadpsp命令行工具把PSP页面加载到数据库中生成过程,浏览PSP页面只需在URL中以过程名结尾即可,不需扩展名“.psp”。 需要注意的是,在Portal体系中,可以由文件夹和文档来管理用于显示在浏览器中的图象和多媒体,而本文在仅安装Oracle数据库时,图片等多媒体类型的文件必须存放在“$ORACLE_HOME\apache\modplsql\cfg\images\”路径下,并且在PSP页面中调用时使用路径“admin_/images/”。 PL/SQL语言已经长时间作为Oracle数据库和开发环境的基础,Oracle本身是使用PL/SQL建立的,并且Oracle已经建立了从PL/SQL过程直接访问HTML的方法,但太依赖于PL/SQL代码会使后来的可能不熟悉PL/SQL代码的开发者难于维护应用程序。使用PL/SQL页面表示层的优势之一是实现了表示层与业务逻辑的分离,业务逻辑以存储过程的形式存储在数据库中,优势之二是PL/SQL页面页面的运行取决于对数据库过程的调用,独立于应用服务器,在数据库缓存服务器支持下运行性能好。



配置Apache的mod_plsql模块


设置Apache Web 服务器中的mod_plsql模块来接收浏览器对数据库中的存储过程的调用。Oracle HTTP Server组件已经包含在Oracle9.0.1服务器中,使用缺省的端口和主机参数,配置文件$ORACLE_HOME\apache\apache\conf\httpd.conf不用修改。需要为Apache Web 服务器设置DAD,步骤如下: 1.浏览网址http://202.99.18.136,也是本机地址或Apache服务器的主机地址.如图2所示。



图22.打开组件mod_plsql的链接,如图3所示。





图33.点击"网关数据库访问描述符设置",如图4所示。可以将新的数据库访问描述符添加到现有列表。此处配置的信息包括:用户名、口令、连接字符串、文档上载路径和过程、需要进行 long raw 上载的文件扩展名、路径别名和相关过程,以及确认连接的信息。本例中




修改SIMPLEDAD,如图5所示。





[ 本帖最后由 Oracle 于 2007-7-6 13:34 编辑 ]

TOP

4.在SIMPLEDAD的编辑页面中,修改Oracle 用户名为cf,Oracle 口令为cf,Oracle 连接字符串为db:152190,如果网关在所连接的数据库以外的其他Oracle主目录中运行,则需要TNS连接字符串。此外,也可使用以下格式的组合字符串来替代TNS连接字符串,即<HOST>:<ORT>:<SID>。<HOST>是运行数据库的主机名,<ORT>是TNS监听程序监听的端口号,<SID>是数据库例程的Oracle SID名称。为了获取最佳性能,请保持网关的数据库连接池处于打开状态。网关使用"文档访问信息"向与此数据库访问描述符关联的数据库上载或下载文档。默认情况下所有文档都将以BLOB类型上载。通过在Long Raw字段中指定以逗号分隔的文件扩展名,可以覆盖此默认设置。此字段的"*"值将使所有文档以Long Raw 数据类型上载。"文档访问过程"指定用于访问文档的虚拟路径。"文档访问过程"字段指定网关处理文档请求所调用的过程。此处都使用缺省值。如果通过此网关连接的应用程序支持将绝对路径映射到关键字,可以指定关键子,本例中此处为空。设置完该页面后返回上级页面。




图55.下面设置全局网关。在如图3所示的网关配置菜单中选择"网关全局设置",如图6所示,将第5步中编辑修改的数据库访问描述符SIMPLEDAD作为默认全局网关的DAD。




图6编写存储过程和网页代码本实例的数据库对象都在cf/cf操作模式下。数据库环境为Oracle9.0.1,带有Oracle HTTP Server安装(已自动安装mod_plsql模块),未安装Oracle9iAS及其任何组件。



[ 本帖最后由 Oracle 于 2007-7-6 13:36 编辑 ]

TOP

1.建立表student并插入7条记录。

CREATE TABLE student
(ID  NUMBER(5,0) NOT NULL
,NAME  VARCHAR2(15) NOT NULL
,DOB  DATE
,GENDER  VARCHAR2(2) DEFAULT '男'
,CLASSYR  NUMBER(4,0) DEFAULT 2002 NOT NULL
,MAJOR  VARCHAR2(25)
,EMAIL  VARCHAR2(50)
,PHOTO  VARCHAR2(100)
);
alter session set nls_date_format = 'dd-mon-yyyy';
alter session set nls_date_language = 'AMERICAN';
insert into student values ( 1001,'赵鹏','14-JUL-1975','男',2001,'History',
'1001@NetUniversity.org','u1001.gif')
/
insert into student values ( 1002,'刘宇','08-OCT-1975','女',2001,'Science',
'1002@NetUniversity.org','u1002.gif')
/
…………



2.以帐户cf/cf建立存储过程show_student。

create or replace procedure show_student
(p_id         in out student.id%TYPE
,p_name          out student.name%TYPE
,p_dob           out student.dob%TYPE
,p_gender        out student.gender%TYPE
,p_classyr       out student.classyr%TYPE
,p_major         out student.major%TYPE
,p_email         out student.email%TYPE
,p_photo         out student.photo%TYPE
)
IS
CURSOR get_student(p_id in student.id%TYPE DEFAULT 1001) IS
    SELECT * FROM student
    WHERE id = NVL(p_id,1001);
student_row student%ROWTYPE;
BEGIN
    IF p_id<1001 THEN
       p_id:=1001;   
    END IF;
    IF p_id>1007 THEN
       p_id:=1007;
    END IF;
    OPEN  get_student(p_id);
    FETCH get_student INTO student_row;
    CLOSE get_student;
    p_name          := student_row.name;
    p_dob           := student_row.dob;
    p_gender        := student_row.gender;
    p_classyr       := student_row.classyr;
    p_major         := student_row.major;
    p_email         := student_row.email;
    p_photo         := student_row.photo;
END;
/

TOP

3.编写PSP网页,文件名为show.psp。

程序说明:第1行标识出该页为PL/SQL语言文件。第2行指出即将为该页面生成的PL/SQL过程名,最后PL/SQL页面将要调用数据库中的该过程来显示数据,如果省略该行则以文件名作为缺省的过程名。第3行为即将生成的过程的输入或输出参数,以标记说明,default="1001"说明该参数为可选参数,注意,即使是数值数据类型,也要用双引号括起。第4至11行为该PSP网页的全局参数,同时也是过程show的局部参数,以标记表示。接下来以全局参数调用已经存储在数据库中的过程show_student,程序代码前后分别被置以标记。当然也可将第二步中的过程show_student的编码直接写入以标记括起的程序中,但是为了实现代码与内容的分离,尽量不要把它们混在一起。这样做的好处是分离业务逻辑与表示层,使得程序结构清晰,因为可能还有其它PSP页面调用该存储过程。在页面显示部分对全局参数的调用格式为标记,这也是输出标记,该标记可以实现字符串的连接和变量的计算,如通过psp_id的加减1达到翻页目的。在链接标记<a href="show?id=<%=psp_id-1%>">中,注意show为已经存储的过程,用"show?id="的格式调用过程并输入参数。

<%@ show language="PL/SQL"%>
<%@ plsql procedure="show" %>
<%@ plsql parameter="id" type="NUMBER" default="1001"%>
<%! psp_id        student.id%TYPE:=id;%>
<%! psp_name      student.name%TYPE;%>
<%! psp_dob       student.dob%TYPE;%>
<%! psp_gender    student.gender%TYPE;%>
<%! psp_classyr   student.classyr%TYPE;%>
<%! psp_major     student.major%TYPE;%>
<%! psp_email     student.email%TYPE;%>
<%! psp_photo     student.photo%TYPE;%>
<%
show_student
(   p_id         => psp_id
,   p_name       => psp_name
,   p_dob        => psp_dob
,   p_gender     => psp_gender
,   p_classyr    => psp_classyr
,   p_major      => psp_major
,   p_email      => psp_email
,   p_photo      => psp_photo
);
%>
<html>
<head>
<title>学生信息</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body bgcolor="#999900" text="#FFFFFF" link="#3366FF">
<table width="80%" border="0" cellspacing="2" cellpadding="2" align="center"
height="400">
  <tr>
    <td colspan="3" height="72">
      <div align="center"><font size="+3"><b>学生信息</b></font></div>
    </td>
  </tr>
  <tr>
    <td width="40%" height="195" rowspan="8"><img
src="admin_/images/<%=psp_photo%>" width="172" height="191" align="middle"></td>
    <td colspan="2" height="30">编号为<%=psp_id%>的学生的资料如下:</td>
  </tr>
  <tr>
    <td colspan="2" height="30">编号:<%=psp_id%></td>
  </tr>
  <tr>
    <td colspan="2" height="30">姓名:<%=psp_name%></td>
  </tr>
  <tr>
    <td colspan="2" height="30">出生日期:<%=psp_dob%></td>
  </tr>
  <tr>
    <td colspan="2" height="30">性别:<%=psp_gender%></td>
  </tr>
  <tr>
    <td colspan="2" height="30">年级:<%=psp_classyr%></td>
  </tr>
  <tr>
    <td colspan="2" height="30">主修课程:<%=psp_major%></td>
  </tr>
  <tr>
    <td colspan="2" height="30">电子邮件:<%=psp_email%></td>
  </tr>
  <tr>
    <td width="40%" height="74">
      <div align="center"></div>
    </td>
    <td width="46%" height="74">
      <div align="center"><a href="show?id=<%=psp_id-1%>">上一页</a>
  <a href="show?id=<%=psp_id+1%>">下一页</a></div>
    </td>
    <td height="74" width="14%">
      <div align="center"></div>
    </td>
  </tr>
</table>
</body>
</html>



4.使用Oracle命令行程序

使用Oracle命令程序$ORACLE_HOME\bin\loadpsp.exe将第3步编写的PSP页面(show.psp)载入数据库的cf/cf模式下。loadpsp.exe程序的所有选项格式如下:

l:\oracle\ora90\bin\loadpsp.exe
usage: loadpsp [-replace] -user <logon> [<page1><page2> ...]
       where <logon> ::= <username>/<password>[@<connect_string>]



本例中使用如下命令:

l:\oracle\ora90\bin\loadpsp -replace -user cf/cf show.psp
"show.psp":procedure "show" created.



5.载入show.psp页面后,在数据库的cf/cf模式下生成存储过程show(该过程名由网页show.psp中的<%@ plsql procedure="show" %>程序决定),过程中已经加入HTP进程包来调用参数。

PROCEDURE show (
id IN NUMBER default 1001) AS
psp_id        student.id%TYPE:=id;
psp_name      student.name%TYPE;
psp_dob       student.dob%TYPE;
psp_gender    student.gender%TYPE;
psp_classyr   student.classyr%TYPE;
psp_major     student.major%TYPE;
psp_email     student.email%TYPE;
psp_photo     student.photo%TYPE;
BEGIN NULL;
htp.prn('

');
htp.prn('
');
htp.prn('

');
htp.prn('
');
htp.prn('
');
htp.prn('
');
htp.prn('
');
htp.prn('
');
htp.prn('
');
htp.prn('
');
htp.prn('

');

show_student
(   p_id         => psp_id
,   p_name       => psp_name
,   p_dob        => psp_dob
,   p_gender     => psp_gender
,   p_classyr    => psp_classyr
,   p_major      => psp_major
,   p_email      => psp_email
,   p_photo      => psp_photo
);

htp.prn('

<html>
<head>
<title>学生信息</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body bgcolor="#999900" text="#FFFFFF" link="#3366FF">
<table width="80%" border="0" cellspacing="2" cellpadding="2" align="center"
height="400">
  <tr>
    <td colspan="3" height="72">
      <div align="center"><font size="+3"><b>学生信息</b></font></div>
    </td>
  </tr>
  <tr>
    <td width="40%" height="195" rowspan="8"><img src="admin_/images/');
htp.prn(psp_photo);
htp.prn('" width="172" height="191" align="middle"></td>
    <td colspan="2" height="30">编号为');
htp.prn(psp_id);
htp.prn('的学生的资料如下:</td>
  </tr>
  <tr>
    <td colspan="2" height="30">编号:');
htp.prn(psp_id);
htp.prn('</td>
  </tr>
  <tr>
    <td colspan="2" height="30">姓名:');
htp.prn(psp_name);
htp.prn('</td>
  </tr>
  <tr>
    <td colspan="2" height="30">出生日期:');
htp.prn(psp_dob);
htp.prn('</td>
  </tr>
  <tr>
    <td colspan="2" height="30">性别:');
htp.prn(psp_gender);
htp.prn('</td>
  </tr>
  <tr>
    <td colspan="2" height="30">年级:');
htp.prn(psp_classyr);
htp.prn('</td>
  </tr>
  <tr>
    <td colspan="2" height="30">主修课程:');
htp.prn(psp_major);
htp.prn('</td>
  </tr>
  <tr>
    <td colspan="2" height="30">电子邮件:');
htp.prn(psp_email);
htp.prn('</td>
  </tr>
  <tr>
    <td width="40%" height="74">
      <div align="center"></div>
    </td>
    <td width="46%" height="74">
      <div align="center"><a href="show?id=');
htp.prn(psp_id-1);
htp.prn('">上一页</a>
  <a href="show?id=');
htp.prn(psp_id+1);
htp.prn('">下一页</a></div>
    </td>
    <td height="74" width="14%">
      <div align="center"></div>
    </td>
  </tr>
</table>
</body>
</html>
');
END;



6.浏览网址:http://localhost/pls/simpledad/show,即可看到如图1所示的页面,可点击"上一页"或"下一页"浏览相临记录。

(责任编辑 Sunny)

TOP

发新话题