基本语法¶
#set ($var=XXX)
左边可以是以下的内容:
- Variable reference
- String literal
- Property reference
- Method reference
- Number literal #set ($i=1)
- ArrayList #set ($arr=["yt1","t2"])
- 算术运算符
- References 引用的类型
单行:
## this is a comment
多行:
#* this line
and this line
and this line, are comments...*#
变量 Variables¶
以 "$" 开头,第一个字符必须为字母。character followed by a VTL Identifier. (a .. z or A .. Z).
变量可以包含的字符有以下内容:
- alphabetic (a .. z, A .. Z)
- numeric (0 .. 9)
- hyphen ("-")
- underscore ("_")
Properties¶
$Identifier.Identifier
$user.name
hashtable user中的的name值.类似:user.get("name")
h2、Methods
object user.getName() = $user.getName()
h2、Formal Reference Notation
用{}把变量名跟字符串分开。如
#set ($user="csy"}
${user}name
返回csyname
$与$!的区别¶
当找不到username的时候,$username返回字符串"$username",而$!username返回空字符串""
双引号 与 引号¶
#set ($var="helo")
则 test"$var" 返回testhello,test'$var' 返回test'$var'。
可以通过设置 stringliterals.interpolate=false改变默认处理方式
条件语句¶
#if( $foo )
<strong>Velocity!</strong>
#end
#if($foo)
#elseif()
#else
#end
当$foo为null或为Boolean对象的false值执行.
逻辑运算符:¶
== && || !
循环语句¶
#foreach($var in $arrays ) // 集合包含下面三种Vector, a Hashtable or an Array
#end
#foreach( $product in $allProducts )
<li>$product</li>
#end
#foreach( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key)</li>
#end
#foreach( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
velocityCount变量在配置文件中定义¶
- Default name of the loop counter
- variable reference.
directive.foreach.counter.name = velocityCount
- Default starting value of the loop
- counter variable reference.
directive.foreach.counter.initial.value = 1
包含文件¶
#include( "one.gif","two.txt","three.htm" )
Parse导入脚本¶
#parse("me.vm" )
#stop 停止执行并返回¶
定义宏¶
Velocimacros, 相当于函数支持包含功能:
#macro( d )
<tr><td></td></tr>
#end
调用
#d()
带参数的宏¶
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end
Range Operator¶
#foreach( $foo in [1..5] )
与struts2的整合¶
模板装载位置(按顺序依次搜索)¶
- Web application 应用程序路径,会覆盖掉类路径下的同名配置文件;
- Class path 类路径,一般为缺省模板的配置,公共模板位置;
数据来源(按顺序依次搜索)¶
- The value stack
- The action context
- Built-in variables
Struts2-Velocity集成的一些隐含变量¶
- stack - ValueStack自身。调用方式:${stack.findString('ognl expr')}
- action - 最新操作的action
- reponse
- request
- session
- applicaion - 获得servlet的环境
- base - 请求环境的路径
Velocity Result 输出模板¶
模拟jsp执行环境,使用velocity的模板直接显示到servelet的输出流。
location - 模板位置,没有其它参数时的缺省配置。
parse - 默认true ,false将不解析Ognl expressions.
配置范例:
<result name="success" type="velocity">
<param name="location">foo.vm</param>
</result>
等价于以下的配置方式:
<result name="success" type="velocity">
foo.vm
</result>
Velocity语法¶
http://blog.csdn.net/alexwan/archive/2007/10/29/1853285.aspx
Struts 与 Velocity 的集成¶
http://www.ibm.com/developerworks/cn/java/j-sr1.html
posted @
2009-07-02 09:38 xiaoxinchen 阅读(158) |
评论 (0) |
编辑 收藏
CDN
的全称是Content Delivery Network,即内容分发网络。其目的是通过在现有的Internet中增加一层新的网络架构,
将网站的内容发布到最接近用户的网络"边缘", 使用户可以就近取得所需的内容, 解决Internet网络拥挤的状况,
提高用户访问网站的响应速度。从技术上全面解决由于网络带宽小, 用户访问量大, 网点分布不均等原因所造成的用户访问网站响应速度慢的问题。
CDN互联网内容发布网络(Content Delivery Network)¶
CDN
技术是近年来在美国首先兴起并迅速发展起来的一种解决互联网性能不佳问题的有效手段。其基本思路就是尽可能避开互联网上有可能影响数据传输速度和稳定性的
瓶颈和环节,使内容传输的更快、更稳。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,cdn系统能够实时地根据网络流
量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。
实际上,内容分发
布网络(CDN)是一种新型的网络构建方式,它是为能在传统的IP网发布宽带丰富媒体而特别优化的网络覆盖层;而从广义的角度,CDN代表了一种基于质量
与秩序的网络服务模式。简单地说,内容发布网(CDN)是一个经策略性部署的整体系统,包括分布式存储、负载均衡、网络请求的重定向和内容管理4个要件,
而内容管理和全局的网络流量管理(Traffic
Management)是CDN的核心所在。通过用户就近性和服务器负载的判断,CDN确保内容以一种极为高效的方式为用户的请求提供服务。总的来说,内
容服务基于缓存服务器,也称作代理缓存(Surrogate),它位于网络的边缘,距用户仅有"一跳"(Single
Hop)之遥。同时,代理缓存是内容提供商源服务器(通常位于CDN服务提供商的数据中心)的一个透明镜像。这样的架构使得CDN服务提供商能够代表他们
客户,即内容供应商,向最终用户提供尽可能好的体验,而这些用户是不能容忍请求响应时间有任何延迟的。据统计,采用CDN技术,能处理整个网站页面的
70%~95%的内容访问量,减轻服务器的压力,提升了网站的性能和可扩展性。
与目前现有的内容发布模式相比较,CDN强调了网络
在内容发布中的重要性。通过引入主动的内容管理层的和全局负载均衡,CDN从根本上区别于传统的内容发布模式。在传统的内容发布模式中,内容的发布由
ICP的应用服务器完成,而网络只表现为一个透明的数据传输通道,这种透明性表现在网络的质量保证仅仅停留在数据包的层面,而不能根据内容对象的不同区分
服务质量。此外,由于IP网的"尽力而为"的特性使得其质量保证是依靠在用户和应用服务器之间端到端地提供充分的、远大于实际所需的带宽通量来实现的。在
这样的内容发布模式下,不仅大量宝贵的骨干带宽被占用,同时ICP的应用服务器的负载也变得非常重,而且不可预计。当发生一些热点事件和出现浪涌流量时,
会产生局部热点效应,从而使应用服务器过载退出服务。这种基于中心的应用服务器的内容发布模式的另外一个缺陷在于个性化服务的缺失和对宽带服务价值链的扭
曲,内容提供商承担了他们不该干也干不好的内容发布服务。
纵观整个宽带服务的价值链,内容提供商和用户位于整个价值链的两端,中间
依靠网络服务提供商将其串接起来。随着互联网工业的成熟和商业模式的变革,在这条价值链上的角色越来越多也越来越细分。比如内容/应用的运营商、托管服务
提供商、骨干网络服务提供商、接入服务提供商等等。在这一条价值链上的每一个角色都要分工合作、各司其职才能为客户提供良好的服务,从而带来多赢的局面。
从内容与网络的结合模式上看,内容的发布已经走过了ICP的内容(应用)服务器和IDC这两个阶段。IDC的热潮也催生了托管服务提供商这一角色。但
是,IDC并不能解决内容的有效发布问题。内容位于网络的中心并不能解决骨干带宽的占用和建立IP网络上的流量秩序。因此将内容推到网络的边缘,为用户提
供就近性的边缘服务,从而保证服务的质量和整个网络上的访问秩序就成了一种显而易见的选择。而这就是内容发布网(CDN)服务模式。CDN的建立解决了困
扰内容运营商的内容"集中与分散"的两难选择,无疑对于构建良好的互联网价值链是有价值的,也是不可或缺的最优网站加速服务。
目前,国内访问量较高的大型网站如新浪、网易等,均使用CDN网络加速技术,虽然网站的访问巨大,但无论在什么地方访问都会感觉速度很快。而一般的网站如果服务器在网通,电信用户访问很慢,如果服务器在电信,网通用户访问又很慢。
它
采取了分布式网络缓存结构(即国际上流行的web
cache技术),通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的cache服务器内,通过DNS负载均衡的技
术,判断用户来源就近访问cache服务器取得所需的内容,解决Internet网络拥塞状况,提高用户访问网站的响应速度,如同提供了多个分布在各地的
加速器,以达到快速、可冗余的为多个网站加速的目的。
CDN的特点¶
- 本地Cache加速 提高了企业站点(尤其含有大量图片和静态页面站点)的访问速度,并大大提高以上性质站点的稳定性
- 镜像服务 消除了不同运营商之间互联的瓶颈造成的影响,实现了跨运营商的网络加速,保证不同网络中的用户都能得到良好的访问质量。
- 远程加速 远程访问用户根据DNS负载均衡技术 智能自动选择Cache服务器,选择最快的Cache服务器,加快远程访问的速度
- 带宽优化 自动生成服务器的远程Mirror(镜像)cache服务器,远程用户访问时从cache服务器上读取数据,减少远程访问的带宽、分担网络流量、减轻原站点WEB服务器负载等功能。
- 集群抗攻击 广泛分布的CDN节点加上节点之间的智能冗于机制,可以有效地预防黑客入侵以及降低各种D.D.o.S攻击对网站的影响,同时保证较好的服务质量 。
关键技术¶
- 内容发布:它借助于建立索引、缓存、流分裂、组播(Multicast)等技术,将内容发布或投递到距离用户最近的远程服务点(POP)处;
- 内容路由:它是整体性的网络负载均衡技术,通过内容路由器中的重定向(DNS)机制,在多个远程POP上均衡用户的请求,以使用户请求得到最近内容源的响应;
- 内容交换:它根据内容的可用性、服务器的可用性以及用户的背景,在POP的缓存服务器上,利用应用层交换、流分裂、重定向(ICP、WCCP)等技术,智能地平衡负载流量;
- 性能管理:它通过内部和外部监控系统,获取网络部件的状况信息,测量内容发布的端到端性能(如包丢失、延时、平均带宽、启动时间、帧速率等),保证网络处于最佳的运行状态。
P4P与传统CDN、P2P的对比¶
7
月30日消息:德国一个名为iPoque的研究机构在2007年研究了一百多万网民将近
3TB的匿名数据流量,调查地区包括澳大利亚、东欧、德国、中东和南欧地区。调查发现,目前网络带宽“消费大户”是P2P文件共享,在中东占据了49%,
东欧地区占据了84%。从全球来看,晚上时段的网络带宽有95%被P2P占据。据国内权威部门统计,当前P2P流量已经占整个互联网流量的约70%,并且
正在以每年350%的速度增长。P2P流量消耗了巨大的网络带宽,尤其是国际带宽,使网络基础设施不堪重负,运营商苦不堪言。
问题
的症结不在于P2P,而在于交换的机制。P2P过于强调“对等”,每个节点之间的交换完全是无序的。一个北京的用户,既可能和广州的用户进行文件片段的交
换,也可能和远在美国的某用户进行交换。显然,无序的交换导致了无谓的跨地区甚至是跨国的 “流量旅行”,这耗费了宝贵的国内和国际带宽资源,代价巨大。
如
果正好用户都在同一个地区,那么,本地化的交换的成本就会大大降低。这也正是P4P的简单原理——让P2P也玩“同城”。
P4P全称是“Proactive network Provider Participation for
P2P(电信运营商主动参与P2P网络)”。与P2P随机挑选Peer(对等机)不同,P4P协议可以协调网络拓扑数据,能够有效选择节点,从而提高网络
路由效率。仍以上述例子来说,北京的用户就可以优先和北京同城的用户来实现文件片段的交换,再扩展至较远的地区,有十分的必要时,才会出国进行文件片段交
换。当然,P4P的运行机制,要远远超过“同城交换”的概念,它还会根据用户的上行、下载带宽进行综合判断,以进行最有效选择,最大化整体交换的效率。
举
几个例子可以说明CDN的普遍作用。例如2008年,北京奥运会之前,关于门票网络出售,很多国内的朋友都去登陆,而大家的登录的时刻几乎千篇一律,导致
中国政府的网站服务器支撑不了这么大的请求,谁都进去不了,都被堵死在门外。这中现象在国内许多网站都出现过,比如高考时期,学生上网填申请,大家都说是
自己网络原因,其实不然,这都跟被请求的服务器有关,来自四面八方的请求去请求他一个网站,他自然接受不了这么大的带宽,给人一种印象,就是互联网太慢,
落后了。这样的例子很多,我们就不纷纷介绍了。不过互联网,网聚全球人的智慧。解决方法很多,美国作为世界的互联网中心,提供了CDN技术,内容网络分
发。美国很多军方工程都是采用该技术。我国国内的香港海洋科技集团的GTONE产品,专业为我国国内大型公司提供海外服务,在全球都有很广的资源。国内很
多很有实力的公司都和他们合作了。
新建文件
posted @
2009-07-02 09:37 xiaoxinchen 阅读(116) |
评论 (0) |
编辑 收藏
- 基本命令
- 常见文件操作
建立目录:mkdir 目录名
删除空目录:rmdir 目录名
无条件删除子目录: rm -rf 目录名
改变当前目录:cd 目录名 (进入用户home目录:cd ~;进入上一级目录:cd -)
查看自己所在目录:pwd
查看当前目录大小:du
显示目录文件列表:ls -l (-a:增加显示隐含目录)
其中:蓝:目录;绿:可执行文件;红:压缩文件;浅蓝:链接文件;灰:其他文件;红底白字:错误的链接文件
浏览文件:more 文件名.txt;less 文件名.txt
复制文件: cp 源文件 目标文件 (-r:包含目录)
查找文件:(1)find (2)locate 命令名
链接:(1)建立hard链接:ln 来源文件 链接文件(-d:创建目录链接);(2)建立符号链接:ln -s 来源文件 链接文件
文本编码转换工具iconv:iconv -f gb2312 -t utf-8 -o new.txt old.txt
输入/输出格式规范
-f, --from-code=NAME 原始文本编码,
-t,--to-code=NAME 输出编码,信息
-l, --list 列出所有已知编码字符集
输出控制:
-c 忽略输出中的无效字符
-o, --output=FILE 输出文件
-s, --silent suppress warnings
# 进程管理
列出当前进程ID:ps -auxw
终止进程:(1)终止单一进程:kill 进程ID号
终止该程序所有进程:killall 程序名
终止X-Window程序:xkill
查看资源占用情况:(1)top (2)free (3)dmesg
查看环境变量值:env
重启:(1)reboot (2)Ctrl Alt Del (3)init 6
关机:(1)shutdown -h now (2)halt (3)init 0
# 网络管理
显示网络接口参数:ifconfig
联机状况:ping xxx.xxx.xxx.xxx
显示网络状况:netstat ,其中:options:-a==所有sockets;-l==包含网络设备;-n==数字IP;-o==其他信息;-r==路由表;-t==只列TCP sockets;-u==只列UDP sockets;-w==只列raw sockets;
-x==只列Unix Domain sockets
# 权限设定
(1)chmod -a|u|g|o |-|=r|w|x 文件/目录名
其中:a--所有用户(all);u--本用户(user);g--用户组(group);o--其他用户(other users)
--增加权限;---删除权限;=--设置权限
文件:r--只读权限(read);w--写权限(write);x--执行权限(execute)
目录:r--允许列目录下文件和子目录;w--允许生成和删除目录下文件;x--允许访问该目录
(2)chmod xxx 文件/目录名
其中:execute=1;write=2;read=4
x取值:0--没有任何权限(常用);1--只能执行(不常见);2--只能写(不常见);3--只能写和执行(不常见);4--只读(常见);5--只读和执行(常见);6--读和写(常见);7--读.写和执行
# vim 常见命令
进入后为命令模式:(1)插入i;(2)打开0;(3)修改c;(4)取代r;(5)替换s
经(1)后进入全屏幕编辑模式。
命令模式-->编辑模式(a/i);编辑模式-->命令模式(Esc);命令模式-->末行模式(:)。
:w/w newfile保存
:q/q!退出iv;:wq保存退出
http://vimcdoc.sourceforge.net/doc/help.html
#ln命令
ln 命令
用途 : 链接文件。
语法
1>将某个文件链接到一个文件上
ln [ -f | -n] [ -s ] SourceFile [ TargetFile ]
2>将一个或多个文件链接到一个目录上
ln [ -f | -n] [ -s ] SourceFile ... TargetDirectory
描述
ln 命令将在 SourceFile 参数中指定的文件链接到在 TargetFile 参数中指定的文件,或将其链接到在 TargetDirectory 参数中指定的另一个目录中的文件。
在缺省情况下,ln 命令会创建硬链接。如果需要使用 ln 命令来创建符号链接,请指明 -s 标志。
符号链接是指向文件的一个间接指针;它的目录项中包含了它所链接的文件名。符号链接可能会跨越文件系统,可能指向目录。
如果正在将某个文件链接到新的名字,那么只能列出一个文件。如果链接到一个目录,那么可以列出多个文件。
TargetFile 参数是可选的。
如果不指定目标文件,ln 命令会在当前的目录中创建一个新的文件。新的文件继承了指定在 SourceFile 参数中的文件名。
注意:
如果不使用 -s 标志,就不能在文件系统之间链接文件。
如果 TargetDirectory 已经是链接到目录上的一个符号链接,那么 ln 命令将现有的目标视为文件。
这意味着,类似于 ln -fs somepath/lname symdir 的命令不会遵循现有的 symdir 符号链接,作为代替,它会创建一个从 somepath/lname 到 symdir 的新的符号链接。
参数
-f 促使 ln 命令替换掉任何已经存在的目的路径。如果目的路径已经存在,而没有指定 -f 标志,ln 命令不会创建新的链接,而是向标准错误写一条诊断消息并继续链接剩下的 SourceFiles。
-n 指定,如果链接是一个现有的文件,那么不要覆盖文件的内容。 -f 标志重设了这个标志。这是缺省的行为。
-s
促使 ln 命令创建符号链接。符号链接中包含了它所链接的文件的名字。当对链接执行打开操作的时候,会使用到引用文件。对符号链接的 stat
调用会返回链接的目标文件;必须完成lstat 调用来获取链接的信息。可以使用 readlink
调用来读取符号链接的内容。符号链接可能跨越文件系统,指向目录。
注意:当为 -s 标志指定 SourceFile 参数的时候,必须使用绝对路径。如果没有指明绝对路径,那么当 SourceFile 和 TargetFile 参数位于不同的目录中的时候,可能会发生意外的结果。在创建符号链接之前,不需要存在源文件。
退出状态
此命令返回以下的退出值:
0 所有指定的文件都成功链接上了。
0 出现一次错误。
示例
1>为了创建到一个文件的另一个链接(别名),请输入:
ln
-f file1 file2
这会将 file1 链接到新的名称, file2。如果 file2 不存在,那么会创建该文件名。如果 file2
已经存在了,那么这个文件会被替换为指向 file1的一个链接。然后 file1 和 file2
文件名会指向同一个文件。对其中任何一个的更改都会出现在另一个中。如果一个文件名被 rm
命令删除,那么该文件并没有完全被删除,因为它仍然以其它的名字存在。
2>为了将文件链接为另一个目录中的相同名字,请输入:
ln index dir1
这会将 index 链接到新的名称,dir1/index。
注意:在示例 1 中的 file2 是一个文件的名称;在示例 2 中的 dir1 是一个已经存在的目录。
3>为了将几个文件链接为另一个目录中的名称,请输入:
ln file2 dir2/file3 /home/dir1
这会将 file2 链接到新的名称 /home/dir1/file2;将 dir2/file3 链接到新的名称 /home/dir1/file3。
4>如果想要在 ln 命令中使用模式匹配字符,请输入:
ln dir1/* .
这会将 dir1 目录中的所有文件链接到当前目录中, . (点),给他们在 dir1 目录中同样的名称。
注意: 必须在星号和句点之间输入一个空格。
5>为了创建一个符号链接,输入:
ln -s /tmp/test test
这会在当前的目录中创建符号链接 test。 test 文件指向 /tmp/test 文件。如果 /tmp/test 文件已经存在了,那么 cat test 命令可以列出其内容。
6>如果想要在不指明 TargetFile 参数的情况下得到相同的结果,请输入:
ln -s /tmp/test
文件
/usr/bin/ln 包含了 ln 命令。
- 常见配置文件
posted @
2009-07-02 09:37 xiaoxinchen 阅读(124) |
评论 (0) |
编辑 收藏
不用安装,直接解压即可。如果进行JEE开发,可以用eclipse-jee-ganymede-SR2文件,而PHP的话可以直接用PDT。Python可以用基于Apanta的PyDev。
基本操作¶
选项:Windows -> Preference。
安装新特性/插件:Help -> SoftwareUpdates
常用快捷键¶
快捷键的设置和修改在Windows -> Preference ->General -> Keys;
我最常用的:
Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以Alt+/来代替,在keys里找到command 为Content
Assist的,把其Binding改为Alt+/)
这个是我最喜欢的功能,你可以把变量命名的很长,下次引用时只要打首个字母,再打Alt+/,就能写出变量。
Ctrl+Q 定位到最后编辑的地方
Ctrl+Shift+R 全局 打开资源
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
Java编辑器 组织导入 Ctrl+Shift+O
Java编辑器 添加导入 Ctrl+Shift+M
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑的页面(当然是针对上面那条来说了)
Ctrl+1 快速修复
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+D: 删除当前行
Java编辑器 格式化 Ctrl+Shift+F
Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)
Alt+↑ 当前行和上面一行交互位置(同上)
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)
Alt+Shift+Z 使用try/catch块来包围
下面是网上转过来
Eclipse快捷键大全(转载)
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)
Ctrl+D: 删除当前行
Ctrl+Alt+↓ 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)
Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)
Alt+↑ 当前行和上面一行交互位置(同上)
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑的页面(当然是针对上面那条来说了)
Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性
Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Shift+Ctrl+Enter 在当前行插入空行(原理同上条)
Ctrl+Q 定位到最后编辑的地方
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Ctrl+M 最大化当前的Edit或View (再按则反之)
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+O 快速显示 OutLine
Ctrl+T 快速显示当前类的继承结构
Ctrl+W 关闭当前Editer
Ctrl+K 参照选中的Word快速定位到下一个
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
Ctrl+/(小键盘) 折叠当前类中的所有代码
Ctrl+×(小键盘) 展开当前类中的所有代码
Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用Alt+/来代替)
Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)
Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)
Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)
Ctrl+Shift+F4 关闭所有打开的Editer
Ctrl+Shift+X 把当前选中的文本全部变味小写
Ctrl+Shift+Y 把当前选中的文本全部变为小写
Ctrl+Shift+F 格式化当前代码
Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反之)
下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift开头的了)
Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)
Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)
Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)
Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)
Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)
Alt+Shift+I 合并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药(Undo)
编辑
作用域 功能 快捷键
全局 查找并替换 Ctrl+F
文本编辑器 查找上一个 Ctrl+Shift+K
文本编辑器 查找下一个 Ctrl+K
全局 撤销 Ctrl+Z
全局 复制 Ctrl+C
全局 恢复上一个选择 Alt+Shift+↓
全局 剪切 Ctrl+X
全局 快速修正 Ctrl1+1
全局 内容辅助 Alt+/
全局 全部选中 Ctrl+A
全局 删除 Delete
全局 上下文信息 Alt+?
Alt+Shift+?
Ctrl+Shift+Space
Java编辑器 显示工具提示描述 F2
Java编辑器 选择封装元素 Alt+Shift+↑
Java编辑器 选择上一个元素 Alt+Shift+←
Java编辑器 选择下一个元素 Alt+Shift+→
文本编辑器 增量查找 Ctrl+J
文本编辑器 增量逆向查找 Ctrl+Shift+J
全局 粘贴 Ctrl+V
全局 重做 Ctrl+Y
查看
作用域 功能 快捷键
全局 放大 Ctrl+=
全局 缩小 Ctrl+-
窗口
作用域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl+Shift+W
全局 上一个编辑器 Ctrl+Shift+F6
全局 上一个视图 Ctrl+Shift+F7
全局 上一个透视图 Ctrl+Shift+F8
全局 下一个编辑器 Ctrl+F6
全局 下一个视图 Ctrl+F7
全局 下一个透视图 Ctrl+F8
文本编辑器 显示标尺上下文菜单 Ctrl+W
全局 显示视图菜单 Ctrl+F10
全局 显示系统菜单 Alt+-
导航
作用域 功能 快捷键
Java编辑器 打开结构 Ctrl+F3
全局 打开类型 Ctrl+Shift+T
全局 打开类型层次结构 F4
全局 打开声明 F3
全局 打开外部javadoc Shift+F2
全局 打开资源 Ctrl+Shift+R
全局 后退历史记录 Alt+←
全局 前进历史记录 Alt+→
全局 上一个 Ctrl+,
全局 下一个 Ctrl+.
Java编辑器 显示大纲 Ctrl+O
全局 在层次结构中打开类型 Ctrl+Shift+H
全局 转至匹配的括号 Ctrl+Shift+P
全局 转至上一个编辑位置 Ctrl+Q
Java编辑器 转至上一个成员 Ctrl+Shift+↑
Java编辑器 转至下一个成员 Ctrl+Shift+↓
文本编辑器 转至行 Ctrl+L
搜索
作用域 功能 快捷键
全局 出现在文件中 Ctrl+Shift+U
全局 打开搜索对话框 Ctrl+H
全局 工作区中的声明 Ctrl+G
全局 工作区中的引用 Ctrl+Shift+G
文本编辑
作用域 功能 快捷键
文本编辑器 改写切换 Insert
文本编辑器 上滚行 Ctrl+↑
文本编辑器 下滚行 Ctrl+↓
文件
作用域 功能 快捷键
全局 保存 Ctrl+X
Ctrl+S
全局 打印 Ctrl+P
全局 关闭 Ctrl+F4
全局 全部保存 Ctrl+Shift+S
全局 全部关闭 Ctrl+Shift+F4
全局 属性 Alt+Enter
全局 新建 Ctrl+N
项目
作用域 功能 快捷键
全局 全部构建 Ctrl+B
源代码
作用域 功能 快捷键
Java编辑器 格式化 Ctrl+Shift+F
Java编辑器 取消注释 Ctrl+\
Java编辑器 注释 Ctrl+/
Java编辑器 添加导入 Ctrl+Shift+M
Java编辑器 组织导入 Ctrl+Shift+O
Java编辑器 使用try/catch块来包围 未设置,太常用了,所以在这里列出,建议自己设置。
也可以使用Ctrl+1自动修正。
运行
作用域 功能 快捷键
全局 单步返回 F7
全局 单步跳过 F6
全局 单步跳入 F5
全局 单步跳入选择 Ctrl+F5
全局 调试上次启动 F11
全局 继续 F8
全局 使用过滤器单步执行 Shift+F5
全局 添加/去除断点 Ctrl+Shift+B
全局 显示 Ctrl+D
全局 运行上次启动 Ctrl+F11
全局 运行至行 Ctrl+R
全局 执行 Ctrl+U
重构
作用域 功能 快捷键
全局 撤销重构 Alt+Shift+Z
全局 抽取方法 Alt+Shift+M
全局 抽取局部变量 Alt+Shift+L
全局 内联 Alt+Shift+I
全局 移动 Alt+Shift+V
全局 重命名 Alt+Shift+R
全局 重做 Alt+Shift+Y
检出项目¶
首先安装SVN插件(subversive或者subclipse),然后新建Project,从SVN检出项目。需要特别注意的是,要在general / workspace选项中正确设置字符编码,否则可能会出现编译错误。
用Maven构建项目¶
安装IAM之后,在项目的context菜单中选“Maven 2 / Use Maven Dependency Management”,然后就可以管理依赖。
查看数据库¶
打开 Database Perspective 即可。注意要先选择驱动程序,即mysql的java connector的jar,然后才是配置各个连接的jdbc地址。
关于插件¶
插件安装方法(zz)¶
英文教程:http://www.venukb.com/2006/08/20/install-eclipse-plugins-the-easy-way/
有关插件安装问题,四种常用的方法在此特别注明:
#“帮助”->“软件更新”->“查找并安装”->“搜索要安装的新功能部件”->“新建远程站点”(此种方式用于在线更新)
#“帮助”->“软件更新”->“查找并安装”->“搜索要安装的新功能部件”->“新建本地站点”(如果插件已经下载到了本地,请不要用第一种方法)
- 直接拷贝plugins和features两个目录下的内容置于$Eclipse_Home$/对应的plugins和features下面
- 用link外链接与外部插件关联
最菜的,一般用第一种方法,而大部分生手一般选择第二或者第三种方法,用得习惯的一般选择最后一种方式。此四类方法优劣势对比如下:
前三种方法都会将插件文件拷贝至相$Eclipse_Home$/对应的plugins和features目录下,从本质上看,没多大区别,并且插件只能
安装和禁用,不能卸载(当然,如果你对插件对应的目录和文件都很熟悉的话,可以通过直接删除拷进去的文件来达到卸载插件的目的),但方法一和方法二在安装
插件的时候很容易出错或者是产生冲突,特别是当你用了Myeclipse插件、中文包的同时,又想安装HibernateSynchronizer、
Jode Compiler(Class反编译工具)、Visual Editor等插件时,及有可能导致Myeclipse插件和中文包失效。
所以,如果插件已经下载到了本地,请直接拷贝至$Eclipse_Home$/对应的plugins和features目录下,也就是用方法三,这样能避免冲突。
方
法四是将所有的插件用一个外部目录存放起来,假如是D:\plug-in,将上面所示的插件目录文件全部拷贝到该目录下,比如Tomcat插件,此时的文
件路径就是D:\plug-in\tomcat_plug\eclipse\plugins
\com.sysdeo.eclipse.tomcat_3.1.0.beta(请注意,方法四一定要严格这样的目录路径放置文件)。然后
在$Eclipse_Home$下新建一个links目录,并在links目录下建立关联文件,假如是tomcat.link,在建立的关联文件中加入如
下语句:
path=D:/plug-in/tomcat_plug
还可以写成相对路径的形式。剩下的事情,不用我说你肯定都知道了,就是重启Eclipse,在Dos窗口下进入Eclipse安
装目录,键入命令eclipse
-clean,回车,或者进入$Eclipse_Home$/configuration目录,删除org.eclipse.update后再重新启动
Eclipse。
QA相关插件¶
参考:http://www.ibm.com/developerworks/cn/java/j-ap01117/
CheckStyle http://eclipse-cs.sourceforge.net/update/
Coverlipse http://coverlipse.sf.net/update
PMD http://pmd.sourceforge.net/eclipse/
JDepend http://andrei.gmxhome.de/eclipse/
Metrics http://metrics.sourceforge.net/update
FindBugs http://findbugs.cs.umd.edu/eclipse
参考资源¶
http://www.ibm.com/developerworks/cn/eclipse/resources.html
http://www.eclipseplugincentral.com/
posted @
2009-07-02 09:36 xiaoxinchen 阅读(259) |
评论 (0) |
编辑 收藏
posted @
2009-07-02 09:35 xiaoxinchen 阅读(107) |
评论 (0) |
编辑 收藏
快速入门
欢迎使用BeanShell.这是一个速成课程。我们将省去一些重要的选项和细节。要学习更多的内容请看本User's Guide的其它部分。
下载和运行BeanShell
请到http://www.beanshell.org下载最新的JAR文件。你可以用图形桌面模式和命令行模式起动BeanShell。
如果你只是要玩一玩BeanShell,你可以在BeanShell的jar文件上双击来起动BeanShell的桌面。但不管怎样,如果你要让BeanShell与你的类与应用程序一起工作就必须将BeanShell的jar文件加到classpath中。
你可以将BeanShell的jar文件拖到JAVA_HOME的ext目录也可以直接加到classpath中。
- windows用户请将bsh.jar放在JAVA_HOME/jre/lib/ext文件夹,OSX用户可以放在/Library/Java/Extensions.
或者增加BeanShell到你的classpath目录,如:
unix: export CLASSPATH=$CLASSPATH:bsh-xx.jar
windows:set classpath %classpath%;bsh-xx.jar
然后你就可以运行BeanShell在GUI或命令行模式:
- java bsh.Console // run the graphical desktop
or
java bsh.Interpreter // run as text-only on the command line
or
java bsh.Interpreter filename [ args ] // run script file
可以在你的应用程序内部来运行,也可以作为debug及servlet的远程服务器模式,或一个Applet内部来运行BeanShell。请参考"BeanShell Modes of Operation"获得更多详情。
BeanShell GUI
用GUI模式启动BeanShell后,将打开一个桌面视窗。用鼠标右击在桌面的背景上,你可以打开另一个控制台视窗及其它的工具如一个简单的类游览器。
每一个控制台视窗运行一个独立的BeanShell解释器。这个图形化的控制台支持基本的历史命令,行编辑,剪切和粘贴,甚至类和变量名的自动完成功能。从控制台你能开启一个简单的编辑视窗。在它里面,你可以编写脚本和使用‘eval’选项求表达式的值。
Java语句和表达式
BeanShell能理解标准的JAVA语句,表达式,和方法宣告。语句和表达式的内容可以是:变量,宣告,赋值,方法调用,循环,条件等。
在
Java程序中你必须严格的使用它们,但在BeanShell中,你可以用“宽松类型”(loosely
typed)的方式来使用它们。也就是说,你可以在写脚本时偷懒,不进行变量类型的宣告(在原始数据类型和对象都可以)。如果你试着用错变量类
型,BeanShell将会给出一个错误。
这里有一些例子:
- foo = "Foo";
four = (2 + 2)*2/2;
print( foo + " = " + four ); // print() is a BeanShell command
// Do a loop
for (i=0; i<5; i++)
print(i);
// Pop up a frame with a button in it
button = new JButton( "My Button" );
frame = new JFrame( "My Frame" );
frame.getContentPane().add( button, "Center" );
frame.pack();
frame.setVisible(true);
有用的BeanShell命令
在
刚才那个例子中我们用了一个内建在BeanShell中的一个方便的命令print(),来显示变量的值。print()跟ava的
System.out.println()非常的相像,除非它能保证输出总是命令行。print()也可以显示一些对象的类型(如数组),但比Java的
更详细。另一个相关的命令是show(),用来开启与关闭显示你输入的每一行的结果。
这儿是一些其它的BeanShell的命令:
source(), run() - 将一个bsh脚本读到解释器或运行在另一个解释器。
frame() - 显示一个Frame或JFrame的GUI组件.
load(), save() - 载入和保存一个序列化的对象到一个文件.
cd(), cat(), dir(), pwd(), etc. - 类unix的shell命令。
exec() - 运行一个本地的程序。
javap() - 打印一个对象的方法和字段,类似于Java的javap命令。
setAccessibility() - 开启无限制的存取private 和protected的组件。
要获得更多的信息请查看BeanShell命令的详细清单。
提示:
BeanShell命令并不是真的"内建"其中的,而是作为脚本方法自动从classpath载入的. 你可以扩展基本命令集并加到classpath中作为自订义的脚本来使用。
脚本方法
你可以在bsh中宣告和使用方法,就像在java的类中一样。
- int addTwoNumbers( int a, int b ) {
return a + b;
}
sum = addTwoNumbers( 5, 7 ); // 12
bsh的方法可以有动态的(宽松的)参数和返回类型。
- add( a, b ) {
return a + b;
}
foo = add(1, 2); // 3
foo = add("Oh", " baby"); // "Oh baby"
实现Interface
注意:如果要BeanShell能实现任意的Interface,必须有jdk1.3及以上支持。
你可以在脚本中用标准的Java内部类的语法来实现Interface.例如:
- ActionListener scriptedListener = new ActionListener() {
actionPerformed( event ) { ... }
}
你
可以不用实现Interface的所有方法,而只用实现你需要的方法。如果代码中调用了未被实现的方法,将丢出异常。如果你想重载大量的方法的行为--例
如为日志生成一个"哑"适配器--你可以在脚本对象中实现一个特殊的方法:invoke(name,args)。invoke()方法用来处理任何未被定
义的方法的调用:
- ml = new MouseListener() {
mousePressed( event ) { ... }
// handle the rest
invoke( name, args ) { print("Method: "+name+" invoked!");
}
脚本对象
在
BeanShell中,和在JavaScript与Perl中一样,脚本对象是用封闭的方法体一构成的。通过在方法未尾返回一个特殊值"this",你就
可以像使用方法一样调用这个对象了。在这个方法调用时,你可以给与它任何的值。通常对象内部需要包括方法,所以BeanShell的脚本方法在一定程度上
可再包含一些方法以构成脚本对象。例如:
- foo() {
print("foo");
x=5;
bar() {
print("bar");
}
return this;
}
myfoo = foo(); // prints "foo"
print( myfoo.x ); // prints "5"
myfoo.bar(); // prints "bar"
如果这些代码对你来说很陌生,别急,请用户手册可得到更透彻的解释。
在
你的脚本中,BeanShell脚本对象(也就是先前例子中的"this"参照)能自动实现任何JAVA介面类型。当JAVA代码调用相应与之通讯的脚本
方法内的方法。当你试着将脚本对象作为参数传给Java方法时,BeanShell会自动将它造型(cast)为相应的类型。如要传递BeanShell
外部的对象时,你可以在需要时显式的进行造型(cast).请看用户手册中的详细内容。
从你的应用程序调用BeanShell
通过建立一个BeanShell解释器,使用eval()或source()命令,你可以在你的应用程序中求文本表达式的值和运行脚本。如果你希望在你的脚本内部使用一个对象,可以用set()方法传递对象的变量参照给BeanShell,并通过get()方法取得结果。
- import bsh.Interpreter;
Interpreter i = new Interpreter(); // Construct an interpreter
i.set("foo", 5); // Set variables
i.set("date", new Date() );
Date date = (Date)i.get("date"); // retrieve a variable
// Eval a statement and get the result
i.eval("bar = foo*10");
System.out.println( i.get("bar") );
// Source an external script file
i.source("somefile.bsh");
BeanShell将成为Java平台上的第三种编程语言
|
2005-06-08 点击:8 来源:CSDN 作者:CSDN |
JCP接纳了一个新的技术规范进入标准化进程,这个编号为JSR-274的技术规范将把BeanShell引入为Java平台上支持的又一种编程语言。
JSR-
274(http://jcp.org/en/jsr/detail?id=274)是由 Patrick
Niemeyer提交的技术规范,其目标是将BeanShell脚本语言(http://www.beanshell.org/)规范化为Java虚拟机
平台上支持的第三种编程语言。除了Java之外,Java虚拟机还支持Groovy脚本语言。Doug
Lea、Apache和Google三个JCP执委会成员对此规范表示了支持。
按照Java最初的设计思路,有很多语言都可以在JVM上
运行(详细列表参见http://en.wikipedia.org/wiki/List_of_Java_scripting_languages),
但这些语言大多没有流行起来。直到2004年为止,Java平台事实上只有一种编程语言,也就是Java。2004年3月,Groovy(JSR-
241)成为了Java平台上的第二种编程语言。
消息全文请看:http://rmh.blogs.com/weblog/2005/05/beanshell_the_3.html
|
http://www.cn-java.com/target/news.php?news_id=2450
简介:
BeanShell是一种脚本语言,一种完全符合java语法的java脚本语言,并且又拥有自己的一些语法和方法,beanShell是一种松散类型的脚本语言(这点和JS类似)。
下载地址:http://www.beanshell.org
设置环境
l 把;bsh-xx.jar放到$JAVA_HOME/jre/lib/ext文件夹下
l unix: export CLASSPATH=$CLASSPATH:bsh-xx.jar
l windows: set classpath %classpath%;bsh-xx.jar
运行方式:
l 界面UI方式 :java bsh.Console
l 命令行方式 :java bsh.Interpreter
l 运行脚本文件:java bsh.Interpreter filename [ args ]
简单举例:
在classpath中设置好环境变量,打开dos窗口,键入:java bsh.Console命令
出现BeanShell图片代表设置成功,beanshell开始运行
测试内容:
设置变量
foo = "Foo";
four = (2 + 2)*2/2;
打印变量
print( foo + " = " + four );
循环
for (i=0; i<5; i++)
print(i);
在窗口中打印按钮
button = new JButton( "My Button" );
frame = new JFrame( "My Frame" );
frame.getContentPane().add( button, "Center" );
frame.pack();
frame.setVisible(true);
完整代码:
foo = "Foo";
four = (2 + 2)*2/2;
print( foo + " = " + four );
for (i=0; i<5; i++)
print(i);
button = new JButton( "My Button" );
frame = new JFrame( "My Frame" );
frame.getContentPane().add( button, "Center" );
frame.pack();
frame.setVisible(true);
在窗口中输入上面的代码
敲回车执行,运行结果如图
说明:
因为beanshell是松散类型的脚本语言因此可以直接写
foo = "Foo";
four = (2 + 2)*2/2;
print是beanshell提供一种简单的打印命令相当于java中的System.out.println()
其他的beanshell脚本命令
· source(), run() – 读取,或者运行一个脚本文件
· frame() – 显示一个窗口
· load(), save() – 读取或者保存一个脚本对象到文件
· cd(), cat(), dir(), pwd(), etc. 使用Unix下面的命令
· exec() – 运行一个本地的方法
· javap() –使用javap命令.
· setAccessibility() – 设置可以接收private和protected类型的变量
BeanShell命令不一定都是内置的脚本命令,脚本方法会自动从classpath中取方法使用,因此你可以添加你自己的脚本到classpath中来扩充基本的命令
脚本方法
一般的方法:
int addTwoNumbers( int a, int b ) {
return a + b;
}
sum = addTwoNumbers( 5, 7 ); // 12
也可以使用动态的变量类型(无状态)方法
add( a, b ) {
return a + b;
}
foo = add(1, 2); // 3
foo = add(1, “2”); //”12” 只要有一个为字符串全部按照字符串处理,系统不会根据1是数字在前把“2”转换成数字处理(特别注意)
foo = add("Oh", " baby"); // "Oh baby"
实现接口
实现任何接口需要java1.3或者更高
可以使用缺省的java匿名类的语法实现一个接口类,例如:
ActionListener scriptedListener = new ActionListener() {
actionPerformed( event ) { ... }
}
不需要实现接口的所有的方法,只需要实现你使用的方法即可,如果使用你没有实现的方法,beanshell将抛出一个错误,
ml = new MouseListener() {
mousePressed( event ) { ... }
// handle the rest
invoke( name, args ) { print("Method: "+name+" invoked!");
}
脚本对象
使用特殊的关键字this可以创建一个对象(根JS类似)
foo() {
print("foo");
x=5;
bar() {
print("bar");
}
return this;
}
myfoo = foo(); // prints "foo"
print( myfoo.x ); // prints "5"
myfoo.bar(); // prints "bar"
从应用程序中调用BeanShell
创建一个BeanShell的解释器(interpreter)用eval()和source()命令可以对一个字符串求值和运行一个脚本文件
使用set()方法可以给一个对象传入一个变量的参考
使用get()方法可以重新得到一个变量的结果
完整代码:
package cn.com.sparknet.util;
import bsh.*;
import java.util.*;
public class BeanShell {
public static void main(String[] args) {
try {
Interpreter interpreter = new Interpreter(); // 构造一个解释器
interpreter.set("foo", 5); // 设置变量
interpreter.set("date", new Date()); //设置一个时间对象
Date date = (Date) interpreter.get("date"); // 重新得到时间变量
interpreter.println(date.toString()); //打印时间变量
interpreter.eval("bar = foo*10"); // 对一段脚本求值,并得到结果
System.out.println(interpreter.get("bar")); //打印变量
interpreter.source("d:\\helloWorld.bsh"); // 导入并执行一个脚本文件
}
catch (Exception e) {
//如果发生异常,写入日志文件
Log.error(new BeanShell(), "main", FormatDate.getCurrDate(), e.getMessage());
}
}
}
BeanShell语法
BeanShell是一种最原始的java解释器。
标准的java语法
/*
Standard Java syntax
*/
// Use a hashtable
Hashtable hashtable = new Hashtable();
Date date = new Date();
hashtable.put( "today", date );
// Print the current clock value
print( System.currentTimeMillis() );
// Loop
for (int i=0; i<5; i++)
print(i);
// Pop up a frame with a button in it
JButton button = new JButton( "My Button" );
JFrame frame = new JFrame( "My Frame" );
frame.getContentPane().add( button, "Center" );
frame.pack();
frame.setVisible(true);
松散类型的java语法
/*
Loosely Typed Java syntax
*/
// Use a hashtable
hashtable = new Hashtable();
date = new Date();
hashtable.put( "today", date );
// Print the current clock value
print( System.currentTimeMillis() );
// Loop
for (i=0; i<5; i++)
print(i);
// Pop up a frame with a button in it
button = new JButton( "My Button" );
frame = new JFrame( "My Frame" );
frame.getContentPane().add( button, "Center" );
frame.pack();
frame.setVisible(true);
异常处理
标准的java异常
try {
int i = 1/0;
} catch ( ArithmeticException e ) {
print( e );
}
松散的异常处理(类似JS)
try {
...
} catch ( e ) {
...
}
松散类型变量的作用范围
标
准的java程序的变量作用范围是在一个模块中的(在模块中声明的变量),而在松散类型的语言中如果在一个模块中没有指定一个变量的类型,则认为是一个全
局变量(只有它以后的代码可以使用该变量,系统在调用该变量的时候自动生成一个全局变量,也就为什么在调用模块之前不能使用该变量的原因)
// Arbitrary code block
{
y = 2; // Untyped variable assigned
int x = 1; // Typed variable assigned
}
print( y ); // 2
print( x ); // Error! x is undefined.
// Same with any block statement: if, while, try/catch, etc.
if ( true ) {
y = 2; // Untyped variable assigned
int x = 1; // Typed variable assigned
}
print( y ); // 2
print( x ); // Error! x is undefined.
同样也使用于for-loop, if-else等循环语句
for( int i=0; i<10; i++ ) { // typed for-init variable
j=42;
}
print( i ); // Error! 'i' is undefined.
print( j ); // 42
for( z=0; z<10; z++ ) { } // untyped for-init variable
print( z ); // 10
方便灵活的语法
标准的java语法
java.awt.Button button = new java.awt.Button();
button.setLabel(“javaButton”);
松散的语法
button = new java.awt.Button();
button.label = "my button";
你也可以使用{}来对一个对象设置属性
b = new java.awt.Button();
b{"label"} = "my button"; // Equivalent to: b.setLabel("my button");
h = new Hashtable();
h{"foo"} = "bar"; // Equivalent to: h.put("foo", "bar");
包装和未包装(box和unbox)
BeanShell自动转为简单类型
i=5;
iw=new Integer(5);
print( i * iw ); // 25
导入类和包
import javax.xml.parsers.*;
import mypackage.MyClass;
超级导入法:
import *;
BeanShell默认导入下面的包
· java.lang
· java.io
· java.util
· java.net
· java.awt
· java.awt.event
· javax.swing
· javax.swing.event
友好文档实体
BeanShell支持特殊的文档操作类型内容
@gt > @lt <
@lteq <= @gteq >=
@or || @and &&
@bitwise_and & @bitwise_or |
@left_shift << @right_shift >>
@right_unsigned_shift >>> @and_assign &=
@or_assign |= @left_shift_assign <<=
@right_shift_assign >>= @right_unsigned_shift_assign >>>=
脚本方法
你可以定义方法象java中的定义方法一样
int addTwoNumbers( int a, int b ) {
return a + b;
}
你可以使用内馅的BeanShell方法使用他们
sum = addTwoNumbers( 5, 7 );
只有BeanShell变量可以被动态定义为动态类型,方法可以有动态的参数以及返回类型
add( a, b ) {
return a + b;
}
在这个方法中,BeanShell将动态的决定类型当这个方法被调用时并且能够准确的计算出你想要的结果
foo = add(1, 2);
print( foo ); // 3
foo = add("Oh", " baby");
print( foo ); // Oh baby
在第一个例子中BeanShell将把参数定义为数字型,并返回数字型
在第二个例子中BeanShell将把参数定义为字符型,并返回字符对象
变量和方法的可见范围
就像您所预期的那样,在方法内您可以参考到上下文中上面的变量和方法
a = 42;
someMethod() { ... }
foo() {
print( a );
someMethod(); // invoke someMethod()
}
// invoke foo()
foo(); // prints 42
如果一个变量只有在方法内使用请定义成局部变量,即加上类型,如果是全局变量请在方法外定义
var = "global";
foo() {
print(var);
String var = "local";
print(var);
}
foo();
print(var);
将打印出
global
local
global
方法内的var(第四行)变量属于局部变量,不会覆盖全局变量var(第一行)的因此改变var(第四行)变量不会影响到全局变量var(第一行)
范围参考:super
使用super关键字可以在局部参考到全局变量
var = "global";
foo() {
String var = "local";
print(var);
print(super.var);
}
foo();
将输出
local
global
脚本对象
this对象
在java标准语言中可以使用this返回一个类的一个实例
// MyClass.java
MyClass {
Object getObject() {
return this; // return a reference to our object
}
}
在这个例子中getObject() 方法是返回MyClass类的一个实例
在BeanShell中对象中的变量只是局部的变量在对象内可以使用,在对象外是不可以使用(不同于前面for-loop,if-else中的使用);
// Define the foo() method:
foo() {
bar = 42;
print( bar );
}
// Invoke the foo() method:
foo(); // prints 42
print( bar ); // Error, bar is undefined here
可以使用this返回对象,使用对象加上“.”运算符参考属性(类似JS)
foo() {
bar = 42;
return this;
}
fooObj = foo();
print( fooObj.bar ); // prints 42!
同样对象中也可以定义一些方法
foo() {
bar() {
...
}
}
例如
foo() {
int a = 42;
bar() {
print("The bar is open!");
}
bar();
return this;
}
// Construct the foo object
fooObj = foo(); // prints "the bar is open!"
// Print a variable of the foo object
print ( fooObj.a ) // 42
// Invoke a method on the foo object
fooObj.bar(); // prints "the bar is open!"
也可以把bar()和foo也可以代参数
foo() {
return this;
}
bar(int a) {
print("The bar is open!" + a);
}
foo().bar(1);
也可以把bar()方法定义到对象外面
foo() {
bar(int a) {
print("The bar is open!" + a);
}
return this;
}
foo().bar(1);
BeanShell一种松散的脚本语言,有很多中声明的方法可以使用
This super global
This是参考当前对象
Super是参考父亲对象
Global是参考最上层对象
super.super.super...foo = 42; // Chain super. to reach the top
global.foo = 42;
简单例子:
文本拖动:
dragText() {
f = new Frame("Drag in the box");
f.setFont( new Font("Serif", Font.BOLD, 24) );
f.setSize(300, 300);
f.show();
gc = f.getGraphics();
gc.setColor(Color.cyan);
mouseDragged( e ) {
gc.drawString("Drag Me!", e.getX(), e.getY());
}
mouseMoved( e ) { }
f.addMouseMotionListener( this );
}
简单画图
import bsh.util.BshCanvas; // BshCanvas simply buffers graphics
graph( int width, int height ) {
canvas=new BshCanvas();
canvas.setSize( width, height );
frame=frame( canvas );
graphics=canvas.getBufferedGraphics();
// draw axis
graphics.setColor( Color.red );
graphics.drawLine( 0, height/2, width, height/2 );
graphics.drawLine( width/2, 0, width/2, height );
graphics.setColor( Color.black );
plot(int x, int y) {
graphics.fillOval( (x+width/2-1), (y+height/2-1), 3, 3);
canvas.repaint();
}
return this;
}
drawSin( graph ) {
for (int x=-100; x<100; x++ ) {
y=(int)(50*Math.sin( x/10.0 ));
graph.plot( x, y );
}
}
简单web浏览器
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.event.*;
import java.awt.*;
JFrame browser( startingUrl ) {
invoke( method, args ) {}
windowClosing(WindowEvent we) {
we.getWindow().setVisible(false);
}
setPage( url ) {
try {
pane.setPage( url );
} catch(Exception e) {
statusBar.setText("Error opening page: "+url);
}
}
hyperlinkUpdate( HyperlinkEvent he ) {
type = he.getEventType();
if (type == HyperlinkEvent.EventType.ENTERED) {
pane.setCursor(
Cursor.getPredefinedCursor( Cursor.HAND_CURSOR) );
statusBar.setText(he.getURL().toString());
} else
if (type == HyperlinkEvent.EventType.EXITED) {
pane.setCursor( Cursor.getDefaultCursor() );
statusBar.setText(" ");
} else {
setPage( he.getURL() );
if (urlField != null)
urlField.setText(he.getURL().toString());
}
}
frame = new JFrame("Browser");
frame.setSize(400,300);
frame.addWindowListener( this );
urlPanel = new JPanel();
urlPanel.setLayout(new BorderLayout());
urlField = new JTextField(startingUrl);
urlPanel.add(new JLabel("Site: "), BorderLayout.WEST);
urlPanel.add(urlField, BorderLayout.CENTER);
statusBar = new JLabel(" ");
pane = new JEditorPane();
pane.setEditable(false);
setPage( startingUrl );
jsp = new JScrollPane(pane);
frame.getContentPane().add(jsp, BorderLayout.CENTER);
frame.getContentPane().add(urlPanel, BorderLayout.SOUTH);
frame.getContentPane().add(statusBar, BorderLayout.NORTH);
// This is the equivalent of an inner class in bsh.
urlTextHandler() {
actionPerformed(ActionEvent ae) {
setPage( ae.getActionCommand() );
}
return this;
}
urlField.addActionListener( urlTextHandler() );
pane.addHyperlinkListener( (HyperlinkListener)this );
return frame;
}
browser = browser("http://java.sun.com/");
browser.show();
更多的文档参考BeanShell网站
http://www.beanshell.org
posted @
2008-10-08 14:34 xiaoxinchen 阅读(2464) |
评论 (0) |
编辑 收藏
在处理一个大数据量数据库的时候
突然发现mysql对于count(*)的不同处理会造成不同的结果
比如执行
SELECT count(*) FROM tablename
即使对于千万级别的数据mysql也能非常迅速的返回结果
而对于
SELECT count(*) FROM tablename WHERE…..
mysql的查询时间开始攀升
仔细查阅累下手册,发现当没有WHERE语句对于整个mysql的表进行count运算的时候
MyISAM类型的表中保存有总的行数,而当添加有WHERE限定语句的时候Mysql需要对整个表进行检索
从而得出count的数值
突然又想起来看到的不少新兴的php程序对于count的处理并没有很好的意思到这点
记录下
顺便提下mysql的DISTINCT的关键字有很多你想不到的用处
1.在count 不重复的记录的时候能用到
比如SELECT COUNT( DISTINCT id ) FROM tablename;
就是计算talbebname表中id不同的记录有多少条
2,在需要返回记录不同的id的具体值的时候可以用
比如SELECT DISTINCT id FROM tablename;
返回talbebname表中不同的id的具体的值
3.上面的情况2对于需要返回mysql表中2列以上的结果时会有歧义
比如SELECT DISTINCT id, type FROM tablename;
实际上返回的是 id与type同时不相同的结果,也就是DISTINCT同时作用了两个字段,必须得id与tyoe都相同的才被排除了,与我们期望的结果不一样
4.这时候可以考虑使用group_concat函数来进行排除,不过这个mysql函数是在mysql4.1以上才支持的
5.其实还有另外一种解决方式,就是使用
SELECT id, type, count(DISTINCT id) FROM tablename
虽然这样的返回结果多了一列无用的count数据(或许你就需要这个我说的无用数据)
返回的结果是 只有id不同的所有结果和上面的4类型可以互补使用,就是看你需要什么样的数据了
posted @
2008-10-07 14:46 xiaoxinchen 阅读(251) |
评论 (0) |
编辑 收藏
Lucene,作为一种全文搜索的辅助工具,为我们进行条件搜索,无论是像Google,Baidu之类的搜索引擎,还是论坛中的搜索功能,还是其它
C/S架构的搜索,都带来了极大的便利和比较高的效率。本文主要是利用Lucene对MS Sql Server
2000进行建立索引,然后进行全文索引。至于数据库的内容,可以是网页的内容,还是其它的。本文中数据库的内容是图书馆管理系统中的某个作者表
-Authors表。
因为考虑到篇幅的问题,所以该文不会讲的很详细,也不可能讲的很深。
本文以这样的结构进行:
1.介绍数据库中Authors表的结构
2.为数据库建立索引
3.为数据库建立查询功能
4.在web界面下进行查询并显示结果
1.介绍数据库中Authors表的结构
字段名称 字段类型 字段含义
Au_id Varchar(11) 作者号
Au_name Varchar(60) 作者名
Phone Char(12) 电话号码
Address Varchar(40) 地址
City Varchar(20) 城市
State Char(2) 省份
Zip Char(5) 邮编
contract Bit(1) 外键(关系不大)
表中的部分内容:
2.为数据库建立索引
首先建立一个类TestLucene.java。这个类就是对数据库进行建立索引,编写查询条件等。
当然,最开始就是建立数据库连接。连接代码这里就省略了。^_^
接着,新建一个方法getResutl(String),它返回的是数据库表Authors的内容。具体代码如下:
public ResultSet getResult(String sql){
try{
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
return rs;
}
catch(SQLException e){
System.out.println(e);
}
return null;
}
然后,为数据库建立索引。
首先要定义一个IndexWriter(),它是将索引写进Lucene自己的数据库中,它存放的位置是有你自己定义的。在定义
IndexWriter是需要指定它的分析器。Lucene自己自带有几个分析器,例
如:StandarAnalyzer(),SimpleAnalyzer(),StopAnalyzer()等。它作用是对文本进行分析,判断如何进行切
词。
接着,要定义一个Document。Document相当于二维表中一行数据一样。Document里包含的是Field字段,Field相当于数据库中一列,也就是一个属性,一个字段。
最后应该对IndexWriter进行优化,方法很简单,就是writer.optimize().
具体代码如下:
public void Index(ResultSet rs){
try{
IndexWriter writer = new IndexWriter("d:/index/", getAnalyzer(), true);
while(rs.next()){
Document doc=new Document();
doc.add(Field.Keyword("id",rs.getString("au_id")));
doc.add(Field.Text("name",rs.getString("au_name")));
doc.add(Field.UnIndexed("address",rs.getString("address")));
doc.add(Field.UnIndexed("phone",rs.getString("phone")));
doc.add(Field.Text("City",rs.getString("city")));
writer.addDocument(doc);
}
writer.optimize();
writer.close();
}
catch(IOException e){
System.out.println(e);
}
catch(SQLException e){
System.out.println(e);
}
}
public Analyzer getAnalyzer(){
return new StandardAnalyzer();
}
3.为数据库建立查询功能
在类TestLucene中建立一个新的方法searcher(String),它返回的是一个搜索的结构集,相当于数据库中的ResultSet一样。它代的参数是你要查询的内容。这里,我把要查询的字段写死了。你可以在添加一个参数表示要查询的字段。
这里主要有两个对象IndexSearcher和Query。IndexSearcher是找到索引数据库,Query是处理搜索,它包含了三个参数:查询内容,查询字段,分析器。
具体代码如下:
public Hits seacher(String queryString){
Hits hits=null;;
try{
IndexSearcher is = new IndexSearcher("D:/index/");
Query query=QueryParser.parse(queryString,"City",getAnalyzer());
hits=is.search(query);
}catch(Exception e){
System.out.print(e);
}
return hits;
}
4.在web界面下进行查询并显示结果
这里建立一个Jsp页面TestLucene.jsp进行搜索。
在TestLucene.jsp页面中首先引入类
<%@ page import="lucenetest.LucentTest"%>
<%@ page import="org.apache.lucene.search.*,org.apache.lucene.document.*" %>
然后定义一个LuceneTest对象,获取查询结果集:
LucentTest lucent=new LucentTest();
Hits hits=lucent.seacher(request.getParameter("queryString"));
定义一个Form,建立一个查询环境:
<form action="TestLucene.jsp">
<input type="text" name="queryString"/>
<input type="submit" value="搜索"/>
</form>
显示查询结果:
<table>
<%if(hits!=null){%>
<tr>
<td>作者号</td>
<td>作者名</td>
<td>地址</td>
<td>电话号码</td>
</tr>
<% for(int i=0;i<hits.length();i++){
Document doc=hits.doc(i);
%>
<tr>
<td><%=doc.get("id") %></td>
<td><%=doc.get("name") %></td>
<td><%=doc.get("address") %></td>
<td><%=doc.get("phone") %></td>
</tr>
<% }}%>
</table>
posted @
2008-08-29 13:59 xiaoxinchen 阅读(209) |
评论 (0) |
编辑 收藏
中国有很多精于编码的人,但是中国软件行业,尤其是网络应用开发方面误区很大,很难形成有规模的软件开发力量和产品能力,不但比美国差距甚远,和印
度相比也是颇有不如。这些问题不是在于中国程序员的智商和工作努力状况,也不是在于国家和民间对开发的投入程度,而是很大程度上,有一些对技术,对程序开
发,对项目设计方面的思想误区,这些误区,导致了软件行业的产品化能力不足,缺乏规模化和大型复用系统研发能力,可以说,改变认识误区,是解决软件行业小
作坊模式和个体英雄模式所带来的局限性的重要工作。
程序员是一种技术工作,在IT的发展中有相当重要的地位,从底层硬件通讯协议的建立,到数据传输层的处理,到操作系统的建设,到数据库平台的建设,一直到应用层上各种数据营销平台的搭建,程序员在里面都扮演着举足轻重的角色并为IT事业的发展做出了巨大的贡献。
中
国有很多小朋友,他们18,9岁或21,2岁,通过自学也写了不少代码,他们有的代码写的很漂亮,一些技术细节相当出众,也很有钻研精神,但是他们被一些
错误的认识和观点左右,缺乏对系统,对程序的整体理解能力,这些人,一个网上的朋友说得很好,他们实际上只是一些Codingfans,压根没有资格称
为程序员,但是据我所知,不少小网络公司的CTO就是这样的codingfans,拿着吓人的工资,做着吓人的项目,项目的结局通常也很吓人。
程序员基本素质:
作一个真正合格的程序员,或者说就是可以真正合格完成一些代码工作的程序员,应该具有的素质。
1:团队精神和协作能力
把
它作为基本素质,并不是不重要,恰恰相反,这是程序员应该具备的最基本的,也是最重要的安身立命之本。把高水平程序员说成独行侠的都是在呓语,任何个人的
力量都是有限的,即便如linus这样的天才,也需要通过组成强大的团队来创造奇迹,那些遍布全球的为linux写核心的高手们,没有协作精神是不可想象
的。独行侠可以作一些赚钱的小软件发点小财,但是一旦进入一些大系统的研发团队,进入商业化和产品化的开发任务,缺乏这种素质的人就完全不合格了。
2:文档习惯
说
高水平程序员从来不写文档的肯定是乳臭未干的毛孩子,良好的文档是正规研发流程中非常重要的环节,作为代码程序员,30%的工作时间写技术文档是很正常
的,而作为高级程序员和系统分析员,这个比例还要高很多。缺乏文档,一个软件系统就缺乏生命力,在未来的查错,升级以及模块的复用时就都会遇到极大的麻
烦。
3:规范化,标准化的代码编写习惯
作为一些外国知名软件公司的规矩,代码的变量命名,代码内注释格式,甚至嵌套中行缩进的长度和函数间的空行数字都有明确规定,良好的编写习惯,不但有助于代码的移植和纠错,也有助于不同技术人员之间的协作。
有些codingfans叫嚣高水平程序员写的代码旁人从来看不懂,这种叫嚣只能证明他们自己压根不配自称程序员。代码具有良好的可读性,是程序员基本的素质需求。
再看看整个linux的搭建,没有规范化和标准化的代码习惯,全球的研发协作是绝对不可想象的。
4:需求理解能力
程
序员需要理解一个模块的需求,很多小朋友写程序往往只关注一个功能需求,他们把性能指标全部归结到硬件,操作系统和开发环境上,而忽视了本身代码的性能考
虑,有人曾经放言说写一个广告交换程序很简单,这种人从来不知道在百万甚至千万数量级的访问情况下的性能指标是如何实现的,对于这样的程序员,你给他深蓝
那套系统,他也做不出太极链的并访能力。性能需求指标中,稳定性,并访支撑能力以及安全性都很重要,作为程序员需要评估该模块在系统运营中所处的环境,将
要受到的负荷压力以及各种潜在的危险和恶意攻击的可能性。就这一点,一个成熟的程序员至少需要2到3年的项目研发和跟踪经验才有可能有心得。
5:复用性,模块化思维能力
经常可以听到一些程序员有这样的抱怨,写了几年程序,变成了熟练工,每天都是重复写一些没有任何新意的代码,这其实是中国软件人才最大浪费的地方,一些重复性工作变成了熟练程序员的主要工作,而这些,其实是完全可以避免的。
复
用性设计,模块化思维就是要程序员在完成任何一个功能模块或函数的时候,要多想一些,不要局限在完成当前任务的简单思路上,想想看该模块是否可以脱离这个
系统存在,是否可以通过简单的修改参数的方式在其他系统和应用环境下直接引用,这样就能极大避免重复性的开发工作,如果一个软件研发单位和工作组能够在每
一次研发过程中都考虑到这些问题,那么程序员就不会在重复性的工作中耽误太多时间,就会有更多时间和精力投入到创新的代码工作中去。
一些好的程序模块代码,即便是70年代写成的,拿到现在放到一些系统里面作为功能模块都能适合的很好,而现在我看到的是,很多小公司软件一升级或改进就动辄全部代码重写,大部分重复性工作无谓的浪费了时间和精力。
6:测试习惯
作
为一些商业化正规化的开发而言,专职的测试工程师是不可少的,但是并不是说有了专职的测试工程师程序员就可以不进行自测;软件研发作为一项工程而言,一个
很重要的特点就是问题发现的越早,解决的代价就越低,程序员在每段代码,每个子模块完成后进行认真的测试,就可以尽量将一些潜在的问题最早的发现和解决,
这样对整体系统建设的效率和可靠性就有了最大的保证。
测试工作实际上需要考虑两方面,一方面是正常调用的测试,也就是看程序是否能在正常调用
下完成基本功能,这是最基本的测试职责,可惜在很多公司这成了唯一的测试任务,实际上还差的远那;第二方面就是异常调用的测试,比如高压力负荷下的稳定性
测试,用户潜在的异常输入情况下的测试,整体系统局部故障情况下该模块受影响状况的测试,频发的异常请求阻塞资源时的模块稳定测试等等。当然并不是程序员
要对自己的每段代码都需要进行这种完整测试,但是程序员必须清醒认识自己的代码任务在整体项目中的地位和各种性能需求,有针对性的进行相关测试,并尽早发
现和解决问题,当然这需要上面提到的需求理解能力。
7:学习和总结的能力
程序员是人才很容易被淘汰,很容易落伍的职业,因为一种技术可能仅仅在三两年内具有领先性,程序员如果想安身立命,就必须不断跟进新的技术,学习新的技能。
善
于学习,对于任何职业而言,都是前进所必需的动力,对于程序员,这种要求就更加高了。但是学习也要找对目标,一些小codingfans们,他们也津津
乐道于他们的学习能力,一会学会了asp,一会儿学会了php,一会儿学会了jsp,他们把这个作为炫耀的资本,盲目的追逐一些肤浅的,表面的东西和名
词,做网络程序不懂通讯传输协议,做应用程序不懂中断向量处理,这样的技术人员,不管掌握了多少所谓的新语言,永远不会有质的提高。
善于总结,也是学习能力的一种体现,每次完成一个研发任务,完成一段代码,都应当有目的的跟踪该程序的应用状况和用户反馈,随时总结,找到自己的不足,这样逐步提高,一个程序员才可能成长起来。
一个不具备成长性的程序员,即便眼前看是个高手,建议也不要选用,因为他落伍的时候马上就到了。
具备以上全部素质的人,应当说是够格的程序员了,请注意以上的各种素质都不是由IQ决定的,也不是大学某些课本里可以学习到的,需要的仅仅是程序员对自己工作的认识,是一种意识上的问题。
posted @
2008-08-29 10:57 xiaoxinchen 阅读(147) |
评论 (0) |
编辑 收藏
Lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引结构。该结构及相应的生成算法如下:
0)设有两篇文章1和2
文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的内容为:He once lived in Shanghai.
1)由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施
a.我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。
b.文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉
c.用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。
d.用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live”
e.文章中的标点符号通常不表示某种概念,也可以过滤掉
在lucene中以上措施由Analyzer类完成
经过上面处理后
文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
文章2的所有关键词为:[he] [live] [shanghai]
2) 有了关键词后,我们就可以建立倒排索引了。上面的对应关系是:“文章号”对“文章中所有关键词”。倒排索引把这个关系倒过来,变成:“关键词”对“拥有该关键词的所有文章号”。文章1,2经过倒排后变成
关键词 文章号
guangzhou 1
he 2
i 1
live 1,2
shanghai 2
tom 1
通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章
中第几个字符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询
快),lucene中记录的就是这种位置。
加上“出现频率”和“出现位置”信息后,我们的索引结构变为:
关键词 文章号[出现频率] 出现位置
guangzhou 1[2] 3,6
he 2[1] 1
i 1[1] 4
live 1[2],2[1] 2,5,2
shanghai 2[1] 3
tom 1[1] 1
以live
这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现
频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第
2个关键字。
以上就是lucene索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。
实现时 lucene将上面三列分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件
(positions)保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信
息。
Lucene中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。
为了减小索引文件的大小,Lucene对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例
如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。其次大量用到的是对数字的压缩,数字只保存与上一个值
的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。例如当前文章号是16389(不压缩要用3个字节保存),上一文章号是16382,
压缩后保存7(只用一个字节)。
下面我们可以通过对该索引的查询来解释一下为什么要建立索引。
假设要查询单词 “live”,lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。
而用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是无法忍受的。
参考资料:
http://blog.csdn.net/ladofwind/archive/2005/01/10/247403.aspx
posted @
2008-08-21 13:24 xiaoxinchen 阅读(146) |
评论 (0) |
编辑 收藏