Java Tools

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  83 随笔 :: 0 文章 :: 16 评论 :: 0 Trackbacks

#

作者:Chris Schalk

AJAX 核心基础技术的真实概述。

2006 年 4 月发布

迄今为止,您可能已经听过太多有关 AJAX 的宣传报道,而且很多产品都宣称它们支持或“兼容”AJAX。但是,很多人可能一直无法从技术角度对 AJAX 的实质进行简单、严谨的阐释。本文将摈弃所有华丽词藻,从平实的角度对构成 AJAX 的核心基础进行概述。

 

首先,AJAX 是个新事物吗?

并非如此。远程 Javascript 在最近掀起了一轮热潮。利用它,开发人员能够使用 XML 数据与服务器交互。而 AJAX 就是一种远程 Javascript。AJAX 之所以成为可能,是因为现在许多主要的浏览器都提供可进行独立 XML HTTP 请求的对象。Internet Explorer 5 以及更高版本提供了一个 XMLHTTP 对象,而基于 Mozilla 的浏览器则提供了一个 XMLHttpRequest 对象。这些对象都能够从服务器请求 XML 数据,并以类似的方式处理这些数据。所有能够动态提供 XML 的技术都可以使用服务器端 AJAX 组件。任何动态 Web 技术(从 PHP 到 Servlet)都可以充当 AJAX 服务器。

 

远程 Javascript 与 AJAX 的缺点之一是,页面作者(设计最终页面的人员)必须编写相当数量的 Javascript 代码来管理 XMLHTTP 交互。幸好,JavaServer Faces (JSF) 为此提供了一个解决方案,从而使 AJAX 更加易于使用。

Ajax Under The Hood

只有了解了 AJAX 客户端-服务器事务中涉及的核心 AJAX 体系结构后,方可进一步理解与其他技术(如 JSF)集成的更为高级的 AJAX 示例。

AJAX 目前可以提供以下两种核心技术:

  • 支持 Javascript 和支持 XMLHTTP 和 XMLHttpRequest 对象的浏览器
  • 能够以 XML 响应的 HTTP 服务器技术

因为所有流行的浏览器都支持 Javascript 和必要的 XMLHTTP 请求对象,且几乎所有 Web 服务器技术均可生成 XML(或任何标记),所以核心 AJAX 技术普遍适用。

最简单的 AJAX 应用程序实质上就是一个带有 Javascript 函数的标准 HTML 用户界面,该界面可与能动态生成 XML 的 HTTP 服务器进行交互。任何动态 Web 技术(从 CGI 到 Servlet,以及本文稍后将谈到的 JSF)都可充当服务器端 AJAX 技术。

核心 AJAX 应用程序的主要组件包括:

  • HTML 页面,其中包含:
    • 与 AJAX Javascript 函数交互的 UI 元素
    • 与 AJAX 服务器交互的 Javascript 函数
  • 可处理 HTTP 请求并以 XML 标记响应的服务器端 Web 技术。

这些元素如图 1 所示。

图 1

图 1 核心 AJAX 体系结构

了解了关键元素后,我们就可以设计一个包含输入域、按钮或任何可链接至 Javascript 的元素的 HTML 用户界面了。例如,按下按钮可激活某个 Javascript 函数,或者更深入些,在用户向输入域键入内容时可激活某个 Javascript 函数。为此,您可以将 onkeyup= 赋予 Javascript 函数的值来处理输入域中的数据。例如,当发生 onkeyup 事件(即键入内容)时,输入域“searchField”将调用 Javascript 函数 lookup( )。

<input type="text" id="searchField"
size="20" onkeyup="lookup('searchField');">

除了响应用户界面交互(例如键入)外,AJAX Javascript 函数还可根据自己的计时器进行独立操作。(可以使用该方法执行 AJAX autosave(自动保存)特性。)

如何发出 XML HTTP 请求

现在,我们来了解如何调用 AJAX Javascript 代码。请看以下 Javascript 代码,该代码可发出一个 XML HTTP 请求:

if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
req = new
ActiveXObject("Microsoft.XMLHTTP");
}   

利用该代码断,主要的浏览器(Internet Explorer 和 Mozilla/Safari)都可向服务器发出独立的 HTTP 请求。该代码首先检查浏览器是否支持上文提及的两个支持的 XMLHTTP 对象,然后对其中之一进行实例化。

一旦对 XMLHttpRequest(或 Microsoft 的 XMLHTTP)进行了实例化,即可以通过完全相同的方式对其进行操作。

要初始化到服务器的连接,需使用以下 open 方法:

req.open("GET", url, true);

第一个参数是 HTTP 方法(GET POST)。第二个参数是服务器(或使用 POST 的表单操作)的 URL;第三个参数为 true,则表明可进行异步调用(“A”代表 AJAX)。这意味着该浏览器可以在实现请求的同时继续执行其他操作。open 方法中若为 false 值,则表明为非异步处理或顺序处理。我们不建议如此,这是因为您的浏览器会在返回响应前停止操作。

使用 open 初始化连接后,可进行 onreadystatechange 调用(只适用于异步调用)。这将注册一个回调函数,一旦请求完成就会调用该函数:

req.onreadystatechange = processXMLResponse;

在完成请求后,将调用处理 XML 响应的 processXMLResponse( ) 函数。可以通过 onreadystatechange 语句以内联方式声明回调函数:

req.onreadystatechange = processXMLResponse() {
// process request
};

还可使用 req.setRequestHeader 指定任何标题内容,如:

req.setRequestHeader("Cookie", "someKey=true");

一旦完全初始化了 XMLHTTP 请求对象 (req),就可使用 send( ) 初始化对服务器的调用:

req.send(null);

对于 GET 请求,使用 null 值或空字符串“”。

POST 请求包含一个带有表单数据的字符串参数。它们也要求在请求的标题中设置 Content-Type。以下两行演示了如何执行 AJAX POST 请求:

req.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded";
req.send("name=scott&email=stiger@foocorp.com");

完成请求后调用的回调函数通常具有确保请求不会发生错误的代码。这可通过检查 readyState 以及 HTTP 请求的整体状态来实现。(readystate 为 4 表示 XMLHTTP 请求完整,而 200 表示请求成功(404 含义正好相反)。

function processXMLResponse() {
if (req.readyState == 4) {
if (request.status != 200) {
// Process the XML response
}
}
}

XML 响应的处理是通过使用标准 Javascript DOM 方法完成的。例如,要从输入的 XML 流中抽取员工姓名:

<employee>
Chris
</employee>

您可以使用以下代码:

var name = req.responseXML.getElementsByTagName("employee")[0];

分析更为复杂的 XML 会使用如下代码迭代元素:

for (i=0;i<elements.length;i++) {
for (j=0;j<elements[i].childNodes.length;j++) {
var ElementData = elements[i].childNodes[j].firstChild.nodeValue;
}
}

结合使用 XMLHttpRequest 和 HTML

请注意,通过 XMLHttpRequest 获得 XML 响应无需总是格式良好和有效。因此,AJAX 服务器端组件可以直接将 HTML 内容发送至客户端。然后,JavaScript 可使用 req.responseText 方法/属性(它只是将内容作为字符串进行检索)检索该 HTML 内容。可以使用该 HTML 字符串文本以任何方式更改页面。例如,对于以下 HTML 流:

<h2>Hello there!</h2>
<p> This is <b>HTML</b></p>

可使用以下语句检索至一个字符串中:

var HTMLcontent = req.responseText;

之后通过 id="div1" 添加至指定的 HTML DIV。

document.getElementById("div1").innerHTML += HTMLcontent;

JSF 如何支持 AJAX

JSF 及其以组件为中心的体系结构通过允许 JSF 组件全权处理 Javascript 和嵌入式 AJAX“管件”解决了 AJAX 的固有难题。JSF 页面作者甚至无需关注客户端与服务器之间的 AJAX 交互。它们只需像使用其他 JSF 组件那样使用支持 AJAX 的 JSF 组件即可,而且感觉更好。JSF 与 AJAX 的结合使用前途光明!

保持关注!

posted @ 2007-07-02 19:55 和田雨 阅读(232) | 评论 (0)编辑 收藏

Java SE 6中的JDBC 4.0增强

时间:2006-10-25
作者:Srini Penchikala
浏览次数: 5760
本文关键字:JDOJDBCSQLJJavaSrini Penchikalajdbcmustangjava se 6RowIDdriverannotation驱动程序注释
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章

   Java Platform, Standard Edition(Java SE)版本6(代码名称Mustang)现在已经推出了第二个beta版本,并计划于今年十月份交付使用。Java SE 6包括几处对Java Database ConnectivityJDBC)API的增强。这些增强将被发布为JDBC 4.0版本。新JDBC功能的主要目标是提供更为简单的设计方式和更好的开发人员体验。本文概要说明了JDBC 4.0增强,以及它们给企业Java开发人员带来的好处。我们将借助一个使用Apache Derby作为后端数据库而构建的贷款处理示例应用程序,对新的JDBC功能进行探讨。

Java SE 6.0

  Java SE 6.0版本的主要目标是提供兼容性、稳定性和高质量。这个版本中有几处有趣的增强,尤其是在监控与管理(JMX)、Web service、脚本语言支持(使用Rhino脚本引擎JSR 223将JavaScript技术与Java源代码集成在一起)、数据库连接性、注释支持和安全性方面。JDBC API中还增加了几个新功能,从新的RowId支持到更多的SQLException子类。

JDBC 4.0功能

  借助Mustang中包含的Java SE Service Provider机制,Java开发人员不再需要使用像Class.forName()这样的代码显式地加载JDBC驱动程序,就能注册JDBC驱动程序。通过在调用DriverManager.getConnection()方法时自动定位合适的驱动程序,DriverManager类可以做到这一点。这个功能是向后兼容的,所以无需修改现有的JDBC代码。

   在访问关系数据库的Java应用程序中,通过最小化我们需要编写的“模板”代码,JDBC 4.0还改善了开发人员体验。它还提供实用程序类,以改进JDBC驱动程序的注册和卸载机制,以及管理数据源和连接对象。

   借助JDBC 4.0,Java开发人员现在可以使用Annotations指定SQL查询,从而利用Java SE 5.0(Tiger)版本中提供的元数据支持。基于注释的SQL查询允许在Java代码中使用Annotation关键字指定SQL查询字符串。这样,我们就不必在两个不同文件中查看JDBC代码以及这些代码中调用的数据库查询了。例如,如果有一个叫做getActiveLoans()的方法,用于获取贷款处理数据库中的当前贷款,可以使用@Query(sql="SELECT * FROM LoanApplicationDetails WHERE LoanStatus = 'A'")注释来修饰它。

   此外,Java SE 6开发工具包(JDK 6)的最后版本——与运行时环境(JRE 6)相反——将会有一个基于与它绑定在一起的Apache Derby的数据库。这将帮助开发人员理解新的JDBC功能,而不必单独下载、安装和配置数据库产品。

   JDBC 4.0中加入的主要功能包括:

  • 自动加载JDBC驱动程序类。
  • 连接管理增强。
  • 支持RowId SQL 类型。
  • 使用Annotations的DataSet SQL实现。
  • 处理增强的SQL异常。
  • 支持SQL XML。

  还存在其他功能,比如对大对象(BLOB/CLOB)的改进支持和National Character Set Support。接下来的内容将会详细分析这些功能。

自动加载JDBC驱动程序

  在JDBC 4.0中,调用getConnection方法时,不再需要使用Class.forName()显式地加载JDBC驱动程序,因为DriverManager将会试着从初始化时加载的以及使用与当前应用程序相同的类加载器显式加载的JDBC驱动程序中,找出合适的驱动程序来。

   DriverManager方法getConnection和getDrivers已经增强为支持Java SE Service Provider机制(SPM)。根据SPM,服务被定义为一组众所周知的接口和抽象类,而服务提供程序则是服务的特定实现。它还指定在META-INF/services目录中保存服务提供程序配置文件。JDBC 4.0驱动程序必须包含文件META-INF/services/java.sql.Driver。这个文件包含JDBC驱动程序的java.sql.Driver实现的名称。例如,要加载JDBC驱动程序以连接到Apache Derby数据库,META-INF/services/java.sql.Driver文件就要包含以下项:

   org.apache.derby.jdbc.EmbeddedDriver

   让我们尽快了解如何使用这项新功能加载JDBC驱动程序管理器。下面的列表显示了加载JDBC驱动程序通常使用的示例代码。我们假定需要连接到一个Apache Derby数据库,因为我们在文章后面提到的示例应用程序中将使用这个数据库:

 Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection conn

=DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);

  但是在JDBC 4.0中,我们不需要Class.forName()这一行。我们只要调用getConnection()就可以获得数据库连接。

   注意,这仅适用于在单机模式中获得数据库连接。如果使用某种数据库连接池来管理连接,代码将会有所区别。

连接管理

  在JDBC 4.0之前,我们依赖于JDBC URL来定义数据源连接。现在有了JDBC 4.0,我们只要提供一组参数(比如主机名称和端口号)给标准的连接工厂机制,就能获得到任意数据源的连接。Connection和Statement接口中加入了新的方法,以便在管理池环境中的Statement对象时可以支持连接状态跟踪改进和更大的灵活性。元数据工具(JSR-175)用于管理活动连接。我们还可以获得元数据信息,比如活动连接的状态,还可以把连接指定为标准的(Connection,用于单机应用程序)、池化的(PooledConnection)或者甚至是用于XA事务的分布式连接(XAConnection)。注意,我们没有直接使用XAConnection。它是由诸如WebLogic、WebSphere或JBoss这样的Java EE应用服务器内部的事务管理器来使用的。

RowId支持

  RowID接口被添加到JDBC 4.0中以支持ROWID数据类型,Oracle和DB2等数据库也支持这种数据类型。当有多条记录没有惟一标识符列,而且需要在不允许复制的Collection(比如Hashtable)中保存查询输出时,RowId很有用。我们可以使用ResultSet的getRowId()方法来获得RowId,并使用PreparedStatement的setRowId()方法在查询中使用RowId。

   关于RowId对象要记住的一件重要事情是,分别在PreparedStatement和ResultSet中使用set或update方法时,RowId对象的值无法在数据源之间移植,可以认为它是特定于数据源的。所以,禁止在不同的Connection和ResultSet对象之间共享它。

   DatabaseMetaData中的getRowIdLifetime()方法可用于确定RowId对象的生存期有效性。表1中列出了返回值或行id可能取的值。

RowId 值 描述
ROWID_UNSUPPORTED 不支持ROWID数据类型。
ROWID_VALID_OTHER RowID的生存期依赖于数据库厂商实现。
ROWID_VALID_TRANSACTION 只要在数据库表中行未被删除,RowID的生存期在当前的事务中。
ROWID_VALID_SESSION 只要在数据库表中行未被删除,RowID的生存期在当前会话的持续时间中。
ROWID_VALID_FOREVER 只要在数据库表中行未被删除,RowID的生存期是无限的。

基于注释的SQL查询

  JDBC 4.0规范利用注释(Java SE 5中加入)允许开发人员把SQL查询与Java类关联在一起,同时不用编写大量的代码。此外,通过使用Generics(JSR 014)和元数据(JSR 175)API,我们可以把SQL查询与Java对象关联在一起,从而指定查询输入和输出参数。我们还可以把查询结果绑定到Java类,以加速对查询输出的处理。我们无需编写通常用于把查询结果填充到Java对象中的所有代码。在Java代码中指定SQL查询时,有2种主要的注释:Select和Update。

Select注释

  Select注释用于在Java类中指定选择查询,以便使用get方法从数据库表中获取数据。表2显示了Select注释的各种属性以及它们的用法。

名称 类型 描述
sql String SQL Select查询字符串。
value String 与sql属性相同。
tableName String 在其上调用sql的数据库表的名称。
readOnly、connected、 scrollable Boolean 标志,分别用于指示返回的DataSet是只读的还是可更新的,是否连接到后端数据库,在connected模式中使用时是否可以滚动。
allColumnsMapped Boolean 标志,用于指示sql注释元素中的列名是否一对一地映射到DataSet中的字段。

  下面是Select注释的一个例子,用于从贷款数据库获得所有当前贷款:

interface LoanAppDetailsQuery extends BaseQuery {
@Select("SELECT * FROM LoanDetais where LoanStatus = 'A'")
DataSet<LoanApplication> getAllActiveLoans();
}

  sql注释也支持I/O参数(参数标记由一个问号后面跟一个整数来表示)。下面是参数化sql查询的一个例子:

interface LoanAppDetailsQuery extends BaseQuery {
@Select(sql="SELECT * from LoanDetails
where borrowerFirstName= 1 and borrowerLastName= 2")
DataSet<LoanApplication> getLoanDetailsByBorrowerName(String borrFirstName,
String borrLastName);
}

Update注释

  Update注释用于修饰Query接口方法,用于更新数据库表中的一条或多条记录。每个Update注释都必须包含一个sql注释类型的元素。下面是Update注释的一个例子:

interface LoanAppDetailsQuery extends BaseQuery {
@Update(sql="update LoanDetails set LoanStatus = 1
where loanId = 2")
boolean updateLoanStatus(String loanStatus, int loanId);
}

处理增强的SQL异常

  异常处理是Java编程的一个重要组成部分,特别是当连接到后端关系数据库或在后端关系数据库上运行查询的时候。我们一直使用SQLException类来指示与数据库相关的错误。JDBC 4.0在SQLException处理方面有几处增强。下面是JDBC 4.0版本中的一些增强,在处理SQLExceptions时它们可以为开发人员带来更好的体验:

  • 新的SQLException子类
  • 支持因果关系
  • 支持增强的for-each循环

新的SQLException类

  JDBC 4.0中创建了SQLException的新子类,以便为Java程序员提供一种编写更多可移植错误处理代码的手段。JDBC 4.0中引入了2类新的SQLException:

  • SQL非瞬时异常
  • SQL瞬时异常

  非瞬时异常:同一项操作重试失败时抛出此异常,直到SQLException的原因得到纠正为止。表3显示了JDBC 4.0中加入的新异常类,它们都是SQLNonTransientException的子类(SQLState类值定义在SQL 2003规范中。):

异常类 SQLState值
SQLFeatureNotSupportedException 0A
SQLNonTransientConnectionException 08
SQLDataException 22
SQLIntegrityConstraintViolationException 23
SQLInvalidAuthorizationException 28
SQLSyntaxErrorException 42

  瞬时异常:当操作在没有任何应用程序级功能进行干涉的情况下重试,前面失败的JDBC操作能够成功时抛出此异常。表4中列出了对SQLTransientException进行扩展的新异常。

异常类 SQLState值
SQLTransientConnectionException 08
SQLTransactionRollbackException 40
SQLTimeoutException None

因果关系

  现在,SQLException类支持配备有异常机制(也称为Cause工具)的Java SE,这种机制让我们能够处理JDBC操作中抛出的多种异常(如果后端数据库支持多异常功能)。这种场景发生在执行一条可能抛出多个SQLException的语句时。

   我们可以使用SQLException中的getNextException()方法,通过异常链进行迭代。下面给出一些用于处理SQLException因果关系的示例代码:

catch(SQLException ex) {
while(ex != null) {
LOG.error("SQL State:" + ex.getSQLState());
LOG.error("Error Code:" + ex.getErrorCode());
LOG.error("Message:" + ex.getMessage());
Throwable t = ex.getCause();
while(t != null) {
LOG.error("Cause:" + t);
t = t.getCause();
}
ex = ex.getNextException();
}
}

增强的For-Each循环

  SQLException类实现了Iterable接口,为Java SE 5中加入的for-each循环功能提供支持。循环的导航将遍历SQLException及其原因。下面给出一个代码片段,对SQLException中加入的for-each循环进行了说明。

catch(SQLException ex) {
for(Throwable e : ex ) {
LOG.error("Error occurred: " + e);
}
}

对国家字符集转换的支持

  下面列出了处理国家字符集(National Character Set)时JDBC类中所做的增强:

  • JDBC数据类型:加入了新的JDBC数据类型,比如NCHAR、NVARCHAR、LONGNVARCHAR和NCLOB。
  • PreparedStatement:加入了新方法setNString、setNCharacterStream和setNClob。
  • CallableStatement:加入了新方法getNClob、getNString和getNCharacterStream。
  • ResultSet:接口加入了新方法updateNClob、updateNString和updateNCharacterStream。

对大对象(BLOB和CLOB)的增强支持

  下面列出了JDBC 4.0中对处理LOB所做的增强:

  • Connection:加入了新方法(createBlob()、createClob()和createNClob())以创建BLOB、CLOB和NCLOB对象的新实例。
  • PreparedStatement:加入了新方法setBlob()、setClob()和setNClob(),以便使用InputStream对象插入BLOB对象,以及使用Reader对象插入CLOB和NCLOB对象。
  • LOB:Blob、Clob和NClob接口中加入了新方法(free()),以便释放这些对象占用的资源。

  现在,让我们看一看java.sql和javax.jdbc包中加入的一些新类,以及它们提供了哪些服务。

JDBC 4.0 API:新类

RowId (java.sql)

  正如前面提过的那样,这个接口代表着数据库中的一个SQL ROWID值。ROWID是一个内置的SQL数据类型,用于识别数据库表中的特定数据行。ROWID通常用在这样的查询中:该查询从输出行没有惟一ID列的表中返回行。

   CallableStatement、PreparedStatement和ResultSet接口中的方法,比如getRowId和setRowId,允许程序员访问SQL ROWID值。接口还提供一个方法(叫做getBytes())把ROWID的值返回为字节数组。DatabaseMetaData接口有一个叫做getRowIdLifetime的新方法,可用于确定RowId对象的生存期。RowId的作用域可以是下列3种类型之一:

  • 在其中创建RowId的数据库事务的持续时间。
  • 在其中创建RowId的会话的持续时间。
  • 数据库表中的标识行,只要它尚未被删除。

DataSet (java.sql)

  DataSet接口为从执行SQL查询返回的数据提供类型安全的视图。DataSet可以在已连接或未连接模式中进行操作。当在已连接模式中使用时,其功能类似于ResultSet。而在未连接模式中使用时,DataSet的功能则类似于CachedRowSet。因为DataSet扩展了List接口,我们可以遍历查询返回的行。

   现有的类中还加入了几个新方法,比如Connection(createSQLXML、isValid)和ResultSet(getRowId)。

示例应用程序

  本文中使用的示例应用程序是一个贷款处理应用程序,它包含一个贷款查找页面,用户可以在这个页面上输入一个贷款ID以获得有关贷款的详细信息,然后提交表单。贷款查找页面调用一个控制器对象,而此控制器对象又调用DAO对象来访问后端数据库,从而获得有关贷款的详细信息。这些详细信息包括借款人姓名、贷款金额和贷款到期时间,它们均会显示在一个贷款详细信息页面上。在后端数据库中,我们使用一个叫做LoanApplicationDetails的表来保存贷款应用程序的详细信息。

   示例应用程序的用例是获得特定贷款ID的贷款详细信息。在注册贷款并针对抵押产品和利率锁定它之后,就可以获得这些贷款详细信息了。贷款处理应用程序的项目细节如表5所示。

名称
Project Name JdbcApp
Project Directory c:\dev\projects\JdbcApp
DB Directory c:\dev\dbservers\apache\derby
JDK Directory c:\dev\java\jdk_1.6.0
IDE Directory c:\dev\tools\eclipse
Database Apache Derby 10.1.2.1
JDK 6.0 (beta 2 release)
IDE Eclipse 3.1
Unit Testing JUnit 4
Build Ant 1.6.5

  下表列出了连接贷款详细信息Apache Derby数据库时需要用到的JDBC参数。这些参数都保存在一个叫做derby.properties的文本文件中,该文件位于项目基目录下的etc/jdbc目录中(参见表6)。

名称
JDBC Driver File LoanApp\META-INF\services\java.sql.driver
Driver org.apache.derby.ClientDriver
URL jdbc:derby:derbyDB
User Id user1
Password user1

  注意:Apache Derby数据库提供2类JDBC驱动程序:Embedded Driver(org.apache.derby.jdbc.EmbeddedDriver)和Client/Server Driver(org.apache.derby.jdbc.ClientDriver)。在示例应用程序中我使用的是Client/Server Driver版本。

   下面给出用于启动Derby数据库服务器和使用ij工具创建新数据库的命令。

   要启动Derby Network Server,打开一个命令提示,然后运行以下命令(修改DERBY_INSTALL和JAVA_HOME环境变量,从而影响本地环境)。

set DERBY_INSTALL=C:\dev\dbservers\db-derby-10.1.2.1-bin
set JAVA_HOME=C:\dev\java\jdk1.6.0
set DERBY_INSTALL=C:\dev\dbservers\db-derby-10.1.3.1-bin
set CLASSPATH=%CLASSPATH%;%DERBY_INSTALL%\lib\derby.jar;
%DERBY_INSTALL%\lib\derbytools.jar;
%DERBY_INSTALL%\lib\derbynet.jar;
cd %DERBY_INSTALL%\frameworks\ NetworkServer\bin
startNetworkServer.bat

  要连接到数据库服务器和创建测试数据库,打开另一个命令提示,然后运行以下命令。确保修改了DERBY_INSTALL和JAVA_HOME环境变量,以适应环境。

set JAVA_HOME=C:\dev\java\jdk1.6.0
set DERBY_INSTALL=C:\dev\dbservers\db-derby-10.1.3.1-bin
set CLASSPATH=%DERBY_INSTALL%\lib\derbyclient.jar;
%DERBY_INSTALL%\lib\derbytools.jar;.
%JAVA_HOME%\bin\java org.apache.derby.tools.ij
connect 'jdbc:derby://localhost:1527/LoanDB;create=true';

测试

  用于编译Java源代码的classpath设置应该包含位于项目主目录下lib目录中的derby.jarjunit4.jar文件。我们还需要在classpath中包含etcetc/jdbcetc/log4j目录,这样应用程序就能访问JDBC属性和Log4J配置文件。我创建了一个Ant编译脚本(位于JdbcApp/build目录中),以自动化编译和打包Java代码的任务。

   用于测试贷款详细信息数据访问对象的测试类叫做LoanAppDetailsDAOTest。我们传入参数(比如贷款ID和借款人姓名)以获得贷款详细信息。

   下面的内容给出了一些代码示例,这些代码是关于JDBC 4.0规范的JDBC驱动程序自动加载和给予注释的SQL查询功能的。

自动加载JDBC驱动程序

  BaseDAO抽象类有一个叫做getConnection的方法,用于获得一个数据库连接。下面的代码片段显示了这个方法(注意,我们不必注册JDBC驱动程序)。只要java.sql.Driver文件中存在正确的驱动程序名称(org.apache.derby.jdbc.ClientDriver),就可以自动加载JDBC驱动程序。

protected Connection getConnection() throws DAOException {
// Load JDBC properties first
if (jdbcUrl == null || jdbcUser == null ||
jdbcPassword == null) {
loadJdbcProperties();
}
// Get Connection
Connection conn = null;
try {
conn = DriverManager.getConnection(jdbcUrl, jdbcUser,
jdbcPassword);
} catch (SQLException sqle) {
throw new DAOException("Error in getting a DB connection.",
sqle);
}
return conn;
}

SQL注释

  LoanAppDetailsQuery接口有带有注释的SQL查询,用于获得当前贷款(条件是loanstatus="A")的列表和基于贷款人姓名的贷款详细信息(在一个贷款人借贷多笔款项的情况下)。我们在本文的前面部分曾见过这些SQL注释。下面给出的示例代码说明了如何调用使用Annotation定义的SQL查询。

public DataSet<LoanAppDetails> getAllActiveLoans() throws Exception {
// Get Connection
Connection conn = getConnection();
LoanAppDetailsQuery query = null;
DataSet<LoanAppDetails> loanDetails = null;
query = QueryObjectFactory.createQueryObject(
LoanAppDetailsQuery.class, conn);
loanDetails = query.getAllActiveLoans();
return loanDetails;
}
public DataSet<LoanAppDetails> getLoanDetailsByBorrowerName(
String borrFirstName, String borrLastName) throws Exception {
// Get Connection
Connection conn = getConnection();
LoanAppDetailsQuery query = null;
DataSet<LoanAppDetails> loanDetails = null;
query = QueryObjectFactory.createQueryObject(
LoanAppDetailsQuery.class, conn);
loanDetails = query.getLoanDetailsByBorrowerName(
borrFirstName,borrLastName);
return loanDetails;
}

结束语

  在使用SQL时,JDBC 4.0可以提供开发的简便性并改善开发人员体验。JDBC 4.0的另一个目标是提供企业级的JDBC功能,把API公开给涵盖范围更广的工具集,以便更好地管理JDBC资源。此外,JDBC 4.0 API为JDBC驱动程序提供了一条迁移路径,从而与J2EE Connector架构(JCA)保持兼容。这使得JDBC厂商能够继续实现JDBC技术Connector API。当在企业级面向服务架构(Service Oriented Architecture,SOA)应用程序中使用JDBC数据源时,这一点很重要,因为在企业级SOA应用程序中,可以把JDBC数据源部署为企业服务总线(Enterprise Service Bus,ESB)架构中的另一个适配器,而不必为JDBC数据源编写ESB特定实现代码。

   在本文中,我们讨论了JDBC 4.0中的增强,比如RowId支持、JDBC驱动程序加载和基于Annotations的SQL。JDBC 4.0中还将加入其他功能,以便在未来支持SQL 2003规范。要了解有关JDBC 4.0规范的更多信息,请参考规范文档。

参考资料

 作者简介
Srini Penchikala 是一位在Flagstar银行工作的信息系统学科问题专家。
posted @ 2007-07-02 19:39 和田雨 阅读(670) | 评论 (0)编辑 收藏

主要特色:
1.使用最新的JDBC3.0数据库驱动。
2.大幅度减化了JSP的反复调用JavaBean,可以直接写SQL,无须再使用连接数据库连接池。
3.将大量的工作交给JavaBean做,JSP负责页面控制。
4.最大特色是极其简单,程序编写也极其简单,非常适合初学者。
5.使用的是tomcat数据库连接池,方便快速。
请提供E_mail,为大家分享,如有高手,请指点不是。
本人E_mail:c841@163.com,望多提意见。
****************************************文件名《page.jsp》*******************************************************************
文件名《page.jsp》
<%@ page language="java" import="java.sql.*, my.*" %>
<%@ page contentType="text/html; charset=gb2312" %>
<jsp:useBean id="pagi" scope="page" class="my.Pagi"/>
<html>
<body>
<table  align="center" border=1>
<%
String CountQuery="select count(*) from 商品资料";
String query = "select * from 商品资料";
ResultSet rs = pagi.querySql(CountQuery,query, request);
String footer = pagi.PageFooter();
%>
<tr>
<td >商品编号</font></td>
<td >商品名称</font></td>
</tr>
<%
if (pagi.intPageCount>0)
{
int i=0;
while (rs.next())
{
i++;
if (i>((pagi.intPage-1)*pagi.intPageSize) &&(i<=pagi.intPage*pagi.intPageSize))
{
%>
<tr>
<td><%=rs.getString(1)%></td>
<td><%=rs.getString(2)%></td>
</tr>
<%
}
}
}
out.println("<tr><td colspan=2>"+footer+"</td></tr>");
rs.close();
pagi.close_all();
%>
</table>
</body>
</html>
****************************************文件名《pagi.java》*********************************************************
文件名《pagi.java》
package my;
import java.util.*;
import java.sql.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import my.DB.*;
public class Pagi
{
ResultSet CountTopicrs=null; //初始化总记录数Rs变量
ResultSet Pagirs=null; //初始化分页时Rs变量
public int intCountTopic=0; //主题总数
public int intPageSize;//每页显示主题数
public int intPageCount;//总页数
public int intPage=1; //当前页数
public String nowPage; // int i;
public String HttpFile;//初始化当前页intPage变量,以准确便获取当前页。 //当前的地址栏的文件
DB db; //定义Linkdb类的一个对象。
public Pagi()//定义构造器,初始化每页显示的主题数和数据库的连接。
{
intPageSize=4;  //每页显示的记录数目
db = new DB();
}
//Countsql:总记录的Query字符串。[形式为select count(*) from tablename]
//Pagisql :要分页的Query字符串。[形式为select * from tablename where ...]
//request :参数传递过程中的变量。[用来控制翻页时的pages变量]
public ResultSet querySql(String Countsql,String Pagisql,HttpServletRequest request)throws Exception
{
HttpFile=request.getRequestURI();  //获取当前文件名。
nowPage=request.getParameter("pages");  //获取当前页,将数值赋予intPage变量。[分页栏中必须要有pages参数]
if (nowPage==null)
{
intPage=1;
}
else
{
intPage=Integer.parseInt(nowPage);
if (intPage<1)
intPage=1;
}
CountTopicrs=db.executeQuery(Countsql); //@@@@@@@@@@@@获取总记录数的结果集。
if (CountTopicrs.next())
{
intCountTopic=CountTopicrs.getInt(1);
}
intPageCount = (intCountTopic+intPageSize-1)/intPageSize;  //获取总页数。
if (intPage>intPageCount)//如果当前页大于总页数,则当前页等于总页数。
{
intPage=intPageCount;
}
CountTopicrs.close();  //关闭总主题数的数据集。
db.close_all();
Pagirs=db.executeQuery(Pagisql);  //@@@@@@@@@@@@@@@获取执行分页的结果集。
return Pagirs;
}//end querySql function.
public int getCountTopic()//获取记录总数。
{
return intCountTopic;
}
public int getPageCount() //获取总页数。
{
return intPageCount;
}
public int getIntPage()  //获取当前页数。
{
return intPage;
}
public String PageFooter()
{
String str = "";
int next, prev;
prev=intPage-1;
next=intPage+1;
str += "查询到<font color=red>"+getCountTopic()+"</font>条记录"+
"    共<font color=red>"+getPageCount()+"</font>页";
str +=" 第<font color=red>"+getIntPage()+"</font>页 ";
if(intPage>1)
str += " <A href=" + HttpFile + "?pages=1"+">首页</A> ";
else
str += " 首页 ";
if(intPage>1)
str += " <A href=" + HttpFile + "?pages=" + prev + ">上一页</A> ";
else
str += " 上一页 ";
if(intPage<intPageCount)
str += " <A href=" + HttpFile + "?pages=" + next + ">下一页</A> ";
else
str += " 下一页 ";
if(intPageCount>1&&intPage!=intPageCount)
str += " <A href=" + HttpFile + "?pages=" + intPageCount +
">尾页</A>";
else
str += " 尾页 ";
return str;
}
public void close_all()
{
db.close_all();
}
}
************************************************文件名《DB.java》********************************************************
文件名《DB.java》
package my;
import java.sql.*;
import javax.naming.*;
import javax.sql.DataSource;
//一个用于查找数据源的工具类。
public class DB {
private Connection con=null;
private Statement stmt=null;
ResultSet rs=null;
public  ResultSet executeQuery(String sql) throws Exception
{
rs=null;
try
{
Context initCtx = new javax.naming.InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource)envCtx.lookup("jdbc/bn");
con=ds.getConnection();
stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
rs=stmt.executeQuery (sql);
}
catch(SQLException e){throw e;}
catch(NamingException e){throw e;}
return rs;
}
//执行Insert,Update语句
public void executeUpdate(String sql) throws Exception
{
stmt = null;
rs=null;
try
{
Context initCtx = new javax.naming.InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource)envCtx.lookup("jdbc/bn");
con=ds.getConnection();
stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
stmt.executeQuery(sql);
stmt.close();
con.close();
}
catch(SQLException ex)
{
System.err.println("执行SQL语句出错: " + ex.getMessage());
}
}
// 关闭stmt和关闭连接
public void close_all()
{
try{
stmt.close();
con.close();
}
catch(SQLException e){e.printStackTrace();}
}
}
***************************************《tomcat中的数据库连接池的设置》********************************************************************************
……
……
……
<Context path="/SQL" docBase="D:\SQL_JSP" debug="0" reloadable="true" crossContext="true">
<Resource name="jdbc/bn" auth="Container" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/bn">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=jspdev</value>
</parameter>
<parameter>
<name>username</name>
<value>cyg</value>
</parameter>
<parameter>
<name>password</name>
<value>325345353</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>20</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>20</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>-1</value>
</parameter>
</ResourceParams>
</Context>
</Host>
</Engine>
</Service>
</Server>
posted @ 2007-07-02 19:23 和田雨 阅读(938) | 评论 (0)编辑 收藏

目前所有的B/S系统应用可以分为:有状态(statefull)和无状态(stateless)两大类别。 有状态是指在整个系统的处理过程中要保留记住一些信息,而无状态则相反,每次request都是独立的连接,不需要在每个request之间共享数据等等。

对于这两种应用,通常第一考虑是性能要最优,性能是我们选择IT技术的主要依据之一。

为达到最大化的性能,对于Java系统,以前通常的作法是使用对象池,这样节约对象生成时的性能开销,也就是说系统启动时,预先生成一定数目的对象实例在内存中,需要使用时,从对象池中取出实例,用完,归还对象池,对于有状态的应用,可以使用相关持久化(persistence)策略来保存状态。

下一步,如何并行访问对象池将是非常重要,java的多线程技术为我们提供了实现可能,线程的创建销毁也是可能非常耗时的,那么,无疑象使用对象池一样,我们必须使用线程池来实现多线程并行计算的最优化。

使用线程池和对象池,每次客户端请求发生一次就从线程池中借用一个线程,处理完这个请求就将线程返回线程池,同样,使用线程快速的访问对象,对象也是从对象池中借用,用完就还回对象池。 整个这样的架构设计在性能上是最优的。

有了性能保证,安全机制、事务机制、集群(cluster)技术也将是选择IT技术的主要依据。

J2EE就是这样一个实现上述多种考量的综合标准框架系统,在具体使用中,也许我们对所有这些考量的要求并不都一样重视,比如:如果纯粹追求性能是第一,可以忽视事务机制,那么,完整的J2EE技术也许就并不适合你。

那么我们先看看J2EE是如何从性能上保证我们的应用系统以最快速度运行的,也就是说J2EE中必然应该有上述线程池和对象池的实现技术,servlet实际是基于线程池的更好的线程容器;EJB是基于对象池的更好的对象容器。

看看Servler的架构图:

 

当client1发生请求时servlet容器会从线程池中分配一个线程给这个request.


再看看EJB的架构图:



instance Pool作为一个对象实例池,维持着EJB实例,当然这个对象池是用生命周期的,简单的说 EJB=对象池+远程对象池

但是,EJB还整合了相当的其它增强功能,如安全 事务机制等,这些对于一般应用都是必需的,当然你还必须根据你的需要来选择是否使用J2EE,如果你的应用对安全 事务机制没有要求,直接使用线程池和对象池技术肯定获得最好的性能。

所以,根据Servler和EJB的原理,我们已经可以规划我们的应用,什么可以放在servlet,或什么需要放在EJB中实现:

线程的本质决定了servlet只适合一些轻量的应用,如分析简单XML文档, 通过JDBC访问数据源,使用JMS或JavaMail处理简单的信息Message,或使用JTS/JTA处理简单的事务机制,注意这些用词都是"简单"的,一旦复杂了,就要使用EJB了。

下面从客户端和服务器端两个方面来具体考量这两个技术的使用,这里的客户端不一定是指最终客户端,因为J2EE是多层结构,中间层可能在多个服务器上实现,如果一个服务器上的服务是供另外一个服务器上的应用访问的,那么后者我们也称为客户端。

根据应用的复杂程度和要求不同,分下列情况:

1.在WEB层可以实现的一些应用

如果你的系统没有很复杂的事务处理,或访问很多企业原有的资源,那么可以借助javabean这样的一些Help性质的类来实现你的应用,但是,这样的方案不是最干净clean, 最有效efficient, 或最有扩展性的scalable。

否则,将所有核心计算放置入EJB中。

2.所有的复杂商务计算核心都在EJB中完成

如果你的客户端和服务器端之间有防火墙,那么目前能够无障碍通过防火墙的协议只有Http了(Web Service也是基于http就是这个道理),既然使用http了,而Servlet是基于Http协议的,那么就需要通过servlet来访问EJB,这是我们最普遍的应用情况。

但是,如果你的客户端和服务器端可以放置在一个网络内,之间没有防火墙,那么就不必使用Servlet,直接使用Java调用RMI来访问EJB,这样性能是最好的,这时的Servlet大概只有用于控制Jsp的页面的输出了(MVC模式中的控制作用)。

如果是非java客户端,可以通过CORBA组件来访问EJB。

3.如果你的应用对速度要求很高,要求非常快,对于事务处理等方面几乎无要求

直接使用J2SE,加上线程池和对象池技术,将会使你的java系统性能发挥极致。Jakarta.Apache.org有这两种技术的源码,线程池可以从Servlet容器Tomcat的源码中发现。

posted @ 2007-07-02 19:19 和田雨 阅读(209) | 评论 (0)编辑 收藏

  1.RequestDispatcher.forward()

  是在服务器端起作用,当使用forward()时,Servlet engine传递HTTP请求从当前的Servlet or JSP到另外一个Servlet,JSP 或普通HTML文件,也即你的form提交至a.jsp,在a.jsp用到了forward()重定向至b.jsp,此时form提交的所有信息在b.jsp都可以获得,参数自动传递.

  但forward()无法重定向至有frame的jsp文件,可以重定向至有frame的html文件,同时forward()无法在后面带参数传递,比如servlet?name=frank,这样不行,可以程序内通过response.setAttribute("name",name)来传至下一个页面.

  重定向后浏览器地址栏URL不变.

  例:在servlet中进行重定向

  public void doPost(HttpServletRequest request,HttpServletResponse response)

  throws ServletException,IOException

  {

  response.setContentType("text/html; charset=gb2312");

  ServletContext sc = getServletContext();

  RequestDispatcher rd = null;

  rd = sc.getRequestDispatcher("/index.jsp");   //定向的页面

  rd.forward(request, response);

  }

  通常在servlet中使用,不在jsp中使用。

  2.response.sendRedirect()

  是在用户的浏览器端工作,sendRedirect()可以带参数传递,比如servlet?name=frank传至下个页面,同时它可以重定向至不同的主机上,sendRedirect()可以重定向有frame.的jsp文件.

  重定向后在浏览器地址栏上会出现重定向页面的URL

  例:在servlet中重定向

  public void doPost(HttpServletRequest request,HttpServletResponse response)

  throws ServletException,IOException

  {

  response.setContentType("text/html; charset=gb2312");

  response.sendRedirect("/index.jsp");

  }

  由于response是jsp页面中的隐含对象,故在jsp页面中可以用response.sendRedirect()直接实现重定位。

  注意:

  (1).使用response.sendRedirect时,前面不能有HTML输出。

  这并不是绝对的,不能有HTML输出其实是指不能有HTML被送到了浏览器。事实上现在的server都有cache机制,一般在8K(我是说JSP SERVER),这就意味着,除非你关闭了cache,或者你使用了out.flush()强制刷新,那么在使用sendRedirect之前,有少量的HTML输出也是允许的。

  (2).response.sendRedirect之后,应该紧跟一句return;

  我们已经知道response.sendRedirect是通过浏览器来做转向的,所以只有在页面处理完成后,才会有实际的动作。既然你已经要做转向了,那么后的输出还有什么意义呢?而且有可能会因为后面的输出导致转向失败。

  比较:

  (1).Request Dispatcher.forward()是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;

  (2).response.sendRedirect()则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。

  前者更加高效,在前者可以满足需要时,尽量使用RequestDispatcher.forward()方法.

  注:在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用HttpServletResponse.sendRequest()方法。

  3.<jsp:forward page="" />

  它的底层部分是由RequestDispatcher来实现的,因此它带有RequestDispatcher.forward()方法的印记。

  如果在<jsp:forward>之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么该语句将不起作用,这一点应该特别注意。

  另外要注意:它不能改变浏览器地址,刷新的话会导致重复提交

  4.修改HTTP header的Location属性来重定向

  通过设置直接修改地址栏来实现页面的重定向。
jsp文件代码如下:

  <%

  response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);

  String newLocn = "/newpath/jsa.jsp";

  response.setHeader("Location",newLocn);

  %>

  5.JSP中实现在某页面停留若干秒后,自动重定向到另一页面

  在html文件中,下面的代码:

  <meta http-equiv="refresh" content="300; url=target.jsp">

  它的含义:在5分钟之后正在浏览的页面将会自动变为target.html这一页。代码中300为刷新的延迟时间,以秒为单位。targer.html为你想转向的目标页,若为本页则为自动刷新本页。

  由上可知,可以通过setHeader来实现某页面停留若干秒后,自动重定向到另一页面。

  关键代码:

  String content=stayTime+";URL="+URL;

  response.setHeader("REFRESH",content);

  如果总结得不够全面,请各位发表自己的意见或经验。
posted @ 2007-07-02 13:38 和田雨 阅读(264) | 评论 (0)编辑 收藏

http://www.stcore.com/java/2006-11-17/1163704120d113828.html
posted @ 2007-07-02 13:34 和田雨 阅读(218) | 评论 (0)编辑 收藏

由于工作需要,最近在找一些解决方案,发现Listener是一个很好的东西, 能够监听到session,application的create,destroy,可以监听到session,application

 属性绑定的变化,考虑了一下,可以应用在"在线人数统计","数据缓存"等各个方面,

下面是整理的一些资料.



Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。当增加一个HttpSession时,就激发sessionCreated(HttpSessionEvent se)方法,这样就可以给在线人数加1。常用的监听接口有以下几个:

ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。

ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。

HttpSessionListener监听HttpSession的操作。当创建一个Session时,激发session Created(HttpSessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法。

HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。

下面我们开发一个具体的例子,这个监听器能够统计在线的人数。在ServletContext初始化和销毁时,在服务器控制台打印对应的信息。当ServletContext里的属性增加、改变、删除时,在服务器控制台打印对应的信息。

要获得以上的功能,监听器必须实现以下3个接口:

HttpSessionListener

ServletContextListener

ServletContextAttributeListener

我们看具体的代码,见示例14-9。

【程序源代码】

1 // ==================== Program Discription =====================

2 // 程序名称:示例14-9 : EncodingFilter .java

3 // 程序目的:学习使用监听器

4 // ==============================================================

5 import javax.servlet.http.*;

6 import javax.servlet.*;

7

8 public class OnLineCountListener implements HttpSessionListener,

ServletContextListener,ServletContextAttributeListener

9 {

10  private int count;

11  private ServletContext context = null;

12  

13  public OnLineCountListener()

14  {

15   count=0;

16   //setContext();

17  }

18  //创建一个session时激发

19  public void sessionCreated(HttpSessionEvent se)

20  {

21   count++;

22   setContext(se);

23   

24  }

25  //当一个session失效时激发

26  public void sessionDestroyed(HttpSessionEvent se)

27  {

28   count--;

29   setContext(se);

30  }

31  //设置context的属性,它将激发attributeReplaced或attributeAdded方法

32  public void setContext(HttpSessionEvent se)

33  {

34   se.getSession().getServletContext().
posted @ 2007-07-02 13:33 和田雨 阅读(1064) | 评论 (2)编辑 收藏

1.RequestDispatcher.forward()

是在服务器端起作用,当使用forward()时,Servlet engine传递HTTP请求从当前的Servlet or JSP到另外一个Servlet,JSP 或普通HTML文件,也即你的form提交至a.jsp,在a.jsp用到了forward()重定向至b.jsp,此时form提交的所有信息在 b.jsp都可以获得,参数自动传递.

但forward ()无法重定向至有frame的jsp文件,可以重定向至有frame的html文件,同时forward()无法在后面带参数传递,比如 servlet?name=frank,这样不行,可以程序内通过response.setAttribute("name",name)来传至下一个页面.

重定向后浏览器地址栏URL不变.

例:servlet文件中重定向
CODE

public void doPost(HttpServletRequest request,HttpServletResponse response)

       throws ServletException,IOException

{

       response.setContentType("text/html; charset=gb2312");

       ServletContext sc = getServletContext();

       RequestDispatcher rd = null;

       rd = sc.getRequestDispatcher("/index.jsp");

       rd.forward(request, response);
}


2.response.sendRedirect()

是在用户的浏览器端工作,sendRedirect()可以带参数传递,比如servlet?name=frank传至下个页面,同时它可以重定向至不同的主机上,且在浏览器地址栏上会出现重定向页面的URL.

sendRedirect()可以重定向有frame的jsp文件.

例:servlet文件中重定向
CODE

public void doPost(HttpServletRequest request,HttpServletResponse response)

       throws ServletException,IOException

{

       response.setContentType("text/html; charset=gb2312");

       response.sendRedirect("/index.jsp");

}

posted @ 2007-07-02 13:31 和田雨 阅读(236) | 评论 (0)编辑 收藏

创建型模式

1、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory

工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。

2、BUILDER—MM最爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM也可以轻松搞掂,这就是我的“我爱你”builder。(这一定比美军在伊拉克用的翻译机好卖)

建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。

3、FACTORY METHOD—请MM去麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory Method模式,带着MM到服务员那儿,说“要一个汉堡”,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。

工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

4、PROTOTYPE—跟MM用QQ聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要copy出来放到QQ里面就行了,这就是我的情话prototype了。(100块钱一份,你要不要)

原始模型模式:通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。

5、SINGLETON—俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)

单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。

结构型模式

6、ADAPTER—在朋友聚会上碰到了一个美女Sarah,从香港来的,可我不会说粤语,她不会说普通话,只好求助于我的朋友kent了,他作为我和Sarah之间的Adapter,让我和Sarah可以相互交谈了(也不知道他会不会耍我)

适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。

7、BRIDGE—早上碰到MM,要说早上好,晚上碰到MM,要说晚上好;碰到MM穿了件新衣服,要说你的衣服好漂亮哦,碰到MM新做的发型,要说你的头发好漂亮哦。不要问我“早上碰到MM新做了个发型怎么说”这种问题,自己用BRIDGE组合一下不就行了

桥梁模式:将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。

8、COMPOSITE—Mary今天过生日。“我过生日,你要送我一件礼物。”“嗯,好吧,去商店,你自己挑。”“这件T恤挺漂亮,买,这条裙子好看,买,这个包也不错,买。”“喂,买了三件了呀,我只答应送一件礼物的哦。”“什么呀,T恤加裙子加包包,正好配成一套呀,小姐,麻烦你包起来。”“……”,MM都会用Composite模式了,你会了没有?

合成模式:合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。

9、DECORATOR—Mary过完轮到Sarly过生日,还是不要叫她自己挑了,不然这个月伙食费肯定玩完,拿出我去年在华山顶上照的照片,在背面写上“最好的的礼物,就是爱你的Fita”,再到街上礼品店买了个像框(卖礼品的MM也很漂亮哦),再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装起来……,我们都是Decorator,最终都在修饰我这个人呀,怎么样,看懂了吗?

装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。
10、FACADE—我有一个专业的Nikon相机,我就喜欢自己手动调光圈、快门,这样照出来的照片才专业,但MM可不懂这些,教了半天也不会。幸好相机有Facade设计模式,把相机调整到自动档,只要对准目标按快门就行了,一切由相机自动调整,这样MM也可以用这个相机给我拍张照片了。

门面模式:外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。

11、FLYWEIGHT—每天跟MM发短信,手指都累死了,最近买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上MM的名字就可以发送了,再不用一个字一个字敲了。共享的句子就是Flyweight,MM的名字就是提取出来的外部特征,根据上下文情况使用。

享元模式:FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。

12、PROXY—跟MM在网上聊天,一开头总是“hi,你好”,“你从哪儿来呀?”“你多大了?”“身高多少呀?”这些话,真烦人,写个程序做为我的Proxy吧,凡是接收到这些话都设置好了自动的回答,接收到其他的话时再通知我回答,怎么样,酷吧。

代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。

行为模式

13、CHAIN OF RESPONSIBLEITY—晚上去上英语课,为了好开溜坐到了最后一排,哇,前面坐了好几个漂亮的MM哎,找张纸条,写上“Hi,可以做我的女朋友吗?如果不愿意请向前传”,纸条就一个接一个的传上去了,糟糕,传到第一排的MM把纸条传给老师了,听说是个老处女呀,快跑!

责任链模式:在责任链模式中,很多对象由每一个对象对其下家的引用而接

起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。

14、COMMAND—俺有一个MM家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我。这不,她弟弟又传送过来一个COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:“我同时给我姐姐三个男朋友送COMMAND,就数你最小气,才请我吃面。”,:-(

命令模式:命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。

15、INTERPRETER—俺有一个《泡MM真经》,上面有各种泡MM的攻略,比如说去吃西餐的步骤、去看电影的方法等等,跟MM约会时,只要做一个Interpreter,照着上面的脚本执行就可以了。

解释器模式:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。



16、ITERATOR—我爱上了Mary,不顾一切的向她求婚。

Mary:“想要我跟你结婚,得答应我的条件”

我:“什么条件我都答应,你说吧”

Mary:“我看上了那个一克拉的钻石”

我:“我买,我买,还有吗?”

Mary:“我看上了湖边的那栋别墅”

我:“我买,我买,还有吗?”

Mary:“你的小弟弟必须要有50cm长”

我脑袋嗡的一声,坐在椅子上,一咬牙:“我剪,我剪,还有吗?”

……

迭代子模式:迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。

17、MEDIATOR—四个MM打麻将,相互之间谁应该给谁多少钱算不清楚了,幸亏当时我在旁边,按照各自的筹码数算钱,赚了钱的从我这里拿,赔了钱的也付给我,一切就OK啦,俺得到了四个MM的电话。

调停者模式:调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。

18、MEMENTO—同时跟几个MM聊天时,一定要记清楚刚才跟MM说了些什么话,不然MM发现了会不高兴的哦,幸亏我有个备忘录,刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存,这样可以随时察看以前的记录啦。

备忘录模式:备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。

19、OBSERVER—想知道咱们公司最新MM情报吗?加入公司的MM情报邮件组就行了,tom负责搜集情报,他发现的新情报不用一个一个通知我们,直接发布给邮件组,我们作为订阅者(观察者)就可以及时收到情报啦

观察者模式:观察者模式定义了一种一队多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

20、STATE—跟MM交往时,一定要注意她的状态哦,在不同的状态时她的行为会有不同,比如你约她今天晚上去看电影,对你没兴趣的MM就会说“有事情啦”,对你不讨厌但还没喜欢上的MM就会说“好啊,不过可以带上我同事么?”,已经喜欢上你的MM就会说“几点钟?看完电影再去泡吧怎么样?”,当然你看电影过程中表现良好的话,也可以把MM的状态从不讨厌不喜欢变成喜欢哦。

状态模式:状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。
21、STRATEGY—跟不同类型的MM约会,要用不同的策略,有的请电影比较好,有的则去吃小吃效果不错,有的去海边浪漫最合适,单目的都是为了得到MM的芳心,我的追MM锦囊中有好多Strategy哦。

策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。

22、TEMPLATE METHOD——看过《如何说服女生上床》这部经典文章吗?女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八大步骤(Template method),但每个步骤针对不同的情况,都有不一样的做法,这就要看你随机应变啦(具体实现);

模板方法模式:模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。

23、VISITOR—情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一个人哪搞得清楚,还是找花店老板和礼品店老板做一下Visitor,让花店老板根据MM的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻松多了;

访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。

posted @ 2007-07-02 13:19 和田雨 阅读(214) | 评论 (0)编辑 收藏

1,前言
2,摘要
3,如何使用本文
4,Google简介
5,搜索入门
6,初阶搜索
  6.1,搜索结果要求包含两个及两个以上关键字
  6.2,搜索结果要求不包含某些特定信息
  6.3,搜索结果至少包含多个关键字中的任意一个
7,杂项语法
  7.1,通配符问题
  7.2,关键字的字母大小写
  7.3,搜索整个短语或者句子
  7.4,搜索引擎忽略的字符以及强制搜索
8,进阶搜索
  8.1,对搜索的网站进行限制
  8.2,查询某一类文件
  8.3,搜索的关键字包含在URL链接中
  8.4,搜索的关键字包含在网页标题中
  8.5,搜索的关键字包含在网页“锚”内
9,其他罕用语法
  9.1,搜索所有链接到某个URL地址的网页
  9.2,查找与某个页面结构内容相似的页面
  9.3,从Google服务器上缓存页面中查询信息
10,图片搜索
11,目录检索
12,新闻组搜索
13,Google的其他杰出功能
  13.1,网页快照
  13.2,集成化的工具条
  13.3,单词英文解释
  13.4,网页翻译
  13.5,单词纠错
  13.6,搜索结果过滤
14,Google尚未发布的一些新特性和功能
  14.1,对网页更新日期做出限定
  14.2,新闻搜索
  14.3,分类广告搜索
  14.4,其它Google的最新发展动态
  14.5,一个有趣的地方
15,后记

——————————————————————————————————

[B]1,前言[/B]

  我是在2000年上半年知道Google的。在这之前,我搜索英文信息通常用AltaVista,而搜索中文信息则常用Sina。但自使用了Google之后,它便成为我的Favorite Search engine了。这也得感谢新浪网友曹溪,因为当初正是因为他的大力推介,才使我识得了Google。

  记得1996年夏季的时候,当我第一次接触Internet,便被扑面而来的魔力征服了。那种天涯咫尺的感觉,真是妙不可言。在经历了疯狂的WWW冲浪和如痴如醉的BBS沉迷之后,我意识到Internet对我影响至深的还是在于学习方式的变迁。

  如何来描述这种变迁呢?以前的学习,一般需要预先在肚子里存储下足够的知识,必要时,就从海量的信息中提取所需的部分。这种学习方式造就了很多“才高八斗,学富五车”的大才子。但是,到了信息领域大大超出“四书五经”的新时期,预先无目的的吞下海量信息的学习方式就有些不合时宜了。比方说,我们到了大型的图书城,往往有一种不知所措的感觉。旧有的学习方式需要变更以适应这个信息爆炸的年代。目的明确的去学习,即先知道要学什么,然后有目的的去寻找答案,这种方式看上去更加有效率。我不妨把这称为“即学式”,相应的,旧有的称为“预学式”。

  不过,“即学式”的实施是有前提的。首先,要求学习者拥有一个包罗万象的信息库,以供随时抽取各种目的信息;其次,是需要一个强劲的信息检索工具,以便高效率的从信息库中提取信息。很明显,Internet可以充当那个海量的信息库,而搜索引擎,则正是寻找光明之火的绝好工具。

  “公欲善其事,必先利其器”。Internet只有一个,而搜索引擎则有N多个。有搜索高手说,所谓搜索,就是“在正确的地方使用正确的工具和正确的方法寻找正确的内容”。但是,对于普通人而言,掌握诸多搜索引擎的可能性似乎不大。用一两个相对强劲的具代表性的工具达到绝大多数搜索目的更为人们所迫切希望。不同的时期,涌现出不同的强者。就目前而言,我们非常幸运的有了: *****Google******


[B]2,摘要[/B]

  本文简要的介绍了Google的历史和特点,Google的基本搜索语法和高级搜索语法,Google的特色功能,包括图片搜索、新闻组搜索和集成工具条等。尽管本文名为“Google搜索从入门到精通”,但事实上,本文只能算是对Google的一个并不十分完全的介绍而已。:)


3,如何使用本文

  阅读本文最好具备一些最基本的布尔代数基础,如“与”、“或”、“非”等。不过,即便你没有这方面的知识,也不必在意。对那些实例进行练习,你的疑惑就会迎刃而解。对于刚刚接触网络搜索的读者而言,也许你应该从头到尾的阅读本文;但对于那些有一定搜索基础的读者而言,只需要跳跃着寻找自己所需要的信息就可以了。此外,你也可以参考中文Google大全:http://www.Google.com/intl/zh-CN/about.html,以及搜索帮助:http://www.google.com/intl/zh-CN/help.html,那是官方Google使用手册以及问题解答中心。


4,Google简介

  Google(www.Google.com)是一个搜索引擎,由两个斯坦福大学博士生Larry Page与Sergey Brin于1998年9月发明,Google Inc. 于1999年创立。2000年7月份,Google替代Inktomi成为Yahoo公司的搜索引擎,同年9月份,Google成为中国网易公司的搜索引擎。98年至今,Google已经获得30多项业界大奖。到Google的新闻中心(http://www.Google.com/press/index.html),你可以找到关于一切关于Google的历史和新闻资料。

  Google的成功得益于其强大的功能和独到的特点:

Google检索网页数量达24亿,搜索引擎中排名第一;
Google支持多达132种语言,包括简体中文和繁体中文;
Google网站只提供搜索引擎功能,没有花里胡哨的累赘;
Google速度极快,年初时据说有15000多台服务器,200多条T3级宽带;
Google的专利网页级别技术PageRank能够提供准确率极高的搜索结果;
Google智能化的“手气不错”功能,提供可能最符合要求的网站;
Google的“网页快照”功能,能从Google服务器里直接取出缓存的网页。
Google具有独到的图片搜索功能;
Google具有强大的新闻组搜索功能;
Google具有二进制文件搜索功能(PDF,DOC,SWF等);
Google还有很多尚在开发阶段的令人吃惊的设想和功能。
等等


5,搜索入门

  要用Google做搜索,当然首先要进Google网站--www.Google.com;不过,163.com和yahoo.com.cn使用的实际上也是Google搜索引擎,只是对搜索结果进行了编排,而且无法提供一些特色功能,如图片搜索等。因此,如果你要搜索网页的话,就直接使用Google.com吧。

  第一次进入Google,它会根据你的操作系统,确定语言界面。需要提醒的是,Google是通过cookie来存储页面设定的,所以,如果你的系统禁用cookie,就无法对Google界面进行个人设定了。

  Google的首页很清爽,LOGO下面,排列了四大功能模块:网站、图像、新闻组和目录服务。默认是网站搜索。现在进行第一次搜索实践,假定你是个搜索新手,想要了解一下搜索引擎的来龙去脉和搜索技巧。在搜索框内输入一个关键字“搜索引擎”, 选中“搜索中文(简体)网页”选项,然后点击下面的“Google搜索”按钮(或者直接回车),结果就出来了。 搜索:“搜索引擎”
结果:已搜索有关搜索引擎的中文(简体)网页。 共约有707,000项查询结果,这是第1-10项 。 搜索用时0.08秒。

  仔细看一下搜索结果的前十项,就会发现绝大部分链接是搜索引擎本身,而不是对搜索引擎的或者搜索技巧方面的介绍。

  注意:文章中搜索语法外面的引号仅起引用作用,不能带入搜索栏内。


6,初阶搜索

  上例是最基本的搜索,即查询包含单个关键字的信息。但是,你可以发现,上例中,单个关键字“搜索引擎”,搜索得的信息浩如烟海,而且绝大部分并不符合自己的要求,怎么办呢?我们需要进一步缩小搜索范围和结果。

6.1,搜索结果要求包含两个及两个以上关键字

  一般搜索引擎需要在多个关键字之间加上“ ”,而Google无需用明文的“ ”来表示逻辑“与”操作,只要空格就可以了。现在,我们需要了解一下搜索引擎的历史,因此期望搜得的网页上有“搜索引擎”和“历史”两个关键字。

示例:搜索所有包含关键词“搜索引擎”和“历史”的中文网页
搜索:“搜索引擎 历史”
结果:已搜索有关搜索引擎 历史的中文(简体)网页。 共约有78,600项查询结果,这是第1-10项 。 搜索用时0.36秒。

  用了两个关键字,查询结果已经从70多万项减少到7万多项。但查看一下搜索结果,发现前列的绝大部分结果还是不符合要求,大部分网页涉及的“历史”,并不是我们所需要的“搜索引擎的历史”。 怎么办呢?删除与搜索引擎不相关的“历史”。我们发现,这部分无用的资讯,总是和“文化”这个词相关的,另外一些常见词是“中国历史”、“世界历史”、“历史书籍”等。

6.2,搜索结果要求不包含某些特定信息

  Google用减号“-”表示逻辑“非”操作。“A –B”表示搜索包含A但没有B的网页。

示例:搜索所有包含“搜索引擎”和“历史”但不含“文化”、“中国历史”和“世界历史”的中文网页
搜索:“搜索引擎 历史 -文化 -中国历史 -世界历史”
结果:已搜索有关搜索引擎 历史 -文化 -中国历史 -世界历史的中文(简体)网页。 共约有36,800项查询结果,这是第1-10项 。 搜索用时0.22秒。

  我们看到,通过去掉不相关信息,搜索结果又减少了将近一半。第一个搜索结果是:

搜索引擎直通车≡搜索引擎发展历史
搜索引擎直通车, ... 搜索引擎专业介绍站点. ...
www.se-express.com/about/about.htm - 14k - 网页快照 - 类似网页

非常符合搜索要求。另外,第八项搜索结果:

463搜索王
本站检索 整个网站 在此输入关键词. 你的当前
位置:首页 >> Internet搜索手册 >> 搜索引擎的历史. ...
www.cnco.net/search/history.htm - 21k - 网页快照 - 类似网页

  也符合搜索要求。但是,10个结果只有两个符合要求,未免太少了点。不过,在没有更好的策略之前,不妨先点开一个结果看看。点开se-express.com的这个名为“搜索引擎发展历史”的网页,我们发现,搜索引擎的历史,是与互联网早期的文件检索工具“Archie”息息相关的。此外,搜索引擎似乎有个核心程序,叫“蜘蛛”,而最早成型的搜索引擎是“Lycos”,使搜索引擎深入人心的是“Yahoo”。了解了这些信息,我们就可以进一步的让搜索结果符合要求了。

  注意:这里的“ ”和“-”号,是英文字符,而不是中文字符的“+”和“-”。此外,操作符与作用的关键字之间,不能有空格。比如“搜索引擎 - 文化”,搜索引擎将视为关键字为“搜索引擎”和“文化”的逻辑“与”操作,中间的“-”被忽略。

6.3,搜索结果至少包含多个关键字中的任意一个。

  Google用大写的“OR”表示逻辑“或”操作。搜索“A OR B”,意思就是说,搜索的网页中,要么有A,要么有B,要么同时有A和B。在上例中,我们希望搜索结果中最好含有“archie”、“lycos”、“蜘蛛”等关键字中的一个或者几个,这样可以进一步的精简搜索结果。

示例:搜索如下网页,要求必须含有“搜索引擎”和“历史”,没有“文化”,可以含有以下关键字中人任何一个或者多个:“Archie”、“蜘蛛”、“Lycos”、“Yahoo”。
搜索:“搜索引擎 历史 archie OR 蜘蛛 OR lycos OR yahoo -文化”
结果:已搜索有关搜索引擎 历史 archie OR 蜘蛛 OR lycos OR yahoo -文化的中文(简体)网页。 共约有8,400项查询结果,这是第1-10项 。 搜索用时0.16秒。

  我们看到,搜索结果缩小到8千多项,前20项结果中,大部分都符合搜索要求。如果你想了解一下解搜索引擎的历史发展,就不妨研究一下现在搜索到的结果吧。 注意:“与”操作必须用大写的“OR”,而不是小写的“or”。

  在上面的例子中,我介绍了搜索引擎最基本的语法“与”“非”和“或”,这三种搜索语法Google分别用“ ”(空格)、“-”和“OR”表示。顺着上例的思路,你也可以了解到如何缩小搜索范围,迅速找到目的资讯的一般方法:目标信息一定含有的关键字(用“ ”连起来),目标信息不能含有的关键字(用“-”去掉),目标信息可能含有的关键字(用“OR”连起来)。


7,杂项语法

7.1,通配符问题

  很多搜索引擎支持通配符号,如“*”代表一连串字符,“?”代表单个字符等。Google对通配符支持有限。它目前只可以用“*”来替代单个字符,而且包含“*”必须用""引起来。比如,“"以*治国"”,表示搜索第一个为“以”,末两个为“治国”的四字短语,中间的“*”可以为任何字符。

7.2,关键字的字母大小写

  Google对英文字符大小写不敏感,“GOD”和“god”搜索的结果是一样的。

7.3,搜索整个短语或者句子

  Google的关键字可以是单词(中间没有空格),也可以是短语(中间有空格)。但是,用短语做关键字,必须加英文引号,否则空格会被当作“与”操作符。

示例:搜索关于第一次世界大战的英文信息。
搜索:“"world war I"”
结果:已向英特网搜索"world war i". 共约有937,000项查询结果,这是第1-10项 。 搜索用时0.06秒。

7.4,搜索引擎忽略的字符以及强制搜索

  Google对一些网路上出现频率极高的英文单词,如“i”、“com”、“www”等,以及一些符号如“*”、“.”等,作忽略处理。

示例:搜索关于www起源的一些历史资料。
搜索:“www的历史 internet”
结果:以下的字词因为使用过于频繁,没有被列入搜索范围: www 的. 已搜索有关www的历史 internet的中文(简体)网页。 共约有75,100项查询结果,这是第1-10项 。 搜索用时0.22秒。

  我们看到,搜索“www的历史 internet”,但搜索引擎把“www”和“的”都省略了。于是上述搜索只搜索了“历史”和“internet”。这显然不符合要求。这里我顺便说一点搜索引擎分词的知识。当我们在搜索“www的历史”的时候,搜索引擎实际上把这个短语分成三部分,“www”、“的”和“历史”分别来检索,这就是搜索引擎的分词。所以尽管你输入了连续的“www的历史”,但搜索引擎还是把这个短语当成三个关键字分别检索。

  如果要对忽略的关键字进行强制搜索,则需要在该关键字前加上明文的“+”号。
搜索:“+www +的历史 internet”
结果:已搜索有关+www +的历史 internet的中文(简体)网页。 共约有25,000项查询结果,这是第1-10项 。 搜索用时0.05秒。

  另一个强制搜索的方法是把上述的关键字用英文双引号引起来。在上例“”world war I””中,“I”其实也是忽略词,但因为被英文双引号引起来,搜索引擎就强制搜索这一特定短语。

搜索:“"www的历史" internet”
结果:已搜索有关"www的历史" internet的中文(简体)网页。 共约有7项查询结果,这是第1-6项 。 搜索用时0.26秒。

  我们看到,这一搜索事实上把“www的历史”作为完整的一个关键字。显然,包含这样一个特定短语的网页并不是很多,不过,每一项都很符合要求。

  注意:大部分常用英文符号(如问号,句号,逗号等)无法成为搜索关键字,加强制也不行。


8,进阶搜索

  上面已经探讨了Google的一些最基础搜索语法。通常而言,这些简单的搜索语法已经能解决绝大部分问题了。不过,如果想更迅速更贴切找到需要的信息,你还需要了解更多的东西。

8.1,对搜索的网站进行限制

  “site”表示搜索结果局限于某个具体网站或者网站频道,如“www.sina.com.cn”、“edu.sina.com.cn”,或者是某个域名,如“com.cn”、“com”等等。如果是要排除某网站或者域名范围内的页面,只需用“-网站/域名”。

示例:搜索中文教育科研网站(edu.cn)上关于搜索引擎技巧的页面。
搜索:“搜索引擎 技巧 site:edu.cn”
结果:已搜索有关搜索引擎 技巧 site:edu.cn的中文(简体)网页。 共约有608项查询结果,这是第1-10项 。 搜索用时0.05秒。

示例:上著名IT门户网站ZDNET和CNET搜索一下关于搜索引擎技巧方面的资讯。
搜索:“"search engine" tips site:www.zdnet.com OR site:www.cnet.com”
结果:已在www.zdnet.com内搜索有关"search engine" tips OR site:www.cnet.com的网页。 共约有1,040项查询结果,这是第1-10项 。 搜索用时0.09秒。

  注意,在这里Google有个小BUG。“已在www.zdnet.com内搜索…”,其实应该表述成“已在www.zdnet.com和www.cnet.com内搜索…”。

示例:搜索新浪科技频道中关于搜索引擎技巧的信息。
搜索:“搜索引擎 技巧 site:tech.sina.com.cn”
结果:已在tech.sina.com.cn搜索有关搜索引擎 技巧 的中文(简体)网页。 共约有163项查询结果,这是第1-10项 。 搜索用时0.07秒。

  注意:site后的冒号为英文字符,而且,冒号后不能有空格,否则,“site:”将被作为一个搜索的关键字。此外,网站域名不能有“http://”前缀,也不能有任何“/”的目录后缀;网站频道则只局限于“频道名.域名”方式,而不能是“域名/频道名”方式。

8.2,在某一类文件中查找信息

  “filetype:”是Google开发的非常强大实用的一个搜索语法。也就是说,Google不仅能搜索一般的文字页面,还能对某些二进制文档进行检索。目前,Google已经能检索微软的Office文档如.xls、.ppt、.doc,.rtf,WordPerfect文档,Lotus1-2-3文档,Adobe的.pdf文档,ShockWave的.swf文档(Flash动画)等。其中最实用的文档搜索是PDF搜索。PDF是ADOBE公司开发的电子文档格式,现在已经成为互联网的电子化出版标准。目前Google检索的PDF文档大约有2500万左右,大约占所有索引的二进制文档数量的80%。PDF文档通常是一些图文并茂的综合性文档,提供的资讯一般比较集中全面。

示例:搜索几个资产负债表的Office文档。
搜索:“资产负债表 filetype:doc OR filetype:xls OR filetype:ppt”
结果:已搜索有关资产负债表 filetype:doc OR filetype:xls OR filetype:ppt的中文(简体)网页。 共约有481项查询结果,这是第1-10项 。 搜索用时0.04秒。

  注意,下载的Office文件可能含有宏病毒,谨慎操作。

示例:搜索一些关于搜索引擎知识和技巧方面的PDF文档
搜索:?quot;search engine" tips OR tutorial filetype:pdf”
结果:已向英特网搜索"search engine" tips OR tutorial filetype:pdf. 共约有12,600项查询结果,这是第1-10项 。 搜索用时0.22秒。

  我们来看其中的一个结果:

[PDF]Search Engines Tips
文档类型: PDF/Adobe Acrobat - HTML 版
... http://www.google.com/press/zeitgeist.html See what people are searching on at Google.com
* Search Engine Watch http://searchenginewatch.com/ Some free tips ...
www.allvertical.com/PromoKits/SearchEngineTips.pdf - 类似网页

  可以看到,Google用[PDF]来标记这是一个PDF的文档检索,另外,它还给出了该PDF文档的HTML版本,该HTML版保留了文档的文字内容和结构,但没有图片。

8.3,搜索的关键字包含在URL链接中

  “inurl”语法返回的网页链接中包含第一个关键字,后面的关键字则出现在链接中或者网页文档中。有很多网站把某一类具有嗤?属性的资源名称显示在目录名称或者网页名称中,比如“MP3”、“GALLARY”等,于是,就可以用INURL语法找到这些相关资源链接,然后,用第二个关键词确定是否有某项具体资料。INURL语法和基本搜索语法的最大区别在于,前者通常能提供非常精确的专题资料。 示例:查找MIDI曲“沧海一声笑”。
搜索:“inurl:midi “沧海一声笑””
结果:已搜索有关inurl:midi "沧海一声笑"的中文(简体)网页。 共约有27项查询结果,这是第1-10项 。 搜索用时0.34秒。

  注意:“inurl:”后面不能有空格,Google也不对URL符号如“/”进行搜索。例如,Google会把“cgi-bin/phf”中的“/”当成空格处理。

  “allinurl”语法返回的网页的链接中包含所有作用关键字。这个查询的关键字只集中于网页的链接字符串。

示例:查找可能具有PHF安全漏洞的公司网站。通常这些网站的CGI-BIN目录中含有PHF脚本程序(这个脚本是不安全的),表现在链接中就是“域名/cgi-bin/phf”。
搜索:“allinurl:"cgi-bin" phf +com”
结果:已向英特网搜索allinurl:"cgi-bin" phf +com. 共约有51项查询结果,这是第1-10项 。 搜索用时0.11秒。

8.4,搜索的关键字包含在网页标题中

  “intitle”和“allintitle”的用法类似于上面的inurl和allinurl,只是后者对URL进行查询,而前者对网页的标题栏进行查询。网页标题,就是HTML标记语言title中之间的部分。网页设计的一个原则就是要把主页的关键内容用简洁的语言表示在网页标题中。因此,只查询标题栏,通常也可以找到高相关率的专题页面。 示例:查找日本明星藤原纪香的照片集。
搜索:“intitle:藤原纪香 "写真集"”
结果:已搜索有关intitle:藤原纪香 "写真集"的中文(简体)网页。 共约有315项查询结果,这是第1-10项 。 搜索用时0.15秒。

8.5,搜索的关键字包含在网页的“锚”(anchor)链点内

  所谓“锚”,就是在同一个网页中快速切换链接点。与URL和TITLE类似,Google提供了两种对anchor的检索,“inanchor”和“allincnchor”。对此不作详述。


9,其他罕用语法

9.1,搜索所有链接到某个URL地址的网页

  如果你拥有一个个人网站,估计很想知道有多少人对你的网站作了链接。而“link”语法就能让你迅速达到这个目的。

示例:搜索所有含指向华军软件园“www.newhua.com”链接的网页。
搜索:“link:www.newhua.com”
结果:搜索有链接到www.newhua.com的网页 。 共约有920项查询结果,这是第1-10项 。 搜索用时0.12秒。

  注意:“link”不能与其他语法相混合操作,所以“link:”后面即使有空格,也将被Google忽略。另外还要说明的是,link只列出Google索引链接很小一部分,而非全部,所以如果你用Google没有搜到链到你的主页的链接,也不必灰心丧气。

  除了上述功能,link语法还有其它妙用。一般说来,做友情链接的网站都有相似地方。这样,你可以通过这些友情链接,找到一大批具有相似内容的网站。比如说,你是个天文爱好者,你发现某网站非常不错,那么,可以用link语法查一下与之做链接的网站,也许可以找到更多符合你兴趣的内容。

9.2,查找与某个页面结构内容相似的页面

  “related”用来搜索结构内容方面相似的网页。例:搜索所有与中文新浪网主页相似的页面(如网易首页,搜狐首页,中华网首页等),“related:wwwsina.com.cn/index.shtml”。我到现在也不明白这个语法有什么作用,如果有谁知道,请不吝指教。预先感谢。:)

9.3,从Google服务器上缓存页面中查询信息

  “cache”用来搜索Google服务器上某页面的缓存,通常用于查找某些已经被删除的死链接网页,相当于使用普通搜索结果页面中的“网页快照”功能。

  其它罕用语法如info、stock等不一一介绍,有兴趣的读者可以参阅Google大全。


10,图片搜索

  Google自称可以检索390,000,000张图片,并称自己为“互联网上最好用的图像搜索工具”。从使用结果来看,Google的图片搜索的确不错,但个人以为比AltaVista的还是要差一些,主要体现在检索图片数量比不上AV,匹配度比AV的图片搜索器也差了些。但AltaVista国内用户无法正常访问,因此对中国用户而言,Google的图片搜索引擎已经是最好的了。

  Google首页点击“图像”链接就进入了Google的图像搜索界面“images.Google.com”。你可以在关键字栏位内输入描述图像内容的关键字,如“britney spears”,就会搜索到大量的小甜甜布兰妮的图片。我目前尚不是很清楚图片的排列标准,不过以观察来看,似乎图片文件名完全符合关键字的结果排列比较考前,然后才按照普通的页面搜索时的标准排列。

  Google给出的搜索结果具有一个直观的缩略图(THUMBNAIL),以及对该缩略图的简单描述,如图像文件名称,以及大小等。点击缩略图,页面分成两祯,上祯是图像之缩略图,以及页面链接,而下祯,则是该图像所处的页面。屏幕右上角有一个“Remove Frame”的按钮,可以把框架页面迅速切换到单祯的结果页面,非常方便。

  Google图像搜索目前支持的语法包括基本的搜索语法如“ ”、“-”、“OR”、“site”和 “filetype:”。其中“filetype:”的后缀只能是几种限定的图片类似,如JPG,GIF等。

示例:查找新浪网上本拉登的图片
搜索:“拉登 OR 拉丹 site:sina.com.cn”
结果:搜索有关 拉登 OR 拉丹 site:sina.com.cn 的图片。 共有6项查询结果,这是第1-6项。 搜索用时0.36秒。

  这里我想说明一点的是,images.google.com作为专门的图片搜索引擎,实际上有其特殊的用途。

  举个例子,互联网上本拉登的照片成千上万,但是,它们都是分散的,往往随机的分布于各种新闻报道中。如果用搜索图片库的方式(最容易想到的如“Ben Ladin photo”),来搜索本拉登的照片,显然是不恰当的,因为很少有人专门为拉登建一个在线相册。在这个时候,images.google.com就派上用场了。

  但是,如果查找的图片在网上有很多主题“gallary”,如诸多电影电视明星的照片,则明显就不适合用images.google.com来查找了。

  images.google.com对于很多报纸杂志的编辑,绝对是一个雪中送炭式的工具。比如要在某个版面上插一张专题图片,用google的图片搜索功能几秒钟就可以搞定。

  综上,可以有这样的一般性结论:如果要搜索的图片是分散的,则用google图片搜索;如果要搜索的图片通常是处于某个图片集合中的,则不适合用google图片搜索。


11,目录检索

  如果不想搜索广泛的网页,而是想寻找某些专题网站,可以访问Google的分类目录“http://directory.Google.com/”,中文目录是“http://directory.Google.com/Top/World/Chinese_Simplified/”。分类的网站目录一般由专人负责,分类明确,信息集中。因此读者应该养成这样的习惯:首先考虑所需要的信息能否在一个专门主题的网站上找到。不过需要说明的是,用目录检索,往往需要用户对查询的领域很熟悉。否则,连查询的内容属于哪个类目都不知道,目录浏览也就无从谈及了。 目前Google使用的分类目录采用了ODP的内容。“Open Directory Project”是网景公司所主持的一项大型公共网页目录。由全世界各地的义务编辑人员来审核挑选网页,并依照网页的性质及内容来分门别类。因此,在某一目录门类中进行搜索往往能有更高的命中率。另外,Google根据其专业的“网页级别”(PageRank)技术对目录中登录的网站进行了排序,可以让一般的检索更具高效率。

示例:查找一下介绍搜索引擎方面的中文网站
搜索:先进入中文简体分类目录,再进入“计算机”目录,再进入“互联网络”子目录,再进入“搜寻”子目录。我们看到在“World > Chinese Simplified > 计算机 > 互联网络 > 搜寻”下,还有两个子目录“分类目录 (33) 搜索引擎 (10)”,以及6个相关网站。显然,这些都是我们所需要的信息。

  除了用鼠标层层点入,也可以在目录中检索。比如,在上例的“互联网络”目录下,选中“只在互联网络中搜索”选项,在搜索栏内填入“搜索引擎”进行搜索。
结果:在分类Google 网页目录项中搜索搜索引擎。 共约有387项查询结果,这是第11-20项 。 搜索用时0.09秒。

  可以看到,上述查询结果比普通的检索更有效,因为在分类“互联网络”下进行搜索剔除了很多不相关的诸如新闻之类的无效信息。不过,对于中文用户而言,现在最大的问题是志愿的中文目录编辑太少,导致收录站点太少,因此搜索结果范围显得过于狭隘。但愿这个问题能随着Google以及ODP项目在国内名声的响亮而能得到改观。


12,新闻组搜索

  新闻组有详尽的分类主题,某些主题还有专人管理和编辑,具有大量的有价值信息。由于新闻组包含的信息实在是海量,因此不利用工具进行检索是不大可能的。DEJA一直是新闻组搜索引擎中的佼佼者。2001年2月份,Google将DEJA收购并提供了所有DEJA的功能。现在,除了搜索之外,Google还支持新闻组的WEB方式浏览和张贴功能。

  进入Google新闻组“http://groups.Google.com/”,你有两种信息查找方式。一种是一层层的点击进入特定主题讨论组,另一种则是直接搜索。现在,我们进行一个最简单的搜索试验,查找一下新闻组中关于山顶洞人的讨论信息。

搜索:“山顶洞人”
结果:在各群组内搜索 山顶洞人 共约有2,400项查询结果,这是第1-10项 。 搜索用时0.94秒。 搜索结果默认按照“留言内容”排列,但是你也可以点击“依照日期”按钮,让帖子按照发布日期排列。

  因为新闻组中的帖子实在是多,而且又涉及一些普通搜索所没有的语法,所以建议使用“高级群组搜寻”进入高级搜索界面。新闻组高级搜索提供留言内容、分类主题、标题、留言者、留言代码、语言和发布日期作为条件进行搜索。其中作者项指作者发帖所用的唯一识别号电子信箱。


13,Google的其他杰出功能

13.1网页快照

  网页快照是Google抓下来缓存在服务器上的网页。它有三个作用:

第一, 如果原地址打开很慢,那么可以直接查看Google缓存页面,因为Google服务器速度极快。

第二, 如果原链接已经死掉或者因为网络的原因暂时链接不通,那么可以通过Google快照看到该页面信息。当然,快照内容不是该页最新页面。

第三, 如果打开的页面信息量巨大,一下子找不到关键词所在位置,那么可以通过Google快照,因为快照中Google用黄色表明关键字位置。

13.2,集成化的工具条

  为了方便搜索者,Google提供了工具条,集成于浏览器中,用户无需打开Google主页就可以在工具条内输入关键字进行搜索。此外,工具条还提供了其他许多功能,如显示页面PageRank等。最方便的一点在于用户可以快捷的在Google主页、目录服务、新闻组搜索、高级搜索和搜索设定之间切换。欲安装Google的工具条,可以访问“http://toolbar.Google.com/”,按页面提示可以自动下载并安装。不过,Google工具条目前只支持IE5.0以上版本。

  对于经常进行网络搜索者而言,Google工具条实在是必备的东西!!

13.3,单词英文解释

  写英文文章的时候,最头疼的事情就是对某个英文单词的用法不确定。现在有了Google,一切就迎刃而解了!无论你是想查找某个生词的意思还是想了解某个单词的用法,均可使用在线词典。

  进入英文Google,输入你要查的单词。举个例子,我想查一下suggest的用法。结果如下:“Searched the web for suggest. Results 1 - 10 of about 8,000,000. Search took 0.08 seconds. ”注意看上面句子中,单词suggest下出现了一个横线,点击这个链接,就跳转到另外一个网站“http://www.dictionary.com/”,Google已经把单词提交给该网站的查询脚本。看看这个网站所提供的详尽解释吧。:)

13.4,网页翻译

  你懂英文,但是你不见得就懂德文、法文、拉丁文。如果搜索出来的页面是这些语言怎么办?呵呵,Google提供了网页翻译功能!!虽然目前只支持有限的拉丁语、法语、西班牙语、德语和葡萄牙文,但是我不得不承认,这是个杰出功能。

  试着做以下搜索:“big bang site:fr”。这个表示查找关于宇宙大爆炸的法文网页。看第一条结果:

The Big Bang Website - [ Translate this page ]
... A propos de Big Bang. Le dernier numéro en date. Les anciens numéros. Autres
activités. Concerts progressifs en France. Emissions de radio. Liens.
perso.club-internet.fr/calyx/bigbang/ - 3k - Cached - Similar pages

  有点晕。没关系,点击“Translate this page”按钮。再看结果,嗯,大致能看明白,这原来是个叫“big bang”的乐队的网站,与大爆炸无关...

  机器翻译是一个很前沿的人工智能课题,想指望翻译出来的结果跟专门用英语撰写的内容是不可能的。但西文间的互相转译比中英文机译强得多得多了。至少能看明白。

13.5,单词纠错

  笔者记忆力很差,英文单词经常拼写错误。但Google有纠错功能。比如在写上文的时候,我要用到英文单词“tutorial”,我只是依稀记得好像是“tatorial”的样子,但不肯定,于是用Google查了一下,它马上提醒:“您要找的会不会是: tutorial ”,呵呵,正是这个单词。

13.6,繁简转换

  对中文用户而言,常希望能同时检索繁体和简体信息。Google能做到这一点。Google默认使用繁简自动转换功能,因此你输入的简体关键字也将被转换成繁体做检索。这样省了不少力气。当然,如果你不希望这样的话,也可以在“使用偏好”中把这个选项关掉。

13.7,搜索结果过滤

  网络上的成人内容浩如烟海,而且很多站点具有欺骗或者其他不良企图,浏览者很容易掉入其中的陷阱。为此,Google新设立了成人内容过滤功能,见Google的设置页面,http://www.Google.com/preferences,最底下有一个选项SafeSearch Filtering。不过,中文状态下的Google尚没有这个功能。


14,Google尚未发布的一些新特性和功能

14.1,对网页更新日期做出限定“daterange:”

  评价一个搜索引擎的好坏,更新频率是一个很关键因素。通常情况下,我们总希望能找到最新的网页。Google已经开发了对更新日期做限定的搜索语法,但目前还未公布。而且比较麻烦的是,Google现在支持的日期格式为julian(凯撒日)格式,把通用日期数值切换成julian格式需要借助第三方网站:http://www.tesre.bo.cnr.it/~mauro/JD/。不过,在下面这个自称是“Google终极搜索界面”的网页上,你已经可以利用Google的这项新特性了,它自动提供日期转换功能。

Google Ultimate Interface:http://www.faganfinder.com/google.html

  Google为什么要这样做呢?也许是在测试阶段,不想让太多人使用吧。:)

14.2,新闻搜索“http://news.google.com/”

  Google的新闻搜索尚在B测试阶段,但使用起来已经非常不错了。新闻首页按头条新闻,各国新闻,以及不同领域做了分类。你可以通过Google搜索各大门户和新闻网站的新闻,简单、快捷、方便。遗憾的是,目前Google新闻只检索英文信息。

14.3,分类广告搜索“http://catalogs.google.com/”

  这也在B测试阶段。主要是对电子分类广告做检索。广告页为JPG图片格式。

14.4,其它Google的最新发展动态

  想了解Google公司的工程师们都在忙些什么吗?去看一下Google实验室(http://labs.google.com/)吧。Google的最新设想都在这个地方向访问者展现出来。现在处于发展和试验阶段的新功能有:术语查询、语音查询、键盘查询等等。

  网络工程师和程序员可以看看这个地方:http://www.google.com/apis/,我想可以让你喜出望外的。

14.5,一个有趣的地方

  想看看世界各国网民都用Google搜索什么信息么?到http://www.google.com/press/zeitgeist.html看一下就知道了。从这些资讯中,你大致可以了解到世界热点和流行时尚走向。:)


15,后记

  这个文章4.0版本与3.0版本相比,变更很大,主要把一些与Google无关的东西删除了,另外随Google的变化作了一些修正,并增加了一些Google尚未发布的新功能。关于搜索技巧和搜索实例,是各个搜索引擎共通的东西,是搜索者长期的经验积累,要写出来,是件工程很浩大的事情,因此在这个小文章中我就不献丑了。

  随着时间的推移,我发现搜索已经成为网络生活的一部分。工作需要搜索技术文档、客户信息;购物需要搜索商品信息和指南;娱乐需要搜索相关背景资料和图片。搜索已经变得无处不在,而Google则相应的成了工作和生活中的一个必备工具。套用雅虎的一句广告词,我们也许应该这样说:“今天你Google了吗?”
posted @ 2007-07-02 13:17 和田雨 阅读(5593) | 评论 (0)编辑 收藏

仅列出标题
共9页: 上一页 1 2 3 4 5 6 7 8 9 下一页