[IIS]详解DNS安装及配置多个二级域名的二种方法(图文教程)

mikel阅读(1238)

最近为了调试程序,配置了本地的DNS服务器,我们要模拟网上的域名环境,发现还有很多的朋友不太了解,所以发一个图文教程简单的介绍下DNS正向区域设置的二级域名的两种方法,如果有什么不对的地方还望网友们指正批评!谢谢!不废话了,贴图先!

第一步:windows 2003中DNS的安装:

      

1.1这个步骤要花上一点点时间,大家耐心等下,不同的机器,速度可能不太一样!

1.2按图中操作后选反DNS服务器点击下一步

1.4到这里DNS服务器就安装好了,接下来的是一个向导添加一个"正向查找区域"了

1.5这张图主要说明一下是,区域名称就是我们要设置的域名!也就是不带主机头的后面那部分了!

1.6DNS安装的机器需要有一个固定的ip地址,不能自动获取,所以我们设置一下“网络连接”将我们的ip 地址输入进去,DNS服务器首选改成本机,这个地方会被强制使用本机的DNS服务器的,因为服务就装在这台机器上!

第二步:“DNS服务器”的配置

2.1下面配置我们刚才添加的"kfoo.com"这个域的“正向查找区域”,这一步,我们为这个域添加几个主机头用来测试!

下面是创建出来的主机头

2.3创建好了主机头,我们去cmd里面去确认下,会发现,指向已经成功!

第三步:IIS站点的配置

上面我们把“默认站点”端口号“80”的站点设置到了http://www.kfoo.com/

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

上面这个要注意,站点的端口是“81”

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

我们发现,这个地方这样设置了,但是只有http://www.kfoo.com/这个可以访问,而product.kfoo.com这个域名是没法访问的!为什么呢!?原来要加上product这个站点的“81”端口号!这样和我们预想的肯定不是一回事,那怎么办呢!?解决方法有三种!!(这里谢谢“木鱼”的指证,我之前把事情弄复杂了,这个地方那么就有三种方法)按木鱼说的最简单的方法就是,把product这个站点的端口修改下,也修改成"80"端口即可!

其它的两种方法还是放在这吧,下面选讲麻烦的,再讲简单的:

第一种方法:为网卡设置多ip绑定来解决上面的问题,操作如下图!(注:这里用多ip应该还可以解决多域名泛解析的情况!)

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

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

设置好了,但是我们的DNS也要相应的更改一下了!就是把之前的指向换成我们新加入的ip地址"192.168.0.253"

 

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

IIS中"product"站点,我们也要作相应的更改,如图,我们要将站点的"81"端口设置到"80",ip分配到我们刚增加的"192.168.0.253",好了,OK!

第一种方法就是这样的,试下,是不是都可以访问了!接下来就看简单好用的第二种方法了!一张图说明问题!

第二种方法:看下图:

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

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

按第二种方法设置的话,设置好hosts文件之后,我们的DNS中设置的主机头都指向到一个ip就可以了!IIS中的设置也比较简单,所有的站点都用80的端口,主机头就按照hosts文件和DNS中设置的配置就可以了,

[Web]Web OS雏形—Opera Unite初体验 从 博客园新闻频道

mikel阅读(850)

     最近,Opera公司发布了自己的新产品Opera 10,它最大的特色是引入了一个新的技术Opera Unite。

      Opera Unite 一种在线协作技术,允许您使用电脑直接与他人共享您的数据 – 如文件、照片或者音乐。Opera Unite 技术基于 Opera 浏览器中简单而精密的服务器程序实现共享数据和服务等功能。

     使用 Opera Unite,您不再需要花费时间上传您需要共享的内容。直接共享自己硬盘上的内容,而不需要第三方共享服务器。

  Opera Unite 彻底的扩大了您的线上活动范围。Opera Unite 借力于当今先进的硬件和流畅的网络连接,赋予所有人定义网络未来面貌的能力。

  Opera Unite 服务

  Opera Unite 服务使您可以扩展您浏览器的功能以共享文件。这些服务范围广泛,从发布信息/聊天的社会性网络工具到文件、照片和音乐共享。用它可以快捷的与朋友共享内容 – 无需上传 – 而别人可以直接访问您的开放的那部分硬盘。
一、下载Opera Unite

下载地址:http://unite.opera.com/

      

二、配置个性化主页

进入浏览器,首先要注册自己的Opera账号

注册后,它就会让你输入个性化计算机名,也就相当于Opera中的个人主页

以我自己的为例:

登陆后,会出现一个侧边栏:

你可以看到Opera Unite目前已经提供了File Sharing(文件共享)、Fridge(留言板)、Media Player(媒体播放器)、Photo Sharing(照片共享)、The Lounge(聊天室)和Web Server(网络服务器)等六项功能。

以Fridge(留言板)为例,我们启动留言板服务,然后ADD Note:

马上就去考六级了,今天就先介绍到这,大家发现什么新的东西要来分享哦!

[MVC]一个基于Asp.Net MVC的权限方案

mikel阅读(870)

    最近这段时间博客园有几位同学在探讨通用的权限方案,偶闲来无事,也来凑凑热闹,下面简单说一下我的简单解决方案,基于AOP的。由于使用了ASP.NET MVC 开发,可能需要先对MVC有些了解,思路都是差不多的。

1.数据结构

Mad_Popedom为权限表,Control记录控制器名,Action记录动作名。
Mad_Role为角色表。

2.权限控制的实现
此处使用比较简单AOP方式,用MVC的Filter实现,代码如下

Code

解释一下,上面的代码就是在执行前,先获取登录用户可以运行的Controller-Action,然后和当前需要执行的Controller-Action比较,如存在,即通过,否则为没有权限执行。

3.为动作添加权限
为简单起见,对于Controller层我是独立出来一个类库的,好处是等会为角色添加权限的时候我们不需要手动输入,只要反射dll就可以了。

如图所示,凡需要权限控制的函数,只需要添加[SupportFilter]特性就可以了,当然这种方式只能控制到Action级。

4.为角色额添加权限
这个比较简单,只需要把角色和权限关联起来就可以了,这里我是用反射Controller层dll实现。
Web.config

Global.asax.cs

Madnet.Controllers.Test即为Controller层的dll

5.结束
上面4步即已完成基本的权限控制。可以在此基础上加上用户组,用户,菜单等管理,可实现”用户-角色-权限”的自由组合,一个简单的通用后台大概就是这样了。


—————————————————————————————-
文章发表于:http://www.madcn.net/?p=454

[Flex]ActionScript 3网站构建框架

mikel阅读(893)

开发基于RIA的网站有很多种方法。对于和多媒体内容息息相关的业务和个人来说,Flash形式的网站尤其动人。Fosfr是一个ActionScript 3网站构建框架,专门用来创建Flash网站。InfoQ采访了Fosfr的创始人——Jeff DePascale,以深入了解Fosfr。 

Q. 是什么驱使你开始开发这个Fosfr框架的? 

A. 我大部分工作都跟小型网站开发相关。Fosfr最早是为了保证各网站的版本能保持一致。最初,AS2中有组特别的类严格控制站点的构建,Fosfr作为 AS3框架主要是以前面提到的那个类库为基础来扩展,给我所有的Flash构建——无论是小型网站,还是独立的SWF,或者是其它项目——提供了稳定、一 致的基础。 

Q. 你为什么觉得会有AS3(或者说Flash)网站的需求? 

A. 目前有两种对立的看法,一部分认为Flash有益于互联网的发展,另一部分人认为Flash只是让整个网络充斥着用户体验很烂而又无法被检索到的网站。就 我个人认为,每个技术都有各自发展的天地,非要说某种技术在像互联网这样迥异的媒体中比另一种技术更适合,未免有些误导。Flash有缺点吗?当然 有,SEO方面就是其中一个非常大的缺点。Flash有没有被用到一些不合适的场合?当然也有。但是,如果能有效应用它的长处的话,Flash能提供强大 的富用户体验, 

Q. 你能概括下Fosfr的基本构架吗? 

A. Fosfr的整体实现是一个三层SWF结构。一个是核心层,或者说是主SWF。这个核心层包含了预加载器,可以看作是项目的宿体。核心层之上是shell SWF,这里包含了所有通用的网站元素,诸如导航栏、脚注等等。最后,那些可变内容则放在子SWF文件中。 

Fosfr的优点还在于它有用于生成文档的类库。Fosfr提供自定义文档类,所有.as文件都能得到扩展(包括外部类);它提供直至自动生成文档 这个层次的自定义方法,这些方法可以是为了调试、跟踪、导航,也可以是为了访问Fosfr的其它控件,比方说cookies、url信息等等。项目的任何 一个地方,你都能直接索引到fosfr对象,快速访问到框架的任何一个方面,可以访问到加载在项目中的所有SWF。 

整个项目由一个外部XML配置文件来驱动,根据这个配置文件,能构从该xml文件本身直接访问Fosfr主要控件的所有属性。借助于自动生成文档的 类库的后台工作,只需要在每个.as文件中添加几行简单的代码就能实例化整个框架。只要几分钟,你就能得到可以立刻运行的一个功能完善的网站了。 

Fosfr还能和Prequel集成使用,Prequel是我开发的一个预加载API;Fosfr还能集成SWFAddress,完全自动完成,不需要任何手动处理。通过Fosfr创建文档的类库来开发结合SWFAddress的子SWF的自定义功能会非常容易。 

另外,如果你只需要一个SWF文件和一个对应的预加载器,那么可以只实现Fosfr的核心文件和shell文件,可以省去其中的导航 /SWFAddress功能;或者通过框架中的FosfrLite创建一个独立的SWF。FosfrLite也可以选择使用XML配置文件。 

Q. Fosfr能和已有的CMS甚至诸如Wordpress这样的日志平台集成吗? 

A. Fosfr的XML配置文件包含了一个专门针对自定义网站元素的结点。CMS或XML编辑插件直接与这部分xml配置交互的话,能够很容易操作在 Fosfr上创建的任何SWF文件的各个方面。目前还没有给Wordpress及类似平台专门开发插件的计划,但我会在以后的开发中实现此类集成。 

Q. 开发Fosfr,你用的是什么开发工具?还有,Fosfr和Flex有关吗?要是没有,以后会把这两者结合起来吗? 

A. 开发Fosfr,我用的是FlashDevelop,这也是这段日子以来一直在用的开发工具。在调试方面,我结合采用了集成在Fosfr当中自定义调试器和Flash播放器的标准调试器。目前我还没有任何计划要把Fosfr集成到Flex当中的计划。 

Q. 你对Fosfr的前景有何规划? 

A. 目前,Fosfr的版本上处于0.8。在推出1.0版本之前,我计划完成处理自定义事件和事件提醒的系统,在调试器上再多加一些功能,而且希望到时候还能 集成我正在抓紧开发的、更新、更强壮的Prequel版本。处于开发阶段、尚未结合在公共发布当中的模块还有tab管理和音频管理。我还计划开发另外的文 档管理类库来捆绑papervision3D站点的创建。1.0及其之后的版本将囊括这些特性,而且会不断添加新功能。就眼前来说,更重要的是确定什么是 目前要完成的,要编写快速入门指南,最好还要创建一个AIR应用把XML配置文件转变为向导。我希望开发人员能在半个小时以内就能轻松掌握Fosfr,而 且我觉得Fosfr能大幅度缩短产品的开发周期,这无疑是它的一大优势。但是如果没有快速入门指南和向导的话,这个优势也很难实现。Fosfr非常有用, 能够极大地缩短开发周期,但前提是你要懂得怎么去使用这个工具。我在不了解如何使用某个API的前提下直接去用这个API,还确实遇到过很多问题。 Fosfr在1.0之后就不会有这些问题。所以编写指南是目前最迫切的一件事。之后,我会发布完全值得信赖的1.0版本,会尝试让公众关注到这个项目,目 前我有意识地尽量把关注度控制到最小。 

Q. 为什么要把这个开发框架叫作“Fosfr”? 

A. 从技术上来说,它的全称是“Flash Open Source Framework”。然而,由于之前SWFObject和SWFFit因为名字当中有“Flash”这个词,在注册商标的时候遇到很多问题,所以现在严 格采用Fosfr。另外,这个名字厅听上去也很酷。 

InfoQ会关注并且追踪报道Fosfr的开发进度。

查看英文原文:ActionScript 3 Site Framework – Fosfr

[Lucene]Lucene.net 系列四 --- index 下

mikel阅读(896)

本文将介绍有关索引并发控制的问题,以结束对Lucene.net建立索引问题的讨论.
1. 允许任意多的读操作并发.即可以有任意多的用户在同一时间对同一份索引做查询工作.
2. 允许任意多的读操作在索引被正在被修改的时候进行.即哪怕索引正在被优化,添加删除文档,这时也是允许用户对索引进行查询工作. (it’s so cool.)
3. 同一时间只允许一个对索引修改的操作.即同一时间只允许IndexWriter或IndexReader打开同一份索引.不能允许两个同时打开一份索引.
Lucene提供了几种对索引进行读写的操作.添加文档到索引,从索引中删除文档,优化索引,合并Segments.这些都是对索引进行写操作的方法. 查询的时候就会读取索引的内容.
有关索引并发的问题是一个比较重要的问题,而且是Lucene的初学者容易忽略的问题,当索引被破坏,或者程序突然出现异常的时候初学者往往不知道是自己的误操作造成的.
下面让我们看看Lucene是如何处理索引文件的并发控制的.
首先记住一下三点准则:
1. 允许任意多的读操作并发.即可以有任意多的用户在同一时间对同一份索引做查询工作.
2. 允许任意多的读操作在索引被正在被修改的时候进行.即哪怕索引正在被优化,添加删除文档,这时也是允许用户对索引进行查询工作. (it’s so cool.)
3. 同一时间只允许一个对索引修改的操作.即同一时间只允许IndexWriter或IndexReader打开同一份索引.不能允许两个同时打开一份索引.
第一个准则很容易理解,第二个准则说明Lucene对并发的操作支持还是不错的.第三个准则也很正常,不过需要 注意的是第三个准则只是表明IndexWriter和IndexReader不能并存,而没有反对在多线程中利用同一个IndexWriter对索引进行 修改.这个功能可是经常用到的,所以不要以为它是不允许的.不过这个时候的并发就需要你自己加以控制,以免出现冲突.
(注: 在前面的系列中已说过IndexReader不是对Index进行读操作,而是从索引中删除docuemnt时使用的对象)
有关这三个原则在实际使用Lucene API时候的体现,让我们先看看下面这张表:
表中列出了有关索引的主要读写操作.其中空白处表示X轴的操作和Y轴的操作允许并发.
而X处表明X轴的操作和Y轴的操作不允许同时进行.
比如Add document到索引的时候不允许同时从索引中删除document.
其实以上这张表就是前面三个准则的体现.Add Optimize Merge操作都是由IndexWriter来做的.而Delete则是通过IndexReader完成.所以表中空白处正是第一条和第二条准则的体现,而X(冲突)处正是第三个原则的具体表现.
为了在不了解并发控制的情况下对Lucene API的乱用. Lucene提供了基于文件的锁机制以确保索引文件不会被破坏.
当你对index 进行修改的时候, 比如添加删除文档的时候就会产生 ***write.lock文件,而当你从segment进行读取信息或者合并segments的时候就会产生***commit.lock文件.在默认 情况下,这些文件是放在系统临时文件夹下的. 简而言之, write.lock文件存在的时间比较长,也就是对index进行修改的锁时间比较长,而commit.lock存在的时间往往很短.具体情况见下表.
如果索引存在于server, 很多clients想访问的时候,自然希望能看到其他用户的锁文件,这时把锁文件放到系统临时文件夹就不好了.此时可以通过配置文件来改变锁文件存放的位置.
比如在一个ASP.NET的应用下,你就可以象下面这样利用web.config文件来实现你的目的.
<configuration>
    <appSettings>
        <add key="Lucene.Net.lockdir" value="c:yourdir" />
    </appSettings>
</configuration>
不仅如此,在某些情况下比如你的索引文件存放在一个CD-ROM中,这时根本就无法对索引进行修改,也就不存在所谓的并发冲突,这种情况下你甚至可以讲锁文件的机制取消掉.同样通过配置文件.
<configuration>
    <appSettings>
        <add key="disableLuceneLocks" value="true" />
    </appSettings>
</configuration>
不过请注意不要乱用此功能,不然你的索引文件将不再受到安全的保护.
下面用一个例子说明锁机制的体现.
using System;
using System.IO;
using Lucene.Net.Analysis;
using Lucene.Net.Index;
using Lucene.Net.Store;
using NUnit.Framework;
using Directory = Lucene.Net.Store.Directory;
[TestFixture]
public class LockTest
{
private Directory dir;
[SetUp]
public void Init()
{
String indexDir = "index";
dir = FSDirectory.GetDirectory(indexDir, true);
}
[Test]
[ExpectedException(typeof(IOException))]
public void WriteLock()
{
IndexWriter writer1 = null;
IndexWriter writer2 = null;
try
{
   writer1 = new IndexWriter(dir, new SimpleAnalyzer(), true);
   writer2 = new IndexWriter(dir, new SimpleAnalyzer(), true);
  
}
catch (IOException e)
{
   Console.Out.WriteLine(e.StackTrace);
}
finally
{
   writer1.Close();
   Assert.IsNull(writer2);
}
}
[Test]
public void CommitLock()
{
IndexReader reader1 = null;
IndexReader reader2 = null;
try
{
   IndexWriter writer = new IndexWriter(dir, new SimpleAnalyzer(),
                                        true);
   writer.Close();
   reader1 = IndexReader.Open(dir);
   reader2 = IndexReader.Open(dir);
}
finally
{
   reader1.Close();
   reader2.Close();
}
}
}
不过很令人失望的是在Lucene(Java)中应该收到的异常在dotLucene(1.4.3)我却没有捕获到.随后我在dotLucene的论坛上问了一下,至今尚未有解答.这也是开源项目的无奈了吧.

[Lucene]并发性、线程安全性以及锁机制

mikel阅读(912)

2.9  并发性、线程安全性以及锁机制

这部分内容 将介绍三个紧密联系的主题:索引文件的并发访问、IndexReader和IndexWriter的线程安全性,以及Lucene用于避免索引被破坏而使 用的锁机制。通常,Lucene的初学者们对这几个主题都存在一定的误解。而准确地理解这些内容是十分重要的,因为,当索引应用程序同时服务于大量不同的 用户时,或为了满足一些突发性的请求、而需要通过对某些操作进行并行处理时,这些内容会帮助你消除在构建应用程序过程中所遇到的疑问。

2.9.1  并发访问的规则

Lucene 提供了一些修改索引的方法,例如索引新文档、更新文档和删除文档;在执行这些操作时,为了避免对索引文件造成损坏,需要遵循一些特定的规则。这类问题通常 会在web应用程序中突显出来。因为web应用程序是同时为多个请求而服务的。Lucene的并发性规则虽然比较简单,但我们必须严格遵守:

— 任意数量的只读操作都可以同时执行。例如,多个线程或进程可以并行地对同一个索引进行搜索。

— 在索引正在被修改时,我们也可以同时执行任意数量的只读操作。例如,当某个索引文件正在被优化,或正在对索引执行文档的添加、更新或删除操作时,用户仍然可以对这个索引进行搜索。

— 在某一时刻,只允许执行一个修改索引的操作。也就是说,在同一时间,一个索引文件只能被一个IndexWriter或IndexReader对象打开。

基于以上的并发性规则,我们可以构造一些关于并发性的更全面的例子,如表2.2中所示。表中说明了是否允许我们对一个索引文件进行各种并发性的操作。

表2.2  是否允许对某个Lucene索引进行并发性操作的举例

   

是否允许

对同一个索引运行多个并行的搜索进程

允许

对一个正在生成、被优化或正在与另一索引合并的索引运行多个并行的搜索进程,或该索引正在进行删除、更新文档等操作时,对索引运行多个并行的搜索进程

允许

对同一个索引用多个IndexWriter对象执行添加、更新文档的操作

不允许

当一个从索引中删除文档的IndexReader对象没有成功关闭时,打开一个IndexWriter对象用于在这个索引中添加新的文档

不允许

IndexWriter对象向索引中添加新文档后,未成功关闭;在此之后,打开一个IndexReader对象用于从这个索引中删除文档

不允许

注:当正在修改一个索引时,请记住在某一时刻,在同一个索引上只能执行一个修改操作。

2.9.2  线程安全性

尽管 Lucene不允许使用多个IndexWriter或IndexReader实例同时对一个索引进行修改,如表2.2所示,但是这两个类都是线程安全 (thread-safe)的,了解这一点相当重要。因此,这两个类的实例都可以被多线程共享,Lucene会对各个线程中所有对索引进行修改的方法的调 用进行恰当的同步处理,以此来确保修改操作能一个接着一个地有序进行。图2.7描述了这样的一个场景:

图2.7  一个IndexWriter或IndexReader对象可以被多个线程所共享

应用程序不 需要进行额外的同步处理。尽管IndexReader和IndexWriter这两个类都是线程安全的,使用Lucene的应用程序还是必须确保这两个类 的对象对索引的修改操作不能重叠。也就是说,在使用IndexWriter对象将新文档被添加至索引中之前,必须关闭所有已经完成在同一个索引上,进行删 除操作的IndexReader实例。同样地,在IndexReader对象对索引中的文档进行删除和更新之前,必须关闭此前已经打开该索引的 IndexWriter实例。

表2.3是 一个关于并发操作的矩阵,它向我们展示了一些具体操作是否能并发地执行。该表假定应用程序只使用了一个IndexWriter或IndexReader实 例。请注意,在此我们并没有将对索引的更新视为一个单独的操作列出,因为它实际上可以被看成是在删除操作后再进行一个添加操作。

表2.3  使用同一个IndexWriter或IndexReader实例时的并发操作矩阵,表中打叉的部分表示两个操作不能同时执行

 

查找

读文档

添加

删除

优化

合并

查找

 

 

 

 

 

 

读文档

 

 

 

 

 

 

添加

 

 

 

×

 

 

删除

 

 

×

 

×

×

优化

 

 

 

×

 

 

合并

 

 

 

×

 

 

这个矩阵可以归纳为:

—  IndexReader对象在从索引中删除一个文档时,IndexWriter对象不能向其中添加文档。

—  IndexWriter对象在对索引进行优化时,IndexReader对象不能从其中删除文档。

—  IndexWriter对象在对索引进行合并时,IndexReader对象也不能从其中删除文档。

从上面的矩 阵及其归纳中,我们可以得到这样一个使用模式:当IndexWriter对象在对索引进行修改操作时,IndexReader对象不能对索引进行修改。这 个操作模式是对称的:当IndexReader对象正在对索引进行修改操作时,IndexWriter对象同样也不能对索引进行修改。

这里读者可 以感到,Lucene的并发性规则和社会中的那些良好的习惯以及合理的法规具有相通之处。我们不一定非得严格地遵守这些规则,但是如果违反这些规则将会造 成相应的后果。在现实生活中,违反法律法规也许得锒铛入狱。在使用Lucene时,违背这些规则,则会损坏你的索引文件。Lucene使用者可能会对并发 性有错误的理解甚至误用,但Lucene的创造者们对此早已有所预料,因此他们通过锁机制尽可能地避免应用程序对索引造成意外的损坏。本书将在2.9.3 节中对Lucene索引的锁机制进行进一步的介绍。

2.9.3  索引锁机制

在 Lucene中,锁机制是与并发性相关的一个主题。在同一时刻只允许执行单一进程的所有代码段中,Lucene都创建了基于文件的锁,以此来避免误用 Lucene 的API造成对索引的损坏。各个索引都有其自身的锁文件集;在默认的情况下,所有的锁文件都会被创建在计算机的临时目录中,这个目录由Java的 java.io.tmpdir中的系统属性所指定。

如果在索引 文档时,观察一下那个临时目录,就可以看到Lucene的write.lock文件;在段(segment)进行合并时,还可以看到 commit.lock文件。你可以通过设定org.apache.lucene.lockDir中的系统属性,使锁文件存放的目录改至指定的位置。这个 系统属性可以通过使用Java API在程序中进行设定,还可以通过命令行进行设定,如:-Dorg.apache.lucene.lockDir=/path/to/lock /dir。若有多台计算机需要访问存储在共享磁盘中的同一个索引,则应该在程序中显式地设定锁目录,这样位于不同计算机上的应用程序才能访问到彼此的锁文 件。根据已知的锁文件以及网络文件系统(NFS)出现的问题,锁目录应该选择放在一个不依赖于网络的文件系统卷上。以下就是上面提到的两个锁文件:

write.lock 文件用于阻止进程试图并发地修改一个索引。更精确地说,IndexWriter对象在实例化时获得write.lock文件,直到IndexWriter 对象关闭之后才释放。当IndexReader对象在删除、恢复删除文档或设定域规范时,也需要获得这个文件。因此,write.lock会在对索引进行 写操作时长时间地锁定索引。

当对段进行 读或合并操作时,就需要用到commit.lock文件。在IndexReader对象读取段文件之前会获取commit.lock文件,在这个锁文件中 对所有的索引段进行了命名,只有当IndexReader对象已经打开并读取完所有的段后,Lucene才会释放这个锁文件。IndexWriter对象 在创建新的段之前,也需要获得commit.lock文件,并一直对其进行维护,直至该对象执行诸如段合并等操作,并将无用的索引文件移除完毕之后才释 放。因此,commit.lock的创建可能比write.lock更为频繁,但commit.lock决不能过长时间地锁定索引,因为在这个锁文件生存 期内,索引文件都只能被打开或删除,并且只有一小部分的段文件被写入磁盘里。表2.4对Lucene 中各种使用Lucene API来锁定索引的情况进行了概括。

表2.4  Lucene中所有锁及创建和释放锁的操作

锁文件

何时获取

何时释放

描述

write.lock

IndexWriter

构造函数

close()

在关闭IndexWriter对象时释放锁

write.lock

IndexReader

delete(int)

close()

在关闭IndexReader对象时释放锁

write.lock

IndexReader

undeleteAll(int)

close()

在关闭IndexReader对象时释放锁

write.lock

IndexReader

setNorms (int,String,byte)

close()

在关闭IndexReader对象时释放锁

commit.lock

IndexWriter

构造函数

构造函数

段信息被读取或写入后立即释放锁

commit.lock

IndexWriter

addIndexes (IndexReader[])

addIndexes (IndexReader[])

写入新的段时获取锁文件

commit.lock

IndexWriter

addIndexes (Directory[])

addIndexes (Directory[])

写入新的段时获取锁文件

commit.lock

IndexWriter

mergeSegment (int)

mergeSegments (int))

写入新的段时获取锁文件

commit.lock

IndexReader

open(Direcory)

Open(Direcory)

所有段被读取后获取锁文件

commit.lock

SegmentReader

doClose()

doClose()

段的文件被写入或重写后获取锁文件

commit.lock

SegmentReader

undeleteAll()

undeleteAll()

移除段.del文件后获取锁文件

请注意另外两个与锁相关的方法:

—  IndexReader的isLocked(Directory) ——这个方法可以判断参数中指定的索引是否已经被上锁。在想要对索引进行某种修改操作之前,应用程序需要检查索引是否被锁保护时,通过使用这个方法可以很方便地得到结果。

—  IndexReader的unlock(Directory) ——该方法的作用正如其命名那样。尽管通过这个方法可以使你在任意时刻对任意的Lucene索引进行解锁,然而它的使用具有一定的危险性。因为 Lucene创建锁自有其理由,此外,在修改一个索引时对其解锁可能导致这个索引被损坏,从而使得这个索引失效。

虽然知 道Lucene使用了哪些锁文件,何时、为什么要使用它们,以及在文件系统的何处存放这些锁文件,但是你不能直接在文件系统对它们进行操作。你应该通过 Lucene的API对它们进行操作。否则,如果将来Lucene开始启用一种不同的锁机制,或者Lucene改变了锁文件的命名或存储位置时,应用程序 可能会受到影响而不能顺利执行。

锁机制的实例

为了演示锁是如何使用的,程序2.7演示了Lucene如何利用锁来避免在同一时刻对同一索引文件进行多个修改操作。在testWriteLock( )方法中,Lucene对一个已经被IndexWriter对象打开的索引上锁,阻止第二个IndexWriter对象对这个索引进行修改。在这个例子中使用了write.lock文件:

程序2.7  使用基于文件的锁以防止索引被损坏

testCommitLock( )方法展示了应用程序是如何使用commit.lock文件,程序通过IndexReader的open(Directory)方法获得这个锁文件,并在 读取了所有的索引段之后就通过同样的方式立即释放它。因为程序是通过与获得锁文件相同的方法释放的。因此,甚至在关闭第一个IndexReader对象之 前,我们仍可以用第二个IndexReader对象来访问同一个目录。(你可能对这个方法中的IndexWriter对象感到诧异:它的惟一目的在于通过 创建程序所需的段文件,这个段文件包含了已经存在的所有索引段的信息。若没有这些段文件,IndexReader对象就会成为无的之矢,因为那样的话,它 就不知道该从索引目录中读取哪些段的信息了)。

当运行这段代码时,可以看到已被上锁的索引造成了类似如下异常的堆栈跟踪信息:

如同我们先 前提到的,Lucene的初学者们有时对这一章中介绍的并发性没有很好理解,从而陷入到本小节中提到的关于锁的问题里,以至在程序中出现了上面所示的异 常。在你的应用程序中如果出现了类似的异常,而索引的一致性对用户而言又十分重要,那么请不要漠视这些异常。与锁相关的异常通常是误用了Lucene API的一个标志;若在应用程序中出现了这种异常,应该妥善地处理它们。

2.9.4  禁用索引锁

我们强烈地 建议读者不要对Lucene的锁机制进行随意修改,不要漠视与锁相关的异常。然而在一些情况下,你也许想禁用Lucene当中的锁机制,并且这样做不会破 坏索引文件。例如,应用程序可能需要访问存储在CD-ROM上的Lucene索引。因为CD是一种只读介质,这意味着应用程序对索引的操作也是只读模式 的。换句话说,该应用程序只使用Lucene来搜索索引而不需要对索引进行任何形式的修改。尽管Lucene已经将锁文件保存在系统的临时目录(这个目录 通常可以被系统的所有用户打开以用于写操作)中,但是你仍可以通过将disableLuceneLocks这个系统属性设定为“true”,从而禁用 write.lock和commit.lock文件。

[MVC]MVC模式结合Mediator模式的运用

mikel阅读(926)

Mediator模式有一种本事,就是可以让本身需要互相协作的对方,可以不用知道彼此,而把两者之间的联系,转交给Mediator来处理。换句 话说,Mediator模式解除了需要互相协调的对象之间的依赖。这也是Mediator(调停者)模式名字的由来。一个颇为形象的例子是聊天室。进入聊 天室的用户总是要彼此通信的,这些对象如果直接进行交互,就会彼此连接,最后织成一张纷繁复杂的大网。要分清彼此之间的关系,真可以说是“剪不断理还乱” 了。所以,引入一个聊天室对象来管理用户间的交流,就势成必然。

Mediator模式与Facade模式都是管理复杂对象的行家里手,不过 二者在运用上还是有本质的不同。Facade是门面,通过它隔断了客户端与复杂对象之间的直接关系。Mediator是仲裁者,哪里出现纠纷哪里就有它的 身影。Facade对象对于客户端来说是可见的,而隐藏了复杂对象;Mediator对象对于客户端来说则是隐藏的,客户端直接调用复杂对象,而复杂对象 之间的关系,则转交给了Mediator。

MVC模式则是职责分离的典范,就好似三权分立一般,各司其职。Model负责提供数 据,View则负责显示数据,Controller则负责控制Model与View之间的交互,封装了领域逻辑。这样的职责分离形式,能够有效地解除数 据、业务逻辑与UI界面之间的耦合关系。但是,在MVC模式中,由于业务逻辑的问题,很有可能在Controller之间还需要进行交互。这种交互一旦增 多,就可能出现在一个Controller中出现不同的Controller,导致代码出现分散,形成霰弹式修改的坏味道。

Marlon在其博客上发表了一篇文章, 有效地将MVC模式与Mediator模式两者结合,创造出一种称之为MVC+M的模式,有效地解决了Controller对象之间相互依赖的问题。 Marlon实现了一个文件浏览器来展示这一模式。运行程序,当我们点击左边的目录树时,在右边就会显示当前目录下的所有文件。UI如图所示:

左 边视图对应的控制对象为DirectorySelectorController,而右边视图对应的则为FileSelectorController对 象。Marlon统一定义了一个接口IColleague,作为Mediator模式中参与者的抽象接口,并让相关的Controller实现它。类图如 下所示:

每个Controller对象所接收的Mediator对象都是相同的,因为Mediator对象作为BaseController基类的属性存在,并利用了Singleton模式,保证了Mediator对象只能存在一个:

public abstract class BaseController : INotifyPropertyChanged, IColleague

{

    static Mediator mediatorInstance = new Mediator();

    public Mediator Mediator { get; private set; }

 

    public BaseController()

    {

        //set the mediator to be the same one for every controller.

        Mediator = mediatorInstance;

    }

     //rest of implementation

}

 

在子类的构造函数中,通过调用Mediator对象的Register方法,建立了消息与Controller对象之间的映射关系。以FileSelectorController类为例:

public FileSelectorController()

{

    Mediator.Register(this, new[]

    {

        Messages.DirectorySelectedChanged

    });

}

Mediator类完成Controller对象之间的协调,其定义如下:

public class Mediator

{

    MultiDictionary<string, IColleague> internalList

        = new MultiDictionary<string, IColleague>();


    public void Register(IColleague colleague, IEnumerable<string> messages)

    {

        foreach (string message in messages)

            internalList.AddValue(message, colleague);

    }

 

    public void NotifyColleagues(string message, object args)

    {

        if (internalList.ContainsKey(message))

        {

            //forward the message to all listeners

            foreach (IColleague colleague in internalList[message])

                colleague.MessageNotification(message, args);

        }

    }

}

Register() 方法会将消息与Controller对象的映射注册到内部字典internalList中。而NotifyColleagues()方法则会遍历整个 internalList,然后执行Controller对象(体现为IColleague类型)的MessageNotification()方法。通 过MessageNotification()方法,每个Controller对象根据传输的消息字符串,做出相应的响应操作。例如在 FileSelectorController类中,就是根据Message的值,执行装载文件的业务逻辑:

public override void MessageNotification(string message, object args)

{

    switch (message)

    {

        case Messages.DirectorySelectedChanged:

            //load all files for the directory specified

            LoadFiles((DirectoryDisplayItem)args);

            break;

    }

}

如 果没有引入Mediator模式,由于需要在点击目录时显示当前目录的文件,因此在DirectorySelectorController类的 ItemSelected事件中,必须调用FileSelectorController对象获取文件信息,然后通过对应视图显示这些文件信息。这就导致 了DirectorySelectorController和FileSelectorController之间的依赖。现在,在 DirectorySelectorController的ItemSelected事件中,就可以通过Mediator来实现文件信息的读取与显示:

//event handler for the selecting changed

void ItemSelected(object sender, RoutedEventArgs e)

{

    TreeView treeView = (TreeView)e.OriginalSource;

    //Send a message that an item is selected and pass the object selected

    Mediator.NotifyColleagues(Messages.DirectorySelectedChanged, treeView.SelectedItem);

}

Marlon实现的MVC+M模式有效地解除了Controller对象之间的耦合关系,其中,他引入了IColleague接口对Controller的相关方法进行了抽象。不过,这样的接口并非必须,正如我在《Strategy模式与Delegate委托》 一文中提到的接口与委托之间的关系,我们完全可以用委托来代替IColleague接口的定义,使整个结构变得更加的灵活。由于引入了委托与消息对象的映 射关系,因此在Controller类的MessageNotification()方法中,不再需要用switch语句来判断消息的值,而是直接根据映 射关系,调用委托对象所指代的方法逻辑。Mediator类可以修改为:

public class Mediator

{

    IDictionary<string,Action<object>> m_List = new Dictionary<string,Action<object>>();

 

    public void Register(string message,Action<object> callback)

    {

        m_List.Add(message,callback);

    }

 

    public void NotifyColleagues(string message, object args)

    {

        if (m_List.ContainsKey(message))

        {

            m_List[message](args);

        }

    }

}

与之对应的,FileSelectorController可以修改为:

public FileSelectorController()

{

    Mediator.Register(Messages.DirectorySelectedChanged,

        (obj) =>

        {

            LoadFiles((DirectoryDisplayItem)obj);

        });

}

至于最初定义在Controller类的MessageNotification()方法,则被匿名函数所代替,已经不再需要了。

本文已在ITPub上全文发表

[资源]20个让Web Developer开发生涯更加轻松的工具

mikel阅读(724)

源文:  http://net.tutsplus.com/articles/web-roundups/20-tools-to-make-the-life-of-a-web-developer-easier/

简译:  PuterJam

 

Typetester

一个在线对比字体的工具,可以很直观得看到不同字体的差异

 

pForm

创建HTML表单的工具,能在瞬间创建很美观的表单,并输出html代码

 

ColourLovers

在线的调色板工具,你能够搜索到很多配色方案或提交你的配色方案

 

Firebug

无所不能的firebug,不多介绍了

 

HTML Entity Character Lookup

HTML 实体 查询工具

 

960 Grid System

960 是个神奇的数字,960 是横向尺寸,960 网格系统是能够让设计师快速创建网页原型的辅助系统。可以比喻成网页的黄金分割线

pfvyzisv.jpg

 

 

Em Calculator

EM换算器~ ,可以把像素换算成 em 单位。

 

Browser Shots

多浏览器截屏工具,可以提供多个平台,不同浏览器的页面截屏效果

 

Icon Finder

还在为找图标发愁么,一个不错的图片搜索工具。

 

WhatTheFont

当你图片里看到一个好看的文字而不知道字体名称时,可以用它来帮你分析字体类型

 

MeasureIt

firefox插件,可以在页面上显示一个尺子

 

ColorZilla

同样是firefox插件,可以在页面上取色,前端开发必备

 

Pingdom

一个在线的抓包工具

 

Test Everything

Test Everything 提供了很多测试工具来测试你的站点。从css html 到SEO ,从网络工具到优化应有尽有。

 

CSS Sprite Generator

样式精灵,这类工具很多了,就是把图片分割并且输出成css

 

Web Developer Toolbar

也是一个非常强大的web开发工具。

 

Domainr

域名查询工具,很方面查询域名的使用情况,并且给出未注册域名的建议。(需要翻墙)

 

Font Burner

字体查询工具,并且提供在线的字体解决方案。仅限英文。

 

Smush.It

图片优化工具,能够优化你的图片尺寸

 

Load Impact

可以模拟不同地区的用户访问你的站点的情况。并且以图表的情况反馈结果。

[ASP.NET]重提URL Rewrite(1):IIS与ASP.NET

mikel阅读(649)

  之前觉得这个话题已经被谈滥了。URL Rewrite早已经被广大开发人员所接受,网上关于URL Rewrite的组件和文章也层出不穷,但是总是让我感觉意犹未尽,于是最终还是忍不住提笔写了这系列文章。这些文章不会谈论URL Rewrite的价值与意义,而只会谈论纯技术的内容。文章中也不会有详尽地实现分析,而是结合了我的经验,从应用角度来讲解这个话题。您已经知道的,您 还不知道的,别处已经讲过的,或者还没有讲过的,希望这系列文章的“旧事重提”不会让您觉得沉闷,并且能让您了解ASP.NET中URL Rewrite的方方面面。如果您以后再遇到URL Rewrite方面的问题是能够想到这几篇文章,估计我做梦也会笑出声来。

  要充分理解文章后面谈到的话题,我们必须简单的了解一下IIS与ASP.NET的通信过程。我在这里讲解的是IIS 6服务器。至于IIS 5和IIS 7,前者可以说已经被淘汰了,而后者的“经典模式”与IIS 6可谓如出一辙,而新的“管道模式”其实是讲ASP.NET中的某些概念与IIS进行了深度集成。我相信,如果您了解了IIS 6和ASP.NET,在IIS 7的集成模式下也不会有任何问题。

  首先我们来看一幅简单的示意图,展示了IIS从收到Request开始,到返回Response整个过程中的几个主要步骤:

  1. IIS收到请求。
  2. 选择器根据URL的特点与IIS中的配置,选择一个ISAPI用于处理该请求——现在自然会选择ASP.NET ISAPI。
  3. ASP.NET执行引擎接收到请求,于是初始化数据(例如构建各种对象)。
  4. 开始触发各种Pipeline事件,自然先从BeginRequest开始。
  5. 经过了多个Pipeline事件,ASP.NET根据配置为当前请求选择一个合适的Handler或HandlerFactory进行处理(当然特殊情况例外,例如已经在之前的事件中直接输出结果并结束请求了)。
  6. 经过了Handler处理之后又经过几个Pipeline事件,以EndRequest结束。
  7. 输出Response。

  在一个ASP.NET应用中如果要进行URL Rewrite,那么一般就是在BeginRequest事件中调用HttpContext的RewritePath方法,将该请求重新“定位”至一个目 标URL。例如我们就可以在Global.asax中重写Application_BeginRequest方法来实现这一点:

  之所以在BeginRequest中进行Rewrite,是因为这个事件是在所有Pipeline事件中最早被触发的。在这时进行了重新“定位 ”之后,当前HttpContext中的一些属性也就发生了相应的变化(例如HttpContext.Request.Path)。这样,接下来的 Pipeline事件的处理程序逻辑就会受到影响。例如在需要根据目录进行权限判断时,就会使用“定位”后的路径,而不是ASP.NET所收到的请求。自 然最“显著”的变化就是对Handler的选择,例如上例,我们把请求重新定位至“CustomerList.aspx”文件,这样ASP.NET引擎就 会选择*.aspx所对应的System.Web.UI.PageHandlerFactory类对请求进行处理。

public class Global : System.Web.HttpApplication
{
    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;
 
        if (context.Request.Path.Equals("/Customers",
            StringComparison.InvariantCultureIgnoreCase))
        {
            context.RewritePath("~/CustomerList.aspx");
        }
    }
}

  最后插句提外话,有两个概念需要区分开来,那就是“ASP.NET Pipeline”与“Web Forms”。两者都是ASP.NET里的重要模型,但是差别还是非常大的:

  • ASP.NET Pipeline:作为每个ASP.NET应用所接受到的请求来说,都会经过这个“管道”进行处理。这是一个ASP.NET级别的模型。
  • Web Forms:在ASP.NET Pipeline的执行过程中,其中有一个步骤是选择一个合适的Handler(或HandlerFactory)来处理请求。如果是aspx页 面,ASP.NET就会选择System.Web.UI.PageHandlerFactory类,在这个类中才最终形成了WebForms模型。

  其实上面这句话的“形成”二字可能也不太确切。因为Web Forms可能应该是一个可以独立使用的执行引擎和模型,而System.Web.UI.PageHandlerFactory中也只是利用了这个模型而 已。我们在编写ASP.NET应用时,完全可以根据我们的需要,在其他地方使用这个模型。例如在《技巧:使用User Control做HTML生成》一文中,我们就在一个Generic Handler中把ascx当作模板来生成内容。

相关链接:

(2)使用已有组件进行URL Rewrite

(3)在URL Rewrite后保持PostBack地址

(4)不同级别URL Rewrite的一些细节与特点

[JQuery]JQuery自动提示插件

mikel阅读(1106)

页面代码: 

  1. <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>  
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  3. <html xmlns="http://www.w3.org/1999/xhtml" >  
  4. <head id="Head1" runat="server">  
  5. <mce:script language="JavaScript" src="JavaScript/JQuery1.2.js" mce_src="javascript/JQuery1.2.js"></mce:script>  
  6. <mce:script language="javascript"><!–  
  7.     var __moveIndex = -1;  
  8.     var _x;  
  9.     var _y;  
  10.     var _w;  
  11.     var _data=[];  
  12.     var eSrc = null;  
  13.     var _searchUrl = '<%=ResolveClientUrl("~/search/?k=") %>';  
  14.     $(function(){  
  15.         eSrc = $('#<%=TKeyWord.ClientID %>');  
  16.         addChoseDiv();  
  17.         $("body").click(function(){  
  18.             var target = event.srcElement || event.target;  
  19.             var eID = $(target).attr("id");  
  20.             if(eID!="TKeyWord")  
  21.             {  
  22.                 $("#matchLay").hide();     
  23.             }  
  24.         });  
  25.     });  
  26.       
  27.     //keydown事件  
  28.     function keydown()  
  29.     {  
  30.         if(event.keyCode==13)//回车键  
  31.         {  
  32.             if(__moveIndex>0)  
  33.             {  
  34.                 eSrc.val(_data[__moveIndex-1]["colKeyName"]);  
  35.                 $("#matchLay").hide();  
  36.                 document.location.href=_searchUrl+encodeURI(_data[__moveIndex-1]["colKeyName"]);  
  37.             }  
  38.             else if($.trim(eSrc.val())!=="")  
  39.             {  
  40.                 $("#matchLay").hide();  
  41.                 document.location.href=_searchUrl+encodeURI(eSrc.val());  
  42.             }  
  43.              
  44.            return false;  
  45.         }  
  46.     }  
  47.       
  48.     //初始化层  
  49.     function addChoseDiv()  
  50.     {  
  51.         _x = pageX(eSrc[0]);  
  52.         _y = pageY(eSrc[0])+eSrc.height()+5;  
  53.         _w =eSrc.width()+4;  
  54.           
  55.         $("<div id='matchLay' z-index='500'   style='background-color:#ffffff;display:none;width:"  
  56.         +_w+"px;position:absolute;left:"+_x+"px;top:"+_y  
  57.         +"px;border-left:1px solid #000000;border-bottom:1px solid #000000;border-right:1px solid #000000;' ></div>").appendTo($("body"));  
  58.     }  
  59.       
  60.     //选定匹配项导航函数  
  61.     function SelKey(obj)  
  62.     {  
  63.        eSrc.val($(obj).children().filter(":nth-child(1)").text());  
  64.        document.location.href=_searchUrl+encodeURI(eSrc.val());  
  65.        $("#matchLay").hide();    
  66.     }  
  67.       
  68.     //匹配函数  
  69.     function IsMatch()  
  70.     {  
  71.       
  72.         var rs = $.ajax({  
  73.             type:"GET",  
  74.             cache:false,  
  75.             url:"SearchPro.aspx",  
  76.             success:function(data,status){  
  77.                 //alert(data);  
  78.             }  
  79.         });  
  80.   
  81.         var v = eSrc.val();  
  82.         if(v=="")//输入为空,返回  
  83.         {  
  84.             $("#matchLay").hide();     
  85.             return false;  
  86.         }  
  87.           
  88.         _data = _Default.GetSkeys(v).value;  
  89.           
  90.         if(_data!=null && _data.length>0)//生成匹配div  
  91.         {  
  92.             var shtm = "<table width='100%' cellspacing='0' id='sList' >";  
  93.             for(var i=0;i<_data.length;i++)  
  94.             {  
  95.                 shtm+="<tr  onmouSEOver='mouSEOver(this)'  onclick='SelKey(this)'><td align='left'>"+_data[i]["colKeyName"]+"</td>";  
  96.                 shtm+="<td align='right' style="color:green" mce_style="color:green">"+RelNumber(parseInt(_data[i]["colResults"],10))+" 结果</td>";  
  97.                 shtm+="</tr>"  
  98.             }  
  99.             shtm+="</table>";  
  100.             $("#matchLay").html(shtm);  
  101.             $("#matchLay").show();     
  102.             return true;  
  103.         }else //没有匹配隐藏div  
  104.         {  
  105.             $("#matchLay").hide();     
  106.             return false;  
  107.         }  
  108.     }  
  109.   
  110.     //search Button click事件  
  111.     function goSearch(k)  
  112.     {  
  113.         document.location.href=_searchUrl+encodeURI(k);  
  114.     }  
  115.       
  116.     //onkeyup事件  
  117.     function matchBase()  
  118.     {  
  119.         if(!IsMatch()) return false;//没有匹配返回  
  120.          
  121.          if(event.keyCode==38)//上箭头  
  122.         {  
  123.             if(__moveIndex==-1 || __moveIndex==1)  
  124.             {  
  125.                 mouseOver($("#sList tr").length);  
  126.             }else  
  127.             {  
  128.                 mouseOver(__moveIndex-1,__moveIndex);  
  129.             }  
  130.         }  
  131.         else if(event.keyCode==40)//下箭头  
  132.         {  
  133.             if(__moveIndex==$("#sList tr").length)  
  134.             {  
  135.                 mouseOver(1,$("#sList tr").length);  
  136.             }else  
  137.             {  
  138.                 if(__moveIndex==-1)  
  139.                 {  
  140.                     mouseOver(1,1);  
  141.                 }else  
  142.                 {  
  143.                     mouseOver(__moveIndex+1,__moveIndex);  
  144.                 }  
  145.             }  
  146.              
  147.         }  
  148.     }  
  149.       
  150.     //提示层mouseover事件  
  151.     function mouseOver()  
  152.     {  
  153.         var obj = null;  
  154.         var n = __moveIndex ;  
  155.         if(n==-1) n=1;  
  156.         var oldObj =$("#sList tr:nth-child("+n+")");  
  157.         if(typeof arguments[0]=="object")  
  158.         {  
  159.             obj = $(arguments[0]);  
  160.         }else  
  161.         {  
  162.             obj = $("#sList tr:nth-child("+arguments[0]+")");  
  163.             oldObj =$("#sList tr:nth-child("+arguments[1]+")");  
  164.         }  
  165.           
  166.         oldObj.css("backgroundColor","#ffffff");  
  167.         oldObj.children().filter(":nth-child(1)").css("color","#000000");  
  168.         oldObj.children().filter(":nth-child(2)").css("color","green");  
  169.           
  170.         obj.css("backgroundColor","#3366CC");  
  171.         obj.children().filter(":nth-child(1)").css("color","#ffffff");  
  172.         obj.children().filter(":nth-child(2)").css("color","#ffffff");  
  173.           
  174.         __moveIndex = obj[0].rowIndex+1;  
  175.     }  
  176.       
  177.     //格式化正整数123,456  
  178.     function RelNumber(num)  
  179.     {  
  180.         var t=num>0?num:Math.abs(num);  
  181.         var str=num.toString();  
  182.         var il = str.length;  
  183.         var n = 1;  
  184.         while(t>1000)  
  185.         {    
  186.             t/=1000;  
  187.             str=str.substring(0,il-n*3)+","+str.substr(il-n*3);  
  188.             ++n;  
  189.         }  
  190.         return str;  
  191.     }  
  192.       
  193.     //取得元素x坐标  
  194.     function pageX(elem)  
  195.     {  
  196.         return elem.offsetParent?(elem.offsetLeft+pageX(elem.offsetParent)):elem.offsetLeft;  
  197.     }  
  198.     //取得元素y坐标  
  199.     function pageY(elem)  
  200.     {  
  201.         return elem.offsetParent?(elem.offsetTop+pageY(elem.offsetParent)):elem.offsetTop;  
  202.     }  
  203. // –></mce:script>  
  204. </head>  
  205. <body>  
  206. <form runat="server">  
  207. <asp:TextBox AutoCompleteType="Disabled"  runat="server" ID="TKeyWord" Width="250px" ></asp:TextBox>  
  208. <asp:Button runat="server" ID="Btn_search" Text="Search"  />  
  209. </form>  
  210. </body>  
  211. </html>  

   

后台代码: 

  1. using System;  
  2. using System.Data;  
  3. using System.Configuration;  
  4. using System.Web;  
  5. using System.Web.Security;  
  6. using System.Web.UI;  
  7. using System.Web.UI.WebControls;  
  8. using System.Web.UI.WebControls.WebParts;  
  9. using System.Web.UI.HtmlControls;  
  10. using AjaxPro;  
  11.   
  12. public partial class _Default : System.Web.UI.Page   
  13. {  
  14.     private string NowKey = string.Empty;  
  15.     SHOPBill.SmartSearch.SearchBill sBill = new SHOPBill.SmartSearch.SearchBill();  
  16.   
  17.     protected void Page_Load(object sender, EventArgs e)  
  18.     {  
  19.         Utility.RegisterTypeForAjax(typeof(_Default));  
  20.         if (!IsPostBack)  
  21.         {  
  22.             TKeyWord.Attributes.Add("onkeyup""matchBase();");  
  23.             TKeyWord.Attributes.Add("onkeydown""keydown();");  
  24.             Btn_search.Style.Add("cursor""hand");  
  25.             Btn_search.Attributes.Add("align""absmiddle");  
  26.             Btn_search.Attributes.Add("onclick""if($.trim($('#" + TKeyWord.ClientID + "').val())==''){alert('关键字不能为空!',false);return false};document.location.href='" + ResolveClientUrl("~/search/?k=") + "'+encodeURI($('#" + TKeyWord.ClientID + "').val())");  
  27.           
  28.             List<SHOPModule.SmartSearch.SearchItem> list = sBill.SelectKeys();  
  29.             HttpContext.Current.Cache["SEARCHKEYS"] = list;  
  30.         }  
  31.   
  32.     }  
  33.   
  34.   
  35.   
  36.     [AjaxPro.AjaxMethod]  
  37.     public List<SHOPModule.SmartSearch.SearchItem> GetSkeys(string inputKey)  
  38.     {  
  39.         NowKey = inputKey;  
  40.         List<SHOPModule.SmartSearch.SearchItem> list = null;  
  41.         List<SHOPModule.SmartSearch.SearchItem> result = null;  
  42.         if (HttpContext.Current.Cache.Get("SEARCHKEYS") == null)  
  43.         {  
  44.             list = sBill.SelectKeys();  
  45.             HttpContext.Current.Cache["SEARCHKEYS"] = list;  
  46.         }  
  47.         else  
  48.         {  
  49.             list = HttpContext.Current.Cache.Get("SEARCHKEYS"as List<SHOPModule.SmartSearch.SearchItem>;  
  50.         }  
  51.   
  52.         result = list.FindAll(ListMatch);  
  53.         return result;  
  54.     }  
  55.   
  56.     private bool ListMatch(SHOPModule.SmartSearch.SearchItem m)  
  57.     {  
  58.         string k = SHOPCommUtility.Hz2Py.GetWholePinyin(m.colKeyName);  
  59.         return (MatchKeys(NowKey.ToLower(), m.colKeyName.ToLower()) || MatchKeys(NowKey.ToLower(), k.ToLower()));  
  60.   
  61.     }  
  62.   
  63.     private bool MatchKeys(string iKey, string K)  
  64.     {  
  65.         return K.Length >= iKey.Length && K.Substring(0, iKey.Length) == iKey;  
  66.     }  
  67. }  

 

汉字转拼音算法: 

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text.RegularExpressions;  
  4. using System.Text;  
  5.   
  6. namespace SHOPCommUtility  
  7. {  
  8.     /// <summary>  
  9.     /// 汉字转拼音类  
  10.     /// </summary>  
  11.     public class Hz2Py  
  12.     {  
  13.         private static int[] pyValue = new int[]  
  14.         {  
  15.             -20319,-20317,-20304,-20295,-20292,-20283,-20265,-20257,-20242,-20230,-20051,-20036,  
  16.             -20032,-20026,-20002,-19990,-19986,-19982,-19976,-19805,-19784,-19775,-19774,-19763,  
  17.             -19756,-19751,-19746,-19741,-19739,-19728,-19725,-19715,-19540,-19531,-19525,-19515,  
  18.             -19500,-19484,-19479,-19467,-19289,-19288,-19281,-19275,-19270,-19263,-19261,-19249,  
  19.             -19243,-19242,-19238,-19235,-19227,-19224,-19218,-19212,-19038,-19023,-19018,-19006,  
  20.             -19003,-18996,-18977,-18961,-18952,-18783,-18774,-18773,-18763,-18756,-18741,-18735,  
  21.             -18731,-18722,-18710,-18697,-18696,-18526,-18518,-18501,-18490,-18478,-18463,-18448,  
  22.             -18447,-18446,-18239,-18237,-18231,-18220,-18211,-18201,-18184,-18183, -18181,-18012,  
  23.             -17997,-17988,-17970,-17964,-17961,-17950,-17947,-17931,-17928,-17922,-17759,-17752,  
  24.             -17733,-17730,-17721,-17703,-17701,-17697,-17692,-17683,-17676,-17496,-17487,-17482,  
  25.             -17468,-17454,-17433,-17427,-17417,-17202,-17185,-16983,-16970,-16942,-16915,-16733,  
  26.             -16708,-16706,-16689,-16664,-16657,-16647,-16474,-16470,-16465,-16459,-16452,-16448,  
  27.             -16433,-16429,-16427,-16423,-16419,-16412,-16407,-16403,-16401,-16393,-16220,-16216,  
  28.             -16212,-16205,-16202,-16187,-16180,-16171,-16169,-16158,-16155,-15959,-15958,-15944,  
  29.             -15933,-15920,-15915,-15903,-15889,-15878,-15707,-15701,-15681,-15667,-15661,-15659,  
  30.             -15652,-15640,-15631,-15625,-15454,-15448,-15436,-15435,-15419,-15416,-15408,-15394,  
  31.             -15385,-15377,-15375,-15369,-15363,-15362,-15183,-15180,-15165,-15158,-15153,-15150,  
  32.             -15149,-15144,-15143,-15141,-15140,-15139,-15128,-15121,-15119,-15117,-15110,-15109,  
  33.             -14941,-14937,-14933,-14930,-14929,-14928,-14926,-14922,-14921,-14914,-14908,-14902,  
  34.             -14894,-14889,-14882,-14873,-14871,-14857,-14678,-14674,-14670,-14668,-14663,-14654,  
  35.             -14645,-14630,-14594,-14429,-14407,-14399,-14384,-14379,-14368,-14355,-14353,-14345,  
  36.             -14170,-14159,-14151,-14149,-14145,-14140,-14137,-14135,-14125,-14123,-14122,-14112,  
  37.             -14109,-14099,-14097,-14094,-14092,-14090,-14087,-14083,-13917,-13914,-13910,-13907,  
  38.             -13906,-13905,-13896,-13894,-13878,-13870,-13859,-13847,-13831,-13658,-13611,-13601,  
  39.             -13406,-13404,-13400,-13398,-13395,-13391,-13387,-13383,-13367,-13359,-13356,-13343,  
  40.             -13340,-13329,-13326,-13318,-13147,-13138,-13120,-13107,-13096,-13095,-13091,-13076,  
  41.             -13068,-13063,-13060,-12888,-12875,-12871,-12860,-12858,-12852,-12849,-12838,-12831,  
  42.             -12829,-12812,-12802,-12607,-12597,-12594,-12585,-12556,-12359,-12346,-12320,-12300,  
  43.             -12120,-12099,-12089,-12074,-12067,-12058,-12039,-11867,-11861,-11847,-11831,-11798,  
  44.             -11781,-11604,-11589,-11536,-11358,-11340,-11339,-11324,-11303,-11097,-11077,-11067,  
  45.             -11055,-11052,-11045,-11041,-11038,-11024,-11020,-11019,-11018,-11014,-10838,-10832,  
  46.             -10815,-10800,-10790,-10780,-10764,-10587,-10544,-10533,-10519,-10331,-10329,-10328,  
  47.             -10322,-10315,-10309,-10307,-10296,-10281,-10274,-10270,-10262,-10260,-10256,-10254  
  48.         };  
  49.   
  50.         private static string[] pyName = new string[]  
  51.         {  
  52.             "A","Ai","An","Ang","Ao","Ba","Bai","Ban","Bang","Bao","Bei","Ben",  
  53.             "Beng","Bi","Bian","Biao","Bie","Bin","Bing","Bo","Bu","Ba","Cai","Can",  
  54.             "Cang","Cao","Ce","Ceng","Cha","Chai","Chan","Chang","Chao","Che","Chen","Cheng",  
  55.             "Chi","Chong","Chou","Chu","Chuai","Chuan","Chuang","Chui","Chun","Chuo","Ci","Cong",  
  56.             "Cou","Cu","Cuan","Cui","Cun","Cuo","Da","Dai","Dan","Dang","Dao","De",  
  57.             "Deng","Di","Dian","Diao","Die","Ding","Diu","Dong","Dou","Du","Duan","Dui",  
  58.             "Dun","Duo","E","En","Er","Fa","Fan","Fang","Fei","Fen","Feng","Fo",  
  59.             "Fou","Fu","Ga","Gai","Gan","Gang","Gao","Ge","Gei","Gen","Geng","Gong",  
  60.             "Gou","Gu","Gua","Guai","Guan","Guang","Gui","Gun","Guo","Ha","Hai","Han",  
  61.             "Hang","Hao","He","Hei","Hen","Heng","Hong","Hou","Hu","Hua","Huai","Huan",  
  62.             "Huang","Hui","Hun","Huo","Ji","Jia","Jian","Jiang","Jiao","Jie","Jin","Jing",  
  63.             "Jiong","Jiu","Ju","Juan","Jue","Jun","Ka","Kai","Kan","Kang","Kao","Ke",  
  64.             "Ken","Keng","Kong","Kou","Ku","Kua","Kuai","Kuan","Kuang","Kui","Kun","Kuo",  
  65.             "La","Lai","Lan","Lang","Lao","Le","Lei","Leng","Li","Lia","Lian","Liang",  
  66.             "Liao","Lie","Lin","Ling","Liu","Long","Lou","Lu","Lv","Luan","Lue","Lun",  
  67.             "Luo","Ma","Mai","Man","Mang","Mao","Me","Mei","Men","Meng","Mi","Mian",  
  68.             "Miao","Mie","Min","Ming","Miu","Mo","Mou","Mu","Na","Nai","Nan","Nang",  
  69.             "Nao","Ne","Nei","Nen","Neng","Ni","Nian","Niang","Niao","Nie","Nin","Ning",  
  70.             "Niu","Nong","Nu","Nv","Nuan","Nue","Nuo","O","Ou","Pa","Pai","Pan",  
  71.             "Pang","Pao","Pei","Pen","Peng","Pi","Pian","Piao","Pie","Pin","Ping","Po",  
  72.             "Pu","Qi","Qia","Qian","Qiang","Qiao","Qie","Qin","Qing","Qiong","Qiu","Qu",  
  73.             "Quan","Que","Qun","Ran","Rang","Rao","Re","Ren","Reng","Ri","Rong","Rou",  
  74.             "Ru","Ruan","Rui","Run","Ruo","Sa","Sai","San","Sang","Sao","Se","Sen",  
  75.             "Seng","Sha","Shai","Shan","Shang","Shao","She","Shen","Sheng","Shi","Shou","Shu",  
  76.             "Shua","Shuai","Shuan","Shuang","Shui","Shun","Shuo","Si","Song","Sou","Su","Suan",  
  77.             "Sui","Sun","Suo","Ta","Tai","Tan","Tang","Tao","Te","Teng","Ti","Tian",  
  78.             "Tiao","Tie","Ting","Tong","Tou","Tu","Tuan","Tui","Tun","Tuo","Wa","Wai",  
  79.             "Wan","Wang","Wei","Wen","Weng","Wo","Wu","Xi","Xia","Xian","Xiang","Xiao",  
  80.             "Xie","Xin","Xing","Xiong","Xiu","Xu","Xuan","Xue","Xun","Ya","Yan","Yang",  
  81.             "Yao","Ye","Yi","Yin","Ying","Yo","Yong","You","Yu","Yuan","Yue","Yun",  
  82.             "Za""Zai","Zan","Zang","Zao","Ze","Zei","Zen","Zeng","Zha","Zhai","Zhan",  
  83.             "Zhang","Zhao","Zhe","Zhen","Zheng","Zhi","Zhong","Zhou","Zhu","Zhua","Zhuai","Zhuan",  
  84.             "Zhuang","Zhui","Zhun","Zhuo","Zi","Zong","Zou","Zu","Zuan","Zui","Zun","Zuo"  
  85.         };  
  86.   
  87.         /// <summary>  
  88.         /// 把汉字转换成拼音(全拼)  
  89.         /// </summary>  
  90.         /// <param name="hzString">汉字字符串</param>  
  91.         /// <returns>转换后的拼音(全拼)字符串</returns>  
  92.         public static string GetWholePinyin(string hzString)  
  93.         {  
  94.             // 匹配中文字符  
  95.             Regex regex = new Regex("^[\u4e00-\u9fa5]$");  
  96.             byte[] array = new byte[2];  
  97.             string pyString = "";  
  98.             int chrAsc = 0;  
  99.             int i1 = 0;  
  100.             int i2 = 0;  
  101.             char[] noWChar = hzString.ToCharArray();  
  102.   
  103.             for (int j = 0; j < noWChar.Length; j++)  
  104.             {  
  105.                 // 中文字符  
  106.                 if (regex.IsMatch(noWChar[j].ToString()))  
  107.                 {  
  108.                     array = System.Text.Encoding.Default.GetBytes(noWChar[j].ToString());  
  109.                     i1 = (short)(array[0]);  
  110.                     i2 = (short)(array[1]);  
  111.                     chrAsc = i1 * 256 + i2 – 65536;  
  112.                     if (chrAsc > 0 && chrAsc < 160)  
  113.                     {  
  114.                         pyString += noWChar[j];  
  115.                     }  
  116.                     else  
  117.                     {  
  118.                         // 修正部分文字  
  119.                         if (chrAsc == -9254)  // 修正"圳"字  
  120.                             pyString += "Zhen";  
  121.                         else  
  122.                         {  
  123.                             for (int i = (pyValue.Length – 1); i >= 0; i–)  
  124.                             {  
  125.                                 if (pyValue[i] <= chrAsc)  
  126.                                 {  
  127.                                     pyString += pyName[i];  
  128.                                     break;  
  129.                                 }  
  130.                             }  
  131.                         }  
  132.                     }  
  133.                 }  
  134.                 // 非中文字符  
  135.                 else  
  136.                 {  
  137.                     pyString += noWChar[j].ToString();  
  138.                 }  
  139.             }  
  140.             return pyString;  
  141.         }  
  142.     }  
  143. }