开发人员:J2EE
"Hello Ajax"!如何在 Oracle JDeveloper 中进行 Ajax 编程
作者:Frank Nimphius
通过创建简单的 "Hello World" 程序来简单介绍 Ajax 编程。
2006 年 5 月发表
可以肯定的是,目前世界上最成功的计算机程序当属 "hello world"。几乎所有的编程语言和编程模式都使用了该程序。
"Ajax" 是软件业为描述一组相关 Web 浏览器技术而使用的缩略语,这些浏览器技术结合在一起可为使用 web 应用程序的用户提供丰富的客户端用户体验。Ajax 有望缩小目前在基于浏览器的 web 应用程序与当前客户端-服务器桌面应用程序之间的使用差距。在本文中,您将了解如何使用 Ajax 编写 "hello world",并通过几个步骤完成从简单到高级的转化过程。
关于 Ajax
"Ajax" 表示 异步 Javascript 和 XML,它是 "Web 2.0" 范型的核心。一种定义(Web 2.0 有多个定义)指出,Web 2.0 是可提高响应速率、提供丰富 UI 组件的新一代 Web 应用程序的简写,它使 Web 应用程序更贴近客户端-服务器桌面客户端的用户体验。Ajax 不是软件标准,而是对一组技术的描述,这些技术包括 JavaScript、文档对象模型 (DOM) 和浏览器 XmlHttpRequest 对象(IE 中为 XmlHttp 对象)。通过结合使用这些技术,用户可以构建基于浏览器的交互式用户界面。
借助浏览器 XmlHttpRequest 对象,Ajax 应用程序可以使用异步通信检索服务器数据。对于怎样的 Web 应用程序才算是 Ajax 应用程序目前还没有明确定义。因此,目前对待 Ajax 的最佳方式是将其视为构建下一代 Web 应用程序(这些应用程序使我们更接近最终用户在客户端-服务器桌面客户端上的体验)的编程模式。需要注意的一点是,Ajax 与 J2EE 或 Java 无关;相反,它可以与 .NET、PHP、CGI 和 Perl 一起使用。有关 Ajax 的好消息是,它用来解释规则的示例并不比 "hello world" 复杂。
这篇方法文档为您利用 Oracle JDeveloper 构建 J2EE 中的 Ajax 应用程序提供了一流的上机体验。
这些练习使用的技术包括:
- JavaScript - JavaScript 语言在浏览器客户端上执行,它是 Ajax 的核心。使用 JavaScript 在客户端执行逻辑、数学和功能操作。使用文档对象模型 (DOM) 时,可使用 JavaScript 动态处理浏览器中显示的网页。
- 文档对象模型 (DOM) - 它是 HTML 页面文档的虚拟树状表示,保存在浏览器内存中,可以通过 JavaScript 进行访问。可以使用 DOM 树动态处理浏览器中当前 HTML 页面上的 UI 组件。
- XmlHttpRequest - XmlHttpRequest 对象是用于访问远程服务器的浏览器端 API,几乎所有现代浏览器都可以提供这种技术。XmlHttpRequest 对象使客户端可以使用 http GET 或 POST 请求获取远程服务器数据,且无需在页面间导航。服务器访问可以设计为同步或异步方式,后者将使用 JavaScript 回调机制。
- 样式表 (CSS) - CSS 用于定义服务器上组件的外观、位置和大小。使用外部 CSS 资源时,您可以使应用程序的外观独立于视图的显示 — 在使用 Ajax 的情况下,视图通常是利用 Javascript 构建的。
- HttpServlet - HttpServlet 用于模仿服务器会话来展示 Ajax 的后台数据检索。
用 Oracle JDeveloper 10.1.3 构建 Ajax 应用程序
遵循此处列出的详细指示,您将从静态 HTML 客户端读取服务器端文件的文本字符串开始逐步构建 "Hello Ajax"。完成此方法文档后,您将开发出一个从服务器上的 servlet 读取数据的网页,并使用 CSS 样式表为检索的数据行建立交变的背景色。一个输入文本域允许您为显示的消息提供输入。单击此处下载完整的 Oracle JDeveloper 10.1.3 工作区。
构建同步 Ajax 页面
1.
|
从 Jdeveloper 菜单和 New Gallery 中选择 File > New > New Application,打开 Oracle JDeveloper 10.1.3 并创建一个新的应用程序。在创建对话框中,键入 JDeveloper 应用程序名 "HelloAjax",并提供其他所需信息。由于默认的 JDeveloper 项目可以满足需要,因此您不必选择应用程序模板。
|
2.
|
为默认的 JDeveloper 项目命名,如 "Ajaxprj"。 |
3.
|
从 Ajaxprj 节点的上下文菜单中选择 New,打开 JDeveloper New Gallery。 |
4.
|
创建一个新的 HTML 页面 helloAjax.hml。验证 helloAjax.html 文件位于 public_html 目录下,以便嵌入的 web 容器能运行该文件。
|
5.
|
创建一个文本文件 helloAjax.txt。要创建该文本文件,在 JDeveloper New Gallery 中选择 General > Simple Files 条目。 |
6.
|
创建一个 JavaScript 文件 helloAjax.js。JavaScript 文件可通过选择 Web Tier > HTML 条目进行创建。同时,确保上述两个文件位于 JDeveloper "Ajaxprj" 项目的 public_html 目录下。 |
7.
|
在源代码视图中打开 helloAjax.html 文件,将光标置于 <head></head> 元素之间,并从 JDeveloper 组件选项板 (ctrl+shift+P) 中选择 Html Common > Script。在打开的对话框中选择 helloAjax.js 文件条目。此操作在 html 文件中创建一个对 JavaScript 的引用,以确保向客户端加载 HTML 页面时 JavaScript 代码可用。
|
8.
|
在源编辑器中打开 helloAjax.js 文件,将以下 JavaScript 代码复制到文件中。
var xmlHttpRequestHandler = new Object();
xmlHttpRequestHandler.createXmlHttpRequest = function(){
var XmlHttpRequestObject;
if
(typeof XMLHttpRequest != "undefined"){
XmlHttpRequestObject = new XMLHttpRequest();
}
else if
(window.ActiveXObject){
// look up the highest possible MSXML version
var tryPossibleVersions=["MSXML2.XMLHttp.5.0",
"MSXML2.XMLHttp.4.0",
"MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp",
"Microsoft.XMLHttp"];
for
(i=0; i< tryPossibleVersions.length; i++){
try{
XmlHttpRequestObject = new ActiveXObject(tryPossibleVersions[i]);
break;
}
catch (xmlHttpRequestObjectError){
//ignore
}
}
}
return XmlHttpRequestObject;
}
JavaScript 是可重复使用的代码,它初始化 XmlHttprequest 对象并为调用程序返回句柄。 XmlHttpRequestObject 变量是作为 createXmlHttpRequest 函数的句柄创建的。JavaScript 在一定程度上允许面向对象的编程,而将变量用作对函数的引用避免了命名冲突(在此情况下,JavaScript 文件中包含多个同名的函数)。
createXmlHttpRequest 函数的 XmlHttpRequestObject 变量用于保存 XmlHttpRequest 对象引用。查看代码,您将发现我们在寻找 XmlHttpRequest 对象和 XmlHttp 对象。虽然 Internet Explorer 和其他浏览器都支持 XmlHttprequest 对象,但该对象在 Internet Explorer 中的命名与其他浏览器有所不同。如果第一个条件 typeof XMLHttpRequest != "undefined" 能够满足,则客户端浏览器是 Mozilla、Safaris 或任何支持异步 JavaScript 请求和响应的非 IE 浏览器。如果条件 window.ActiveXObject 为真,则客户端浏览器为 IE。Microsoft 的浏览器还会区分 XmlHttp 版本支持,因此开发人员最好使用最新的支持。 for() 循环测试浏览器对特定 XmlHttp 版本(从最新版本到最旧版本)的支持,并从 XmlHttpRequest 对象引用中引用最新的版本支持。
使用 XmlHttpRequest 对象引用时,您可以使用 JavaScript 从 HTML 页面发出服务器调用。根据发布请求的方式是同步的还是异步的,浏览器会等待服务器响应或使用 JavaScript 回调句柄向页面通知服务器的响应。在该此上机练习中,您将接触到上述两种情况。
|
9.
|
保存您的工作。
|
10.
|
在 JDeveloper 中打开 helloAjax.txt 文件并输入文本消息 hello Ajax,然后保存文件。 |
11. |
首要工作已经完成,现在您可以集中构建 HTML 页面了,该页面是真正的 Ajax 客户端。在源代码视图编辑器中打开 helloAjax.html 文件。 |
12. |
将光标置于 <head>...</head> 元素之间,从组件选项板中选择 Html Common > Script 条目。此时,您无需引用外部 JavaScript 文件,而只需直接在对话框的 Content 文本区域输入 JavaScript 代码。以下 JavaScript 代码引用了 helloAjax.js 脚本中创建的 xmlHttpRequestHandler,将静态的 HTML 文件转换成动态的 Ajax 客户端。
function doTheAjaxThing(){
var PAGE_SUCCESS = 200;
var requestObject = xmlHttpRequestHandler.createXmlHttpRequest();
requestObject.open("Get","helloAjax.txt",false); requestObject.send(null);
if
(requestObject.status==PAGE_SUCCESS){
var div_handle = document.getElementById("message");
//check if DIV element is found
if(div_handle){
div_handle.innerHTML+='</'+'br>'+
requestObject.responseText;
}
}
else{
alert ("Request failed");
}
}
函数 doTheAjaxThing 从 HTML 页面上的输入按钮调用,并从服务器端的文本文件获得 "hello Ajax" 字符串。在 Script 对话框中按下 OK 后,函数添加到 HTML 页面标题上,且包含在 <script>...</script> 元素对中。从文件引用的 JavaScript 代码与直接向页面添加的 JavaScript 的不同之处在于,前者可以在许多其他 HTML 页面中重复使用,这就是它为什么只应包含通用代码的原因。
上述脚本使用 helloAjax.js 文件中的 xmlHttpRequestHandler 引用创建一个 requestObject 变量,该变量包含 XmlHttpRequest 对象的句柄。注意,你无需考虑页面在 IE 还是 Mozilla 中运行。对浏览器类型的选择由可重用的 JavaScript 文件进行。在 requestObject 句柄上,调用 open() 并传递三个自变量。第一个自变量指定了访问,该访问可以是任何允许的服务器访问,如 GET、POST 或 HEAD。第二个自变量引用需要读取的 URI 源。本示例中的资源是一个文本文件,而后面示例中的资源是 HttpServlet。注意,JavaScript 安全(也称为 JavaScript 沙箱)只允许访问从中下载代码的服务器。第三个自变量是布尔类型,它定义了调用是同步(假)还是异步(真)。使用同步请求时,浏览器等待服务器响应。当从服务器获取大量数据时,您不希望在实际使用的应用程序中看到这种情况。稍后,您在本次上机练习中将使用异步服务器访问。
XmlHttp Request 对象上的 requestObject.send(null)> 方法调用向服务器发送请求。如果这是 POST 请求,则 null 自变量将由要求服务器处理的请求参数列表代替。
由于此示例使用了同步服务器调用,因此浏览器在继续工作之前会等待服务器的响应。由服务器发送、表示请求成功的 http 代码是 200。在调用 requestObject.responseText 从 requestObject 中读取服务器响应之前,检查成功状态使用 requestObject.status==PAGE_SUCCESS。这是 XmlHttpRequest 对象提供的方法。其他代码引用页面上的 DIV HTML 元素,该元素可通过 DOM 树访问并用于显示服务器响应。
注意: requestObject.responseText 用于访问来自服务器的纯文本响应。要获得 XML 格式的数据,使用 XMLHttpRequest 对象的 responseXML 方法。有关 responseXML 的用法示例,请参见“AJAX 非宣传性简介”。需要动态确定响应类型的应用程序可以执行以下语句:
var contentType =
requestObject.getResponseHeader("content-type");
可能返回的内容类型为 'text/xml' 或 'text/plain',指示内容是 XML 或纯文本类型。
|
13. |
接下来的工作是在 HTML 页面上创建调用 > doTheAjaxThing 函数的输入按钮和显示结果的 <DIV> 元素。在 helloAjax.html 文件的代码编辑器视图中,在 <body>...</body> 元素之间复制以下 HTML 源代码。
<input type="button" value="Press Me"
onclick="doTheAjaxThing();"/>
<div
id="message">
</div>
添加到输入按钮的 onclick 事件在单击鼠标时调用 doTheAjaxThing 方法。<DIV> 元素有一个 id 属性,该属性用于为元素赋予唯一的名称,以便在 DOM 树中可以直接访问该元素。
|
14.
|
为避免浏览器缓存静态 HTML 页面(这样做会对测试 Ajax 页面造成干扰),在 <head> 和 </head> 元素间添加以下语句行。
<meta http-equiv="pragma" content="no-cache"></meta>
注意,可以在 <head> 元素之间设置多个 <meta ...> 元素。此语句告知浏览器不要缓存该页面及其内容。 |
15. |
现在,该 HTML 文件应如下所示:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></meta>
<title>Hello Ajax from file</title>
<script src="helloAjax.js" type="text/javascript"></script>
<script type="text/javascript">
function doTheAjaxThing(){
var PAGE_SUCCESS = 200;
var requestObject = xmlHttpRequestHandler.createXmlHttpRequest();
requestObject.open("Get","helloAjax.txt",false);
requestObject.send(null);
if(requestObject.status==PAGE_SUCCESS){
var div_handle = document.getElementById("message");
//check if DIV element is found
if(div_handle){
div_handle.innerHTML+='<br></'+'br>'+requestObject.responseText;
}
}
else{
alert ("Request failed");
}
}
</script>
</head>
<body>
<input type="button" value="Press Me" onclick="doTheAjaxThing();"<//>
<DIV id="message"></DIV>
</body>
</html>
|
16. |
保存您的工作并运行 HTML 文件。
|
17. |
多次按下此按钮。显示的结果应如下所示。
注意,此页面附加了所有从服务器读取的字符串。要证明当前页面使用了 Ajax,单击页面的重新加载按钮,您会发现所有字符串都从页面中删除了。
|
恭喜!您已创建了第一个 Ajax 程序!
增强 Ajax 应用程序
以下练习构建在上一个示例的基础上,并用 Http Servlet 替换了 helloAjax.txt 文件。由于 servlet 可以包含逻辑,能够基于预先的定义修改响应格式,因此 servlet 比文件更具动态性,您可以使用 CSS 样式表为返回的数据行设置交变颜色,并显示页面用户键入的文本。
1.
|
使用 Ajaxprj 项目上的 New 选项打开 JDeveloper New Gallery。选择 Web Tier > HTML 树条目中的 CSS File 选项。将文件命名为 helloAjax.css,然后确保该文件位于 public_html 目录下。 |
2.
|
删除 JDeveloper 默认生成的样式表代码。 |
3.
|
将以下代码复制或键入到样式表文件中,然后保存该文件。
div.message b.red
{
background-color:gray;
color:RED;
font-family:Arial, Helvetica, sans-serif;
}
div.message b.green
{
background-color:yellow;
color:GREEN;
font-family:Arial, Helvetica, sans-serif;
}
div.message b.red 标记显示所有 <b> 元素时使用灰色背景颜色和红色字体颜色。<b> 元素有一个类属性 "red",并作为子元素嵌入具有一个 message 类属性的 HTML <DIV> 元素中。<DIV> 和 <b> HTML 元素作为返回给异步 Ajax 请求的服务器请求的一部分动态创建。
|
4.
|
要创建 Http Servlet,从 JDeveloper 上下文菜单中选择 New,然后选择 Web Tier > Servlets 条目。从可选项中选择 HTTP Servlet。将 servlet 类命名为 HelloAjax,保留所有其他域和对话框的默认值。此操作将创建一个 Http Servlet 并将其映射为 web.xml 部署描述符中的 /helloajax 名。
|
5.
|
将两个例程域
private int counter = 0;
private String name="";
添加到 servlet 中,且正好位于 private static final String CONTENT_TYPE = "text/html; charset=windows-1252"; 域中。
|
6.
|
更改 servlet doGet 方法的代码,使其如下所示
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
++counter;
name = request.getParameter("name") != null?(String)request.getParameter("name"):null;
//init cap
name="From "+name;
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
if
(counter % 2 == 0)
{
out.println("<b class='green'>Hello Ajax "+name+" </b><br<//>");
}
else
{
out.println("
<b class='red'>Hello Ajax "+name+" </b><br<//>");
}
out.close();
}
Servlet 期待包含用户输入的请求参数 "name",并将该参数添加到 Hello Ajax 消息中。每个偶数行都用 CSS 类引用 ‘green’ 显示,每个非偶数行都用 CSS 类引用 ‘red’ 显示。由于 XmlHttpRequest 输出显示在 <DIV></DIV> 元素对之间,因此为输出设置颜色的样式表将 <b> 元素表现为 div b.green 或 div b.red。稍后,您会为 HTML DIV 元素添加 class="message" 属性,因此产生的 CSS 引用为 div.message b.red 和 div.message b.green,这些是您先前在 helloAjax.css 文件中定义的 CSS 名称。 |
7.
|
保存您的工作。 |
8.
|
在 JDeveloper 代码视图编辑器中打开 helloAjax.html 文件。 |
9.
|
将 HTML <body> 的内容从
<body>
<input type="button" value="Press Me" onclick="doTheAjaxThing();"<//>
<div id="message"></div>
</body>
更改为
<body>
<form name="form1" action="">
<input type="button" value="Press Me" onclick="doTheAjaxThing();"/>
<input type="text"id="name" name="name"/>
</form>
<div id="message" class="message"></div>
</body>
现在,该 HTML 文件中包含一个额外的文本域,可供用户键入输出字符串。名称输入域的 id 属性为 "name",用户可以使用浏览器的 DOM 树通过 JavaScript 对其进行访问。文本域的确切位置是 document.form1.name。
最后更改的内容是 class 属性,该属性被添加到 <div> 元素,以便由样式表文件进行处理。
|
10. |
转至 helloAjax.html 文件的设计视图。在 Application Navigator 中选择 helloAjax.css 条目,然后将该条目拖放到 HTML 页面上。此操作会在运行时创建由 HTML 页面到样式表的引用。 |
11.
|
再次打开源代码视图中的 helloAjax.html 文件,并在 <head></head> 元素对之间查找 doTheAjaxThing() 方法。 |
12.
|
将以粗体突出显示的第一行添加到 JavaScript 函数中,然后使用突出显示的第二个代码行替换当前的 requestObject.open() 方法。
function doTheAjaxThing(){
var requestObject;
var PAGE_SUCCESS = 200;
var param="name="+(document.form1.name.value.length >0 ?document.form1.name.value:"nobody");
requestObject = xmlHttpRequestHandler.createXmlHttpRequest();
requestObject.open("Get","helloajax?"+param,false);
requestObject.send(null);
...
第一行创建一个变量参数,该参数读取输入文本域的值。为确保该域的值不为空,您可以使用 JavaScript 测试输入字符串的长度。如果域值确实为空,则使用 "nobody"。
requestObject.open 方法调用目前引用 helloajax(服务器端 HTTP Servlet 的 web.xml 名称),而不是 helloajax.txt 文件。由于该请求为 GET 请求,因此 name 请求参数使用问号 ' ?' 添加到 servlet 引用中。如您所见,从 XmlHttpRequest 的观点来看,由调用服务器上的静态文件转变为调用 servlet 所需进行的更改很少。
|
13.
|
您还可以将标题中的 HTML <tile> 元素更改为
<title>Hello Ajax from servlet</title>
|
14.
|
保存您的工作,然后运行 helloAjax.html 文件。
|
您将发现,第一次运行应用程序时有轻微的延迟现象。这是由 servlet 所需的初始启动时间造成的。该延迟会给用户造成不好的印象,因此在下一部分中,您将把同步 XmlHttpRequest 调用更改为异步调用。
使 Ajax 成为异步应用程序
异步请求允许应用程序用户在等待服务器响应的同时继续进行自己的工作。即使用户不能在服务器响应前继续自己的工作,使用异步请求的方法也比同步调用更有利。例如,为避免用户将注意力集中在按下的按钮上,您可以在屏幕上显示一些可供最终用户消遣的小部件,如进度条。这部分上机练习不会涉及到上述内容,我们仅把同步调用更改为异步调用。
1.
|
使用以下语句替换在 helloAjax.html 页面中定义 doTheAjaxThing() 函数的当前 JavaScript 语句,使请求成为异步调用:
<script type="text/javascript">
var requestObject;
var READY_STATE_COMPLETE = 4;
var PAGE_SUCCESS = 200;
function doTheAjaxThing(){
param="name="+(document.form1.name.value.length >0 ?document.form1.name.value:"nobody");
requestObject = xmlHttpRequestHandler.createXmlHttpRequest();
requestObject.onreadystatechange=onReadyStateChangeResponse;
requestObject.open("Get","helloajax?"+param,true);
requestObject.send(null);
}
function onReadyStateChangeResponse(){
var ready = requestObject.readyState;
var status = requestObject.status;
if(ready==READY_STATE_COMPLETE && status == PAGE_SUCCESS){
var div_handle = document.getElementById("message");
//check if DIV element is found
if(div_handle){
div_handle.innerHTML+='
</'+'br>'+requestObject.responseText;
}
}
}
</script>
当前的异步请求处理与前一个同步调用之间的差异以粗体突出显示。由于浏览器不等待服务器做出响应,此示例使用了 JavaScript 回调(状态改变时由 XMLHttpRequest 对象调用的函数)。涉及到的状态有四种,包括:
0
|
请求初始化,这是在 XmlHttRequestObject 上调用 open() 方法前的状态。 |
1
|
准备发送请求。 |
2
|
请求已发出,正在服务器上处理。 |
3
|
服务器处理请求。 |
4
|
响应完成,可供客户端进行进一步处理。 |
用户最关注的状态由状态值 4 指出。在上面的 JavaScript 函数中,为进行更好的读取,此数值被赋给 JavaScript 变量 READY_STATE_COMPLETE。不要混淆状态与状况。状态是 XmlHttpRequest 返回的值,而状况是 HTTP 代码,用于通知用户所请求的访问。例如,如果 requestObject 状况为 403,则用户访问了未被授权的服务器资源。此状况需要的客户端处理与状况为 200(指示成功的服务器访问)时的处理不同。
要使用 XmlHttprequest 对象注册 JavaScript 回调句柄 onReadyStateChangeResponse,您需要将其指定为 XmlHttpRequest onreadystate 方法 requestObject.onreadystatechange=onReadyStateChangeResponse 的值,上述方法是 XmlHttpRequest 对象公开的一个函数。
您可以随意为 JavaScript 函数 onReadyStateChangeResponse() 命名,但必须为 requestObject.onreadystatechange 赋予相同的名称。在读取返回的消息主体之前,您需要执行前面提及的检查,以确保就绪状态为 4、请求状况为 200。其余代码与前面示例中的代码相同。
|
2.
|
保存您的工作,然后运行应用程序。
注意,在此次执行时,从按下按钮到服务器响应仍存在延迟,但按钮会立即释放。
|
基本故障排除
使用 Javascript 时最常发生的问题是组件、变量名称的拼写错误以及对 DOM 组件上不存在属性的访问。您可以从互联网免费获取 JavaScript 调试器。然而,要进行迅速、随性的调试,您可以使用 alert("test"); 或 document.write("test"); 语句在客户端打印信息。在服务器端,您可以使用 Oracle JDeveloper 调试器调试所访问的 Java 代码,也可以使用 System.out.println("test");。
总结
此方法文档旨在为您提供初次使用 Oracle JDeveloper 10.1.3 进行 Ajax 编程的上机体验。正如我在介绍中提到的那样,进行 Ajax 编程的要求并不高。如果要进行更高级的 Ajax 编程,您需要对 JavaScript、CSS 和 http 消息代码进行更深入的研究。从 XmlHttpRequest 对象的观点来看,简单的对象(或 API)会对 Web 应用程序的开发产生重要的影响。由于 IDE 不需要特定的 Ajax 支持,您可以浏览互联网,查找使用 Oracle JDeveloper 进行应用程序开发时可参考的更多示例和当前 javaScript 库。
尽管构建 Ajax 应用程序涉及到的技术已经出现了很多年,但 Ajax 仍然是一种新的模式,这个领域还会有更多发展。它将导致改良客户端的出现,这些客户端最终会成为各种 Web 应用程序开发人员(包括具有 4GL 背景的开发人员)的主流客户端。
阅读有关 Oracle 和 Ajax 的更多信息
阅读并了解有关 Oracle 和 Ajax 的更多信息!请访问 Oracle 技术网 (OTN) 上的 Ajax 页面。
Frank Nimphius 是 Oracle 开发人员工具的产品经理,同时他也是一名 Oracle ACE。您可以阅读他的网志 orablogs.com/fnimphius。 |