vim FAQ

 

(1) 为什么别人的方法在我这里行不通?

(2) 如何找到上次编辑的文件?

(3) 如何复制粘贴?

(4) 如何在多个文件中进行替换?

(5) 如何把fold一次全部打开?

(6) 如何选择、复制或者查找光标所在的单词?

(7) 如何计数搜索的字符串?

(8) 如何去掉高亮搜索?

(9) 如何解决linuxgvim中文菜单乱码的问题?

(10) 如何对所编辑的文件语法高亮显示?

(11) 如何快速插入多行数字0-99

(12) 如何设置中文编码?

(13) 如何去掉或者插入^M这样的字符?

(14) 如何整体缩进一段代码(插入tab)?

(15) 如何合并两行?

(16) 如何设置缩进距离(tab宽度)?

 

==============================================================================

(1) 为什么别人的方法在我这里行不通?

 

估计这是最难回答的一个问题了。:-)

不过首先应该确定你的VIM版本是否足够新,功能是否完整。使用 :version 命令查看你

VIM版本以及功能。一个常见的情况,如果你用的是RedHat系统,请确定安装了

vim-enhancerpm包,否则将是不完整的VIM

 

(2) 如何找到上次编辑的文件?

 

Ctrl+O (按两次)

 

(3) 如何复制粘贴?

 

复制

方法一:先ma标记当前位置为a,移动到新的位置,再y`a或者y''a复制从标记位置a

当前位置的内容。`''的区别:`以字符为单位,''以行为单位。这个方法应该是所有vi

都适用的。(如果不对请指正。)

方法二:按vVCtrl+V进入visual模式,移动光标选择一段内容,按y。三者的区别:

v以字符为单位,V以行为单位,Ctrl+V是块选择。这个方法只在VIM下适用。

 

粘贴

pP。区别:前者粘贴到光标后面,后者粘贴到光标前面。

 

(4) 如何在多个文件中进行替换?

 

一般可以用sed或者vim来做。比如要对当前目录下的*.c文件进行替换:

方法一:

for i in *.c; do

  sed -i -e ''s/oldvalue/newvalue/g'' $i

done

方法二:

vim *.c

:argdo %s/oldvalue/newvalue/g

 

(5) 如何把fold一次全部打开?

 

zR 或者 :set foldlevel=999

 

(6) 如何选择、复制或者查找光标所在的单词?

 

VIM中用iw或者aw表示一个单词,两者稍有区别。

选择光标所在的单词:viw v进入visual模式,然后iw

复制光标所在的单词:yiw

 

查找的话就是两个很常用的明令: *

 

(7) 如何计数搜索的字符串?

 

如果需要统计缓冲中一个模式(pattern)出现的频率,需要把 ''report'' 置为0,然后

用替换命令把模式替换成它自己。Vim 报告的已替换的数目就是模式出现的次数。例:

        :set report=0

        :%s/./&/g               characters

        :%s/i+/&/g            words

        :%s/^                   lines

        :%s/the/&/g             "the" anywhere

        :%s/<the>/&/g         "the" as a word

你可能希望复位 ''hlsearch'' 或者使用 ":nohlsearch"

 

(8) 如何去掉高亮搜索?

 

方法一::nohlsearch

方法二:/awertgvcxz (查找一个肯定不存在的字符串)

设置了高亮搜索(:set hlsearch)以后,可以通过 :set nohlsearch 永久地关闭高亮

显示,也可以通过 :nohlsearch 暂时关闭高亮显示,下次搜索时将自动恢复高亮。

 

(9) 如何解决linuxgvim中文菜单乱码问题?

 

vim6.3为例

:source $VIMRUNTIME/delmenu.vim

:source $VIMRUNTIME/menu.vim

 

也可以将以上内容加入.vimrc

 

source一个menu.vim或者啥也不source都是乱码

另外,也有网友报告说没有遇到此类问题

 

注:这里的source指的是vim自己的source命令,和bash shellsource无关

 

(10) 如何对所编辑的文件语法高亮显示?

 

需要解释的是,VI有很多变种,它本身并没有这种功能,提供这种功能

往往是其各种衍生版本,比如说vim。下面就vim中如何语法高亮简单解释一下。

 

首先,确定一下你所用的操作系统,如果是windows,那么默认的配置文件

就可以工作了。如果还不行,可以用鼠标从syntax菜单下选择一下适合你的

文件类型(新版本的gvim默认把文件类型选择关闭了,需要点开,然后按照

开头字母选择类型)

如果是linux,那么确认一下是否是redhat。如果是redhat,那么需要安装

vim-enhancedrpm包。这些都做了以后,可以用:syntax on来打开语法高亮。

必要时可以用:set filetype=...来设定你的文件类型。

如果使用图形界面,比如gvim,那么syntax onset filetype的操作可以

用鼠标在菜单中选择,同windows下。

如果是在控制台中使用vim,还应当确定你的终端设置支持颜色。

 

(11) 如何快速插入多行数字0-99

 

在命令行中输入以下代码,或者先把代码保存到一个外部文件,然后source这个文件:

let i = 0

while i < 100

  put = i

  let i = i + 1

  endw

如果位数不足需要在前面补零,可以用Ctrl-V块选择,然后I插入0

 

(12) 如何设置中文编码?

 

.vimrc中作如下设置,可以实现界面以及显示字体采用gb2312,遇到utf8文件时

自动做转换:

set encoding=prc

set fileencoding=prc

set fileencodings=utf8,prc

需要注意的是,按照上面的设置,如果你打开一个空的(0字节)或者是纯7bits的文件,

这时VIM将认为是utf8编码的文件,如果你往里面输入中文,存盘的时候也将是utf8

因此你可能需要在存盘之前 :set fileencoding=prc 把编码改回来。

另外,对于纯7bits的文件,由于认成了utf8,每次打开存盘的时候都要做一次转换,

会比较慢,所以如果你很长一段时间不会接触utf8的话,可能暂时把 fileencodings

一行注释掉比较好。

[警告]:转换可能会造成信息丢失!如果你需要编辑的是重要的系统文件,最好把

fileencodings 一行暂时注释掉。

 

(13) 如何去掉或者插入^M这样的字符?

 

VIM的插入模式或者命令行中用<C-V>输入^M这样的特殊字符,例如输入

:s/<C-V><C-M>//g

实际显示是

:s/^M//g

就可以去掉文件中所有的^M。同理,要在文件中输入^M只要按<C-V><C-M>即可。

 

这个问题往往发生在WINDOWS/DOS系统和UNIX系统之间交换文件时,因为这两类系统

对于文本的“换行”概念解释不同。所以,还有一个解决方法就是对这类文本进行

转换。vim内部就可以做这件事情。首先打开文本,然后

set fileformat=unix

再从新保存该文件覆盖原文件就可以去除:^M

 

(14) 如何整体缩进一段代码(插入tab)?

 

选中一段代码, >  2<  3> ……

 

(15) 如何合并两行?

 

合并两行的键是 J

另外,如果你设置了

set backspace=2

你就可以用backspace或者delete很方便的删到上一行或者下一行。

 

(16) 如何设置缩进距离(tab宽度)?

 

set tabstop=8

set shiftwidth=8

 

从 <http://www.fish888.com/vim-FAQ-t95403> 插入

Python程序员的进化

 从 酷壳 - CoolShell.cn 作者:耗子

有 92 人喜欢此条目

以前本站发布过一篇《程序员的进化》,以一种幽默的代码展现方式调侃了程序。下面这篇是关于Python程序员的。以阶乘为例,很有意思。

新手程序员

def factorial(x):

    if x == 0:

        return 1

    else:

        return x * factorial(x - 1)

print factorial(6)

第一年的刚学完Pascal的新手

def factorial(x):

    result = 1

    i = 2

    while i <= x:

        result = result * i

        i = i + 1

    return result

print factorial(6)

第一年的刚学完C语言的新手

def fact(x): #{

    result = i = 1;

    while (i <= x): #{

        result *= i;

        i += 1;

    #}

    return result;

#}

print(fact(6))

第一年刚学完SICP的新手

@tailcall

def fact(x, acc=1):

    if (x > 1): return (fact((x - 1), (acc * x)))

    else:       return acc

print(fact(6))

第一年刚学完Python的新手

def Factorial(x):

    res = 1

    for i in xrange(2, x + 1):

        res *= i

    return res

print Factorial(6)

爱偷懒的程序员

def fact(x):

    return x > 1 and x * fact(x - 1) or 1

print fact(6)

更懒的 Python 程序员

f = lambda x: x and x * f(x - 1) or 1

print f(6)

Python 专家

import operator as op

import functional as f

fact = lambda x: f.foldl(op.mul, 1, xrange(2, x + 1))

print fact(6)

Python 黑客

import sys

@tailcall

def fact(x, acc=1):

    if x: return fact(x.__sub__(1), acc.__mul__(x))

    return acc

sys.stdout.write(str(fact(6)) + '\n')

专家级程序员

import c_math

fact = c_math.fact

print fact(6)

英语系的专家级程序员

import c_maths

fact = c_maths.fact

print fact(6)

Web 设计者

def factorial(x):

    #-------------------------------------------------

    #--- Code snippet from The Math Vault          ---

    #--- Calculate factorial (C) Arthur Smith 1999 ---

    #-------------------------------------------------

    result = str(1)

    i = 1 #Thanks Adam

    while i <= x:

        #result = result * i  #It's faster to use *=

        #result = str(result * result + i)

           #result = int(result *= i) #??????

        result str(int(result) * i)

        #result = int(str(result) * i)

        i = i + 1

    return result

print factorial(6)

Unix 程序员

import os

def fact(x):

    os.system('factorial ' + str(x))

fact(6)

Windows 程序员

NULL = None

def CalculateAndPrintFactorialEx(dwNumber,

                                 hOutputDevice,

                                 lpLparam,

                                 lpWparam,

                                 lpsscSecurity,

                                 *dwReserved):

    if lpsscSecurity != NULL:

        return NULL #Not implemented

    dwResult = dwCounter = 1

    while dwCounter <= dwNumber:

        dwResult *= dwCounter

        dwCounter += 1

    hOutputDevice.write(str(dwResult))

    hOutputDevice.write('\n')

    return 1

import sys

CalculateAndPrintFactorialEx(6, sys.stdout, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)

公司里的程序员

def new(cls, *args, **kwargs):

    return cls(*args, **kwargs)

class Number(object):

    pass

class IntegralNumber(int, Number):

    def toInt(self):

        return new (int, self)

class InternalBase(object):

    def __init__(self, base):

        self.base = base.toInt()

    def getBase(self):

        return new (IntegralNumber, self.base)

class MathematicsSystem(object):

    def __init__(self, ibase):

        Abstract

    @classmethod

    def getInstance(cls, ibase):

        try:

            cls.__instance

        except AttributeError:

            cls.__instance = new (cls, ibase)

        return cls.__instance

class StandardMathematicsSystem(MathematicsSystem):

    def __init__(self, ibase):

        if ibase.getBase() != new (IntegralNumber, 2):

            raise NotImplementedError

        self.base = ibase.getBase()

    def calculateFactorial(self, target):

        result = new (IntegralNumber, 1)

        i = new (IntegralNumber, 2)

        while i <= target:

            result = result * i

            i = i + new (IntegralNumber, 1)

        return result

print StandardMathematicsSystem.getInstance(new (InternalBase, new (IntegralNumber, 2))).calculateFactorial(new (IntegralNumber, 6))

 

摘自:来源

 

8个实用而有趣Bash命令提示行

很多人都对过命令行提示的重要性不屑一顾,甚至是一点都不关心。但是我却一点都不这么认为,一个好的命令行提示可以改变你使用命令的方式。为此,我在internet上找到一些非常实用,优秀,并有趣的bash的命令行提示。下面我将我最喜欢使用的一些命令行提示罗列如下。

注意  -  要使用下面这些提示,你可以拷贝粘贴这些以”PS1″打头的内容到你的终端上,为了使你的改变永久生效,还要将这些内容粘贴到你使用用户的~/.bashrc文件中去。

 

1. 在成功执行的命令上增加一个笑脸符号

这个命令提示行可能是这个命令行提示列表中最有趣的一个,但是它也依然有使用的价值。这个提示的想法是基于当你命令被成功执行,你将会得到一个笑脸作为你的命令行提示,一旦的命令执行失败,命令行提示将会换成一个哭脸。

例子:

bashprompts-happyface

代码:

PS1=”\`if [ \$? = 0 ]; then echo \[\e[33m\]^_^\[\e[0m\]; else echo \[\e[31m\]O_O\[\e[0m\]; fi\`[\u@\h:\w]\\$ “

2.更改失败命令的颜色

下面这个命令行提示是我最喜欢的命令行之一。和上一个相似,这个命令行提示的颜色会在你最后一个命令运行失败后改变,而且这个命令行长路径会缩短输入命令的空间,这个命令提示还包含了bash 每个历史命令的命令号,以方便重新提取运行。

例子:

bashprompts-hurring

代码:

PS1=”\[\033[0;33m\][\!]\`if [[ \$? = "0" ]]; then echo “\\[\\033[32m\\]“; else echo “\\[\\033[31m\\]“; fi\`[\u.\h: \`if [[ `pwd|wc -c|tr -d " "` > 18 ]]; then echo “\\W”; else echo “\\w”; fi\`]\$\[\033[0m\] “; echo -ne “\033]0;`hostname -s`:`pwd`\007″‘

3. 多行提示

如果你是喜欢命令行提示中包含完整信息的那一类人,那么下边就有一个适合于你的命令行提示。这个命令行提示信息中包含日期/时间,全路径,用户,主机,活动终端,甚至包含文件数和占用空间等。

例子:


bashprompts-informant

代码:

PROMPT_COMMAND=’PS1=”\n\[\033[35m\]\$(/bin/date)\n\[\033[32m\]\w\n\[\033[1;31m\]\u@\h: \[\033[1;34m\]\$(/usr/bin/tty | /bin/sed -e ’s:/dev/::’): \[\033[1;36m\]\$(/bin/ls -1 | /usr/bin/wc -l | /bin/sed ’s: ::g’) files \[\033[1;33m\]\$(/bin/ls -lah | /bin/grep -m 1 total | /bin/sed ’s/total //’)b\[\033[0m\] -> \[\033[0m\]“‘

 

4. 多颜色提示

这个命令行提示除了使用了不同颜色来区别不同信息外,它并没有很特别的地方。就像你看到的那样,它提供了时间,用户名,主机名,当前目录。相当少的信息,但是非常地实用。

例子:

bashprompts-4

代码:

PS1=”\[\033[35m\]\t\[\033[m\]-\[\033[36m\]\u\[\033[m\]@\[\033[32m\]\h:\[\033[33;1m\]\w\[\033[m\]\$ “

 

5.显示完整路径

这是一个良好,简洁,最小的2行提示(加上顶上的空行)。在第一行你能得到一个全路径信息,在第二行是一个用户名。如果你对每个命令提示行的空行不爽的话,你只要移走第一个\n就OK了

例子:

bashprompts-5

代码:

PS1=”[\[\033[32m\]\w]\[\033[0m\]\n\[\033[1;36m\]\u\[\033[1;33m\]-> \[\033[0m\]“

 

6. 显示后台运行任务数

这是另外的一个两行提示,但是这个两行提示具有更多的之前我们没有的信息。第一行是显示通常的user@host和全路径等信息。在第二行我们可以得到命令执行历史序号和一个后台运行任务个数信息。

例子:

 

bashprompts-6

代码:

PS1=’\[\e[1;32m\]\u@\H:\[\e[m\] \[\e[1;37m\]\w\[\e[m\]\n\[\e[1;33m\]hist:\! \[\e[0;33m\] \[\e[1;31m\]jobs:\j \$\[\e[m\] ‘

 

7. 显示路径信息

这是一个非常眩的设计。我们可以从这个命令行提示信息的第一行中获取到用户/主机,运行任务数,和时间日期等信息。在第二行我们可以得到当前目录的文件数和他们占用的磁盘空间。

例子:

 

bashprompts-7

代码:

PS1=”\n\[\e[30;1m\]\[\016\]l\[\017\](\[\e[34;1m\]\u@\h\[\e[30;1m\])-(\[\e[34;1m\]\j\[\e[30;1m\])-(\[\e[34;1m\]\@ \d\[\e[30;1m\])->\[\e[30;1m\]\n\[\016\]m\[\017\]-(\[\[\e[32;1m\]\w\[\e[30;1m\])-(\[\e[32;1m\]\$(/bin/ls -1 | /usr/bin/wc -l | /bin/sed ’s: ::g’) files, \$(/bin/ls -lah | /bin/grep -m 1 total | /bin/sed ’s/total //’)b\[\e[30;1m\])–> \[\e[0m\]“

8. My Prompt

最后这个命令提示行是我个人最喜欢的使用的命令提示行。它是#7的一个修改,这个命令提示行只包含我最希望知道的信息,因此节省了它的占用空间。我偏爱两行风格,因为这样不仅可以让我看到全路径信息,而且不影响我命令输入的可视空间。

例子:

bashprompts-8

代码:

PS1=”\n\[\e[32;1m\](\[\e[37;1m\]\u\[\e[32;1m\])-(\[\e[37;1m\]jobs:\j\[\e[32;1m\])-(\[\e[37;1m\]\w\[\e[32;1m\])\n(\[\[\e[37;1m\]! \!\[\e[32;1m\])-> \[\e[0m\]“

如果你愿意共享你的命令提示行,请在将这些命令提示代码加在下面的评论中。

PS1=”\n\[\033[35m\]\$(/bin/date)\n\[\033[32m\]\w\n\[\033[1;31m\]\u@\h: \[\033[1;34m\]\$(/usr/bin/tty | /bin/sed

-e ’s:/dev/::’): \[\033[1;36m\]\$(/bin/ls -1 | /usr/bin/wc -l | /bin/sed ’s: ::g’) files \[\033[1;33m\]\$(/bin/ls -lah | /bin/grep -m 1 total | /bin/sed ’s/total //’)b\[\033[0m\] -> \[\033[0m\]”

 出处

Tapestry入门

简介
Jakarta Tapestry是一个开源的Java Web应用框架。你或许会说:"大同小异的东西罢了."多数
情况下,我同意你的观点,然而,只要花上些许时间研究一下,你会发现Tapestry跟别的框架大为不同,它是值得严肃对待的。
Tapestry是一个基于控件的框架以致于用它开发Web应用类似开发传统的GUI应用。你用Tapestry开发Web应用时你无需关注以操作 为中心的(operation-centric) Servlet API.引用Tapestry网站上的一句话:"Tapestry用对象(objects),方法(methods),属性(properties)替代 以往的URLs和查询参数, 重新诠释Web应用开发.Tapestry 3.0即将发布,它有大量的改进和新的特性。
Tapestry的目标
简单性
Tapestry应用与传统的Servlet应用相比代码量更少。大多数传统的Servlet应用包含如下厌烦和
重复的任务:解析查询参数,处理HttpSession对象,构建URLs。Tapestry消除了传统Servelt应用中许多无趣的"衔接"代码("plumbing" code)使开发者把精力集中到应用逻辑上来。
一致性
Tapestry为开发Web应用的页面提供了一致的方式。这样有助于消除传统Servlet应用开发中臆测。由于所有Tapestry应用中的页面都是用相同的可复用的控件组织而成,所以工作方式是相似的。
效率
Tapestr应用拥有高度的可升级性,它利用缓存和对象池使每个请求的处理时间最小化。Tapestry应用拥有跟传统Servlet应用相仿的性能。
错误反馈
任何开发过Servlet/JSP应用的人毫无质疑有类似经历:为了找出Web.xml文件有什么错误,不得不花费大量时间察看浏览器中的堆栈信息。Tapestry拥有优秀的错误报告方式,最值得一提的是它会指出哪个文件以及那一行导致了错误。
与Struts比较
既然Apache Struts可能是当今应用最广泛的Web应用框架,拿Tapestry与它比较是唯一公平的。以下是一些观察比较,它们来源于为这篇文章开发的几个简单的Tapestry应用和为几个Struts工程的工作经历。
Struts的优点
1 一个Servlet/JSP开发者熟悉Struts无需太久。然而Tapestry的学习曲线会长一点,因为它与流行的Web应用框架不太相同 。
2 Struts在Java社区里被广泛接受和使用。为你的项目找一个好的Struts开发人员并非难事,Tapestry近来在开发者社区里 赢得一些关注,然而仍有许多Java老手不知道Tapestry为何物。
3 既然Struts被如此广泛的使用,所以有很多Struts资源可供参考。相比大多数开源软件,Tapestry拥有非常可观的资源和文档,但跟Struts相比仍有差距。
Tapestry的优点
1 你开发一个Tapestry应用无需关注Servlet API,你也无须为你的Servlet应用写一些典型的"衔接"代码。虽然Struts简化了工作,然而Servlet API 仍是你需面对的。
2 Tapestry的页面模板除了几个特别属性和标识就是一个标准的HTML文件。 如果你是一个开发小组中的HTML设计高手,然而你不懂Java或JSP,这就给你带来很大方便。
3 因为Tapestry页面是标准的HTML,所以可以用HTML所见即所得(WYSIWYG)编辑器编辑和预览该页。当一个页需要修改它的外观并不需要通知服务器让它重新编译JSP.
4 Tapestry不需要一个至高的,整个应用范围的配置文件。Tapestry应用中的每一页是独立的,改变一页不会影响开发其他 页面的开发者,因为并没有一个配置文件把所有页面的浏览粘连在一起。
5 Tapestry拥有极好的错误报告。如果你在一个页的模板或页面规范犯了一个错误,Tapestry会指出导致错误的行号。
6 用Tapestry开发是种乐趣。这样说听上去似乎老调,然而用Tapestry开发一个Web应用相比应用其他流行的框架更为自然有趣。用Tapestry开发是应用了一种基于控件的架构,与开发传统的GUI应用非常相似。
Tapestry 架构
Tapestry框架是标准Servlet API的一种扩展。它需要J2SDK1.2或更高版本的J2SDK和一个与Servlet API 2.2(或更高)兼容的应用服务器/Servlet容器。
一个Tapestry应用由许多拥有唯一名称的页面组成。一个页面由一个模板和一些可复用的控件构成。模板由标准的HTML标签和一些额外的属性和标签构成,这些额外的属性和标签是为了告诉Tapestry框架这个页面的那些部分是由Tapestry控件组成。
简单的Tapestry应用
为了最好的描述构建一个Tapestry页面的方方面面,我们可以看看这个Pig Latin翻译器应用的代码。这个应用只有一个页面,在这页里输入一个text值把它翻译成Pig Latin,然后把翻译好的值显示给用户。
在Tapestry应用中每个页由3个部分组成:一个HTML模板,一个页面规范文件,一个Java类。
这里有这个页面屏幕抓图:
 

页面模板由标准的HTML标签和一些额外的属性和标签构成,这些额外的属性和标签是为了告诉Tapestry框架这个页面的那些部分是由 Tapestry控件组成。页面模板存放在Web应用的根context目录下。通常,Tapestry在启动时会寻找和呈现一个名叫"Home"的页。 虽然我们可以改变这种行为,但依照Tapestry的惯例会更简单。
Home.html 
    <html>
    <head>
      <title>Tapestry Pig Latin Translator</title>
    </head>
    <body>
      <h1>Pig Latin Translator</h1>
      <form jwcid="@Form"① listener="ognl:listeners.submit"②>
      <table border="1">
        <tr>
          <td>Value to Translate:</td>
          <td>
            <input type="text" jwcid="@TextField"③ value="ognl:inputValue"/>
          </td>
        </tr>
        <tr>
          <td>Pig Latin:</td>
          <td>
            <jwcid="@Insert"④ value="ognl:pigLatinValue"/>
          </td>
        </tr>
      </table>
      <input type="submit" jwcid="@Submit"⑤ value="Translate"/>
      </form>
    </body>
    </html>
    
页面模板的绝大部分是普通的HTML,只有少部分Tapestry特有的属性和标签。这种模板机制的优势就是Tapestry页面模板可以在一个可见即所得的编辑器里创建和预览。描述Tapestry控件部分的标识是有限的和突出的。
标识里的jwcid所指是被应用的Tapestry控件的Java Web Component ID.在上面代码断里,我们是隐式地使用控件。隐式的控件是指直接在页面模板里声明使用的控件,。jwcid的前缀 '@ '符号就是通知Tapestry这里声明使用了一个隐式控件。
在上面的Pig Latin Translator页面模板里用了四个控件:Form①, TextField③, Insert④ 和Submit⑤。它们只是Tapestry框架提供的包含超过40个控件的控件库里的四个。在后面的范例中,我们将会看到如何使用显式控件。显式控件是 指控件在页面规范文件里声明后再使用的控件。
在前面的HTML模板里,使用控件的同时,也为控件指定了参数。例如控件Form①有一个listener②参数它指定了当表单提交时对应的页面类 调用的方法名称。那个ognl:前缀的使用贯穿页面的HTML模板,指向的是Object Graph Navigation Language (OGNL)。OGNL是一个强大的开源的表达式语言,用于将页面内控件的属性绑定到页面类的属性。
现在我们看看页面规范文件。页面规范文件是一个扩展名为page的XML文件,这个文件有许多职责,在众多职责中最基本是指定页面对应的Java类。页面规范文件存放在webapp的WEB_INF目录。
Home.page 
    <?xml version="1.0"?>
    <!DOCTYPE page-specification PUBLIC
        "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
        "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>
    <page-specification class="Home">
        <property-specification name="inputValue" type="java.lang.String"/>
        <property-specification name="pigLatinValue" type="java.lang.String"/>
    </page-specification>
    
页面规范文件的根元素有一个class的属性,它指定了这个页对应的Java类。这个类必须要实现org.apache.tapestry.Ipage接口。页面规范同时页定义了两个属性(property)元素,以便Tapestry在页面类里创建新的属性。
Tapestry框架提供了org.apache.tapestry.html.BasePage class,它实现了Ipage接口。页面类被存放在Web-INF/classes目录下,跟你的Web应用的所需要的其他类放在一起。
Home.java 
    import org.apache.tapestry.html.BasePage;
    import org.apache.tapestry.IRequestCycle;
    public abstract class Home extends BasePage {
        public abstract String getInputValue();
        public abstract void setInputValue(String inputValue);
        public abstract String getPigLatinValue();
        public abstract void setPigLatinValue(String pigLatinValue);
        public void submit(IRequestCycle cycle) {
            String inputValue = getInputValue();
            String pigLatinValue = new PigLatinTranslator().translate(inputValue);
            setPigLatinValue(pigLatinValue);
        }
    }
    
你要提醒的第一件事或许是这个类为什么是抽象类。它还有几个抽象方法访问inputValue,pigLatinValue属性。这里利用了Tapestry会在运行时刻创建子类的功能,这个子类会创建你在页面规范里声明的属性和生成相应的访问方法。
在表单提交时页面类的submit方法会被调用。为什么会这样?因为我们在页面模板里将Form控件的listener属性指定为:ognl:listeners.submit。这就意味着一个名叫submit的listener会通过页面类的listeners被访问。
所有的页面类和控件类都从org.apache.tapestry.AbstractComponent这个类继承来一个叫listeners的属性。当submit方法完成后,页面会显示被翻译好的词。
最后讲讲Web.xml这个Web发布描述文件。Tapestry,像许多其他的流行的Web应用框架一样,由一个Servlet构成,但是还需要一个发布描述文件。那个发布描述文件应该被存放在WEB-INF目录。
web.xml 
    <?xml version="1.0"?>
    <!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd>
    <web-app>
        <display-name>Tapestry Pig Latin Translator</display-name>
        <servlet>
            <servlet-name>tapestry</servlet-name>
            <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>tapestry</servlet-name>
            <url-pattern>/app</url-pattern>
        </servlet-mapping>
    </web-app>
    
虽然Pig Latin翻译应用非常简单,但是它会让你对在Tapestry应用中一个页面的3个组成部分有了基本的了解。它也展示了创建一个Tapestry应用的一个页面只需写多么少的代码。
表单输入验证
Tapestry 提供了一些控件以便校验用户的输入。校验子系统是ValidField控件的核心。在下面的登录应用中我们将使用ValidField控件。ValidField控件位于表单内,对用户在客户端的校验提供了有用的反馈和视觉上的错误提示。
区域化
在Tapestry中,区域化是相当简单的。Tapestry允许文字和图形的区域化。为了区域化页面的内容,你可以为每一个添加一个 properties文件,或者提供一个区域化的模板。为每个页面提供一个资源文件的方式远比管理和维护一个巨大的全局的应用范围的资源文件简单。如果页 面的区域化并不仅仅只是文字信息的区域化,例如页面的布局不同或者组成的控件不同,这样情况提供区域化的页面模板就能派上用场了。我们会在下面的登录应用 的使用Tapestry区域化。
创建控件
Tapestry发布时提供了40多个自带的控件。如果你想知道更多的关于Tapestry自带控件的信息,请参考Tapestry Component Reference.想看看Tapestry的控件的应用范例可访问Tapestry Component Workbench.如果你发现你需要一个Tapestry本身没提供的控件,你可以自己创建一个。创建你自己的Tapestry控件跟创建一个页面是相 似的。一个典型的Tapestry控件由一个控件规范文件(XML文档),一个HTML控件模板,一个实现了 org.apache.tapestry.Icomponent接口的Java类。这个议题有点超出本文的范围,但是如果你有兴趣学习如何创建你自己的 Tapestry控件,你可以参考Tapestry的原创人,Tapestry In Action 一书的作者--Howard Lewis Ship写的 Designing Tapestry Mega-Components 。
Tapestry 登录应用
你在Pig latin翻译器应用中看到了Tapestry的一些基本特性。与其用一个复杂的应用展示Tapestry所有的特性以致于压得你揣不过气来,还不如通过 一些简单的应用让你找到一点对Tapestry的感觉。下面这个应用展示Tapestry如何处理页面导航,区域化,验证和其他一些特性。
这里有一个Home页的屏幕抓图,下面跟着它的页面模板。
 
Home.html 
    <html>
    <head>
        <title>Welcome to the Tapestry Login Application</title>
    </head>
    <body>
        <h1>Welcome to the Tapestry Login Application</h1>
        <span jwcid="@PageLink"① page="Login">Login</span>
    </body>
    </html>
    
这个Home页的页面模板除了一个jwcid属性定义使用一个Tapestry PageLink①控件以外都是标准的HTML。
PageLink控件生成了一个指向Login页的超链接。既然Home页没有任何动态的行为所以它不需要页面规范和页面对应的Java类。
这里是Login页的屏幕抓图,后面跟着是它的页面模板。
 
Login.html 
    <html>
    <head>
        <title>
            <span key="title">①Login</span>
        </title>
    </head>
    <body jwcid="@Body">②
        <span jwcid="@Conditional" condition="ognl:beans.delegate.hasErrors">③
            <div style="color: red">
                <span jwcid="@Delegator" delegate="ognl:beans.delegate.firstError">④
                    Error Message
                </span>
            </div>
        </span>
        <p style="font-weight: bold" >
            <span key="hint">Hint: Your password is your username spelled backwards.</span>
        </p>
        
        <form jwcid="@Form" listener="ognl:listeners.login" delegate="ognl:beans.delegate">
⑤
            <table>
                <tr>
                    <td align="right">
                        <span jwcid="@FieldLabel" field="ognl:components.inputUsername"⑥>
                            Username:
                        </span>
                    </td>
                    <td>
                        <input type="text" jwcid="inputUsername"⑦ value="simpson_h" 
size="30"/>
                    </td>
                </tr>
                <tr>
                    <td align="right">
                        <span jwcid="@FieldLabel" field="ognl:components.inputPassword">
                            Password:
                        </span>
                    </td>
                    <td>
                        <input type="text" jwcid="inputPassword" hidden="true" value="" 
size="30"/>
                    </td>
                </tr>
                <tr>
                    <td colspan="2" align="center">
                        <input type="submit" jwcid="@Submit" value="message:login"/>
                    </td>
                </tr>
            </table>
        </form>
    </body>
    </html>
    
这个页面模板大多数是通常的HTML。我们从页面模板中可以看到Tapestry的区域化特性:它使用一个span元素,这个span元素带有一个 叫key的属性,key的值映射到Login.properties文件里一个属性。一个Body控件被声明使用,因为它对客户端的JavaScript 校验是必需的。
为Form component⑤设定delegate属性激活表单输入验证。delegate属性是我们在页面规范里声明的 org.apache.tapestry.valid.IvalidationDelegate的实现类。如果验证错误发生了,我们用 Conditional component③控件判断delegate是否有任何错误,如果有就把第一个错误④显示给用户。如果ognl 表达式ognl:beans.delegate.hasErrors 为true,Conditional控件将显示它的内容实体。所有的页面类和控件类都从AbstractComponent继承来一个叫beans的属 性。这个beans属性是一个org.apache.tapestry.IbeanProvider的实例,利用它可以通过名字取得在页面规范文件里定义 的beans.FieldLabel⑥被用于为inputuserName validField控件显示标签,这个FieldLabel控件也被用来与表单的验证代理协作,指出包含错误的输入域。
InputUserName⑦控件是一个显示控件的例子。显式控件是指在页面规范文件声明的控件。InputUsername和inputPassword控件都是显式的,它们与FieldLabel联合显示它们的displayName属性。
下面的是Login页的资源文件。Login.properties跟页面规范一并存放在WEB-INF目录。
Login.properties 
    title = Login to the Application
    hint = Hint: Your password is your username spelled backwards.
    login = Login
    username = Username:
    password = Password:
    invalidpassword = Invalid Password
    
Here is the page specification for the Login page. 
Login.page 
    <?xml version="1.0"?>
    <!DOCTYPE page-specification PUBLIC
        "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
        "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>
    <page-specification class="com.ociweb.tapestry.Login">
        <bean name="delegate" class="org.apache.tapestry.valid.ValidationDelegate"/>①
        <bean name="requiredValidator"②
            class="org.apache.tapestry.valid.StringValidator">
            <set-property name="required" expression="true"/>
            <set-property name="clientScriptingEnabled" expression="true"/>
        </bean>
        <property-specification name="username" type="java.lang.String"/>
        <property-specification name="password" type="java.lang.String"/>
        <component id="inputUsername" type="ValidField"> ③
            <message-binding name="displayName" key="username"/> ④
            <binding name="validator" expression="beans.requiredValidator"/> ⑤
            <binding name="value" expression="username"/> ⑥
        </component>
        <component id="inputPassword" type="ValidField"> ⑦
            <message-binding name="displayName" key="password"/>
            <binding name="validator" expression="beans.requiredValidator"/>
            <binding name="value" expression="password"/>
        </component>
    </page-specification>
    
Page-specification元素的class属性和两个property-specification元素与Pig Latin翻译器应用是相似的。
你会发现第一个新东西-bean元素①,bean元素把一个org.apache.tapestry.valid.ValidationDelegate
的实例指定了名称"delegate"。页面HTML模板里的Form控件把它的参数delegate设定为
ognl:beans.delegate,就是指向了这个org.apache.tapestry.valid.ValidationDelegate实例。
Bean元素②把一个org.apache.tapestry.valid.StringValidator的实例指定了名称" 
requiredValidator", 以用于验证。这个bean的required属性被设为true表明使用这个bean的域是必须被验证的。这个bean的 clientScriptingEnabled属性被设定为ture,表明使用这个bean的域客户端的JavaScript验证功能是激活的。 RequiredValidator bean被用于验证inputUsername和inputPassword的内容。
控件inputUsername③被控件规范声明为ValidField,ValidField是一种用于Tapestry验证子系统的特殊版本的 TextField控件。Message-binding元素被用于指定inputUsername控件的displayName参数的值,这个值是 用"username"为关键字从login.properties④文件里得到。InputUsername控件的validator参数被设定为 requiredValidator bean,这是我们在页面规范里声明过的⑤。控件的value参数跟页面Java类的username属性绑定在一起⑥。控件inputPassword 的控件规范跟控件inputUsername几乎相似,除了用于取得displayName的关键字和绑定的页面Java类的属性不同。
通过使用ValidField控件和为表单(form)提供一个ValidationDelegate, 我们激活了Login表单的验证功能。除了服务器端的验证,Tapestry也提供了客户端的验证(利用JavaScript)。下面就是当用户提交一个 表单而没有为UserName域提供值时,一个JavaScript错误对话框弹出时的屏幕抓图。
 
下面就是当用户提交一个表单而没有为Password域提供值时,一个JavaScript错误对话框弹出时的屏幕抓图。
 
 
下面就是Login页对应的Java 类。
Login.java 
    package com.ociweb.tapestry;
    import org.apache.tapestry.html.BasePage;
    import org.apache.tapestry.IRequestCycle;
    import org.apache.tapestry.valid.ValidationConstraint;
    import org.apache.tapestry.valid.IValidationDelegate;
    public abstract class Login extends BasePage {
        public abstract String getUsername();
        public abstract void setUsername(String username);
        public abstract String getPassword();
        public abstract void setPassword(String password);
        public void login(IRequestCycle cycle) {
            String username = getUsername();
            String password = getPassword();
            StringBuffer sb = new StringBuffer(username);
            String validPassword = sb.reverse().toString();
            if (password.equals(validPassword)) {
                cycle.activate("Success");①
            } else {
                String errorMessage = getMessage("invalidpassword");②
                IValidationDelegate validationDelegate =
                        (IValidationDelegate) getBeans().getBean("delegate");③
                validationDelegate.record(errorMessage,
                                          ValidationConstraint.CONSISTENCY);④
            }
        }
    }
    
跟Pig Latin翻译器应用一样,我们的页面类也是抽象的,它有抽象方法访问在页面规范里定义的属性(properties)。Tapestry会在运行时刻创 建username和password属性。Login方法只是简单的验证一下用户输入的密码值是否刚好是用户名的反向。如果密码通过验证,用户将被引领 导Success page①。
如果密码输入有误,我们用关键字"invalidPassword"通过从 org.apache.tapestry.AbstractComponent里继承来的getMessage()方法从 Login.properties②里查找对应的资源。我们需要把密码错误信息纪录到我们在页面规范中定义的页面validation delegate中去。我们可以利用我们在页面规范中指定的名称,从页面的beans属性中找回validationDelegate③。最后,我们调用 org.apache.tapestry.valid.IvalidationDelegate的record方法把将要显示给用户看的错误信息保存起 来。下面就是当用户输入错误密码的提交后的屏幕抓图。
 
下面就是Success页的页面模板。Success页的页面模板仅仅包含HTML标识,所以它不需要页面规范和页面
Java类。
Success.html 
    <html>
    <head>
        <title>Successful Login</title>
    </head>
    <body>
        <p>
            Congratulations! You have successfully logged on.
        </p>
    </body>
    </html>
    
总结
我希望这篇文章已经向你展示了Tapestry框架在构建Web应用的是多么简单,然而优雅。Tapestry与大多数主流Web应用框架最大不同 在于它让你用基于控件的方式开发,而非以操作为中心的方式开发。如果这篇文章激起了你的兴趣,我建议你把它下载下来利用它你自己的简单的Web应用。通过 感受简单的应用,这是你了解这个框架的优点的唯一途径。如果你想在你的下一个项目里使用Tapestry,我强烈建议你购买
Tapestry In Action 这本书。我拥有这本书,对它我感到很满意。
References
1 Zip file with all source code and war files from the article. (12K) 
                 http://www.ociweb.com/jnb/jnb2004_05.zip
2 Tapestry Home Page http://jakarta.apache.org/tapestry/
3 Tapestry In Action Page http://www.manning.com/lewisship/
4 Tapestry Wiki http://jakarta.apache.org/tapestry/wiki_frame.html
5 OGNL page http://www.ognl.org/
6 Tapestry Component Reference 
                 http://jakarta.apache.org/tapestry/doc/ComponentReference/index.html
7 Tapestry Component Workbench http://www.t-deli.com/app
8 Designing Tapestry Mega-Components 
                 http://www.onjava.com/pub/a/onjava/2001/11/21/tapestry.html

源文档 <http://blog.csdn.net/gmplayer/archive/2004/11/15/182923.aspx> 

ibatis 动态sql定义

 

ibatis map标签记录

Table Binary conditional attributes

Element

Description

<isEqual>

Checks the equality of a property and a value, or another property. Example Usage:

<isEqual prepend="AND"
             property="status"
             compareValue="Y">
MARRIED = ‘TRUE'
</isEqual>              

<isNotEqual>

Checks the inequality of a property and a value, or another property. Example Usage:

<isNotEqual prepend="AND"
             property="status"
             compareValue="N">
MARRIED = ‘FALSE'
</isNotEqual>  

<isGreaterThan>

Checks if a property is greater than a value or another property. Example Usage:

<isGreaterThan prepend="AND"
             property="age"
             compareValue="18">
ADOLESCENT = ‘FALSE'
</isGreaterThan>  

<isGreaterEqual>

Checks if a property is greater than or equal to a value or another property. Example Usage:

<isGreaterEqual prepend="AND"
             property="shoeSize"
             compareValue="12">
BIGFOOT = ‘TRUE'
</isGreaterEqual>

<isLessEqual>

Checks if a property is less than or equal to a value or another property. Example Usage:

<isLessEqual prepend="AND"
             property="age"
             compareValue="18">
ADOLESCENT = ‘TRUE'
</isLessEqual>

Table?.8.Bnary conditional attributes

Element

Description

<isPropertyAvailable>

Checks if a property is available (i.e is a property of the parameter object). Example Usage:

<isPropertyAvailable property="id" >
  ACCOUNT_ID=#id#
</isPropertyAvailable>

<isNotPropertyAvailable>

Checks if a property is unavailable (i.e not a property of the parameter object). Example Usage:

<isNotPropertyAvailable property="age" >
  STATUS='New'
</isNotEmpty>

<isNull>

Checks if a property is null. Example Usage:

<isNull prepend="AND" property="order.id" >
  ACCOUNT.ACCOUNT_ID = ORDER.ACCOUNT_ID(+)
</isNotEmpty>

<isNotNull>

Checks if a property is not null. Example Usage:

<isNotNull prepend="AND" property="order.id" >
  ORDER.ORDER_ID = #order.id#
</isNotEmpty>

<isEmpty>

Checks to see if the value of a Collection, String property is null or empty ("" or size() < 1). Example Usage:

<isEmpty property="firstName" >
  LIMIT 0, 20
</isNotEmpty>

<isNotEmpty>

Checks to see if the value of a Collection, String property is not null and not empty ("" or size() < 1). Example Usage:

<isNotEmpty prepend="AND" property="firstName" >
  FIRST_NAME LIKE '%$FirstName$%'
</isNotEmpty>

Element

Description

<isParameterPresent>

Checks to see if the parameter object is present (not null).

<isParameterPresent prepend="AND">
  EMPLOYEE_TYPE = #empType#
</isParameterPresent>

<isNotParameterPresent>

Checks to see if the parameter object is not present (null). Example Usage:

<isNotParameterPresent prepend="AND">
  EMPLOYEE_TYPE = ‘DEFAULT'
</isNotParameterPresent>

Table?.10.Creating a list of conditional clauses

Element

Description

<iterate>

Iterates over a property that is of type IList Example Usage:

<iterate prepend="AND" property="UserNameList"
  open="(" close=")" conjunction="OR">
  username=#UserNameList[]#
</iterate>

Note: It is very important to include the square brackets[] at the end of the List property name when using the Iterate element. These brackets distinguish this object as an List to keep the parser from simply outputting the List as a string.

Tag标签: ibatis

 

从 <http://www.cnblogs.com/jifsu/archive/2010/03/01/1675342.html> 插入