??xml version="1.0" encoding="utf-8" standalone="yes"?>快乐12开奖:BlogJava - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/zh-cnSat, 15 Dec 2018 21:09:10 GMTSat, 15 Dec 2018 21:09:10 GMT60vim 替换 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2012/05/09/377726.html林光?/dc:creator>林光?/author>Wed, 09 May 2012 09:28:00 GMT//www.ot7t.com.cn/lingy/archive/2012/05/09/377726.html:%s/143250/143120/g

//www.linux521.com/2009/system/201106/15135_2.html 

]]>
[端口被占?环境起不来]常见测试环境问题解决 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2012/01/31/369065.html林光?/dc:creator>林光?/author>Tue, 31 Jan 2012 03:29:00 GMT//www.ot7t.com.cn/lingy/archive/2012/01/31/369065.html大家是否遇到部署环境的时?端口被占?环境起不来的问题呢?遇到这个情况,我们该如何解决呢?/span>

下面我把我遇到这个问题解决的方法总结下:

现象是这样的:

1. 页面访问出现: Http 500

2. 后台启动日志提示: 

vodka init successfully!!! ...

start apache ......

(98)Address already in use: make_sock: could not bind to address [::]:5071

no listening sockets available, shutting down

Unable to open logs

解决方法: 杀掉占用的进程

首先,需要用root账号登陆,登陆?输入: netstat -plan |grep 5070

出现如下:


[Intranet root@qa-kernal-143-41 /root]

#netstat -plan |grep 5070

tcp 0 0 :::5070 :::* LISTEN 28002/httpd 

tcp 1 0 ::ffff:10.20.143.41:5070 ::ffff:10.16.46.75:4654 CLOSE_WAIT 28406/httpd 

最后杀掉占用的进程,输入:   lsof -i:5070 即可 (?070是端口号)

[Intranet root@qa-kernal-143-41 /root]

#lsof -i:5070

]]>
linux用户组相关知?/title><link>//www.ot7t.com.cn/lingy/archive/2012/01/31/369064.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Tue, 31 Jan 2012 03:28:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2012/01/31/369064.html</guid><description><![CDATA[<span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">用root用户登陆输入命令cd /home,再用ll查看发现drwxr-xr-x 12 622   622    4096 Apr 18 19:21 aurora  aurora用户属主不正?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">用命令chown aurora.aurora aurora修改用户属主</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">知识点:</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1.查看用户组信?cat /etc/passwd</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">/etc/passwd中一行记录对应着一个用户,每行用冒号隔开分为7个字段,具体字段说明如下?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(255,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">name:password:uid:gid:comment:home:shell<br style="outline-style: none" />用户?口令:用户标识?组标识号:注释性描?主目?登录Shell</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">home: 指定用户的主目录的绝对路?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">shell: 用户登陆后启动的一个进程,这个进程是用户登录到系统后运行的命令解释器或某个特定的程序,即Shell?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">例子?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">aurora:x:707:707::/home/aurora:/bin/bash</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">   系统首先会查?/etc/passwd 文件,看是否有aurora 这个账号,然后确定aurora的UID,通过UID 来确认用户和身份?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">   如果存在则读?etc/shadow 影子文件中所对应的aurora的密码;  <span class="Apple-converted-space"> </span></span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">   用户名:x:uid:gid:用户名全称:用户的家:用户所用的shell类型</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">  x指向映射</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">uid? 则为root  </span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2.aurora:$1$nC4FzXJz$OP5LS0Evj4uMsLvMHP1eZ/:15082:0:99999:7:::</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">etc/shadow文件?etc/passwd 的影子文件,这个文件并不?etc/passwd 而产生的,这两个文件是应该是对应互补的;</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">shadow内容包括用户及被加密的密码及其他/etc/passwd 不能包括的信息?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">用户:密码:上次修改密码的时?:两次修改口令间隔最少的天数:两次修改口令间隔最多的天数</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">3.aurora:x:707:</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">用户名:用户组密码:GID :用户列表</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">第四字段:用户列表,每个用户之间?号分割;本字段能为空?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">如果字段为空表示用户组为GID的用户名</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">4.chown 修改文件和文件夹的用户和用户组属?/span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; outline-style: none; font: 14px/24px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/24px Arial; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">5.passwd aurora 修改密码</span><img src ="//www.ot7t.com.cn/lingy/aggbug/369064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/lingy/" target="_blank">林光?/a> 2012-01-31 11:28 <a href="//www.ot7t.com.cn/lingy/archive/2012/01/31/369064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux之用户登录环境变量分?/title><link>//www.ot7t.com.cn/lingy/archive/2012/01/31/369057.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Tue, 31 Jan 2012 02:53:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2012/01/31/369057.html</guid><description><![CDATA[<strong class="yibqv">昨天遇见一个问题,与大家分享一下。现象如下,当从一个用户切换到另外一个用户。或者直接登录的时候会出现如错误:bash-3.2</strong>  <p><strong class="yibqv">分析?/strong></p> <p><strong class="yibqv">而且bpm这个用户以前都是好的,为什么呢?我们来分析一下用户的登录的一些原理就明白了:</strong></p> <p><strong class="yibqv">用户在刚登录Linux时,步骤如下?/strong></p> <p><strong class="yibqv">1</strong><strong class="yibqv">、首先启?/etc/profile 文件?/strong></p> <p><strong class="yibqv">2</strong><strong class="yibqv">、然后再启动用户目录下的 ~/.bash_profile?~/.bash_login?~/.profile文件中的其中一个,</strong></p> <p><strong class="yibqv">执行的顺序为:~/.bash_profile?~/.bash_login?~/.profile?如果 ~/.bash_profile文件存在的话,一般还会执?~/.bashrc文件?/strong></p> <p><strong class="yibqv">因为?~/.bash_profile文件中一般会有下面的代码:</strong></p> <p>if [ -f ~/.bashrc ] ; then</p> <p> . ./bashrc</p> <p>fi</p> <p> 因为?~/.bash_profile文件中一般会有下面的代码?br />if [ -f ~/.bashrc ] ; then<br />. ./bashrc<br />fi<br />所以,~/.bashrc会调?/etc/bashrc文件?/p> <p><strong class="yibqv">3</strong><strong class="yibqv">、最后,在退出shell时,还会执行 ~/.bash_logout文件?/strong></p> <p><strong class="yibqv">所以一个用户从登录到登出的执行顺序为:/etc/profile -> (~/.bash_profile | ~/.bash_login | ~/.profile) -> ~/.bashrc ->/etc/bashrc -> ~/.bash_logout</strong></p> <p><strong class="yibqv">当我们查看当前用户的隐藏文件【ls -al】是否有这些文件的时候,这些文件都丢失了,所以就会出现bash-3.2的错误。也就是取不到当前登录用户的变量导致?/strong></p> <p><strong class="yibqv">备注:关于各个文件的作用域,在网上找到了以下说明?/strong></p> <p><strong class="yibqv">??etc/profile?此文件为系统的每个用户设置环境信?当用户第一次登录时,该文件被执行. 并从/etc/profile.d目录的配置文件中搜集shell的设置?/strong></p> <p><strong class="yibqv">??etc/bashrc: 为每一个运行bash shell的用户执行此文件.当bash shell被打开?该文件被读取?/strong></p> <p><strong class="yibqv">?)~/.bash_profile: 每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一?默认情况?他设置一些环境变?执行用户?bashrc文件?/strong></p> <p><strong class="yibqv">?)~/.bashrc: 该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell?该该文件被读取?/strong></p> <p><strong class="yibqv">??/strong><strong class="yibqv"><sub>/.bash_logout:当每次退出系?退出bash shell)?执行该文? 另外,/etc/profile中设定的变量(全局)的可以作用于任何用户,?/sub></strong><strong class="yibqv">/.bashrc等中设定的变?局?只能继承/etc/profile中的变量,他们?父子"关系?/strong></p> <p><strong class="yibqv">??/strong><strong class="yibqv"><sub>/.bash_profile 是交互式、login 方式进入 bash 运行?/sub></strong><strong class="yibqv">/.bashrc 是交互式 non-login 方式进入 bash 运行的通常二者设置大致相同,所以通常前者会调用后者?/strong></p> <p><strong class="yibqv"> </strong></p> <p><strong class="yibqv">解决方案?/strong></p> <p><strong class="yibqv"> </strong> <strong class="yibqv">从正确的环境copy?/strong><strong class="yibqv">.bash_profile</strong><strong class="yibqv">?bashrc?bash_logout</strong><strong class="yibqv">三个文件中任一丢失的文件到当前目录下面。让其生效即可?/strong></p> <p><strong class="yibqv">但为什么这三个文件丢失我没有找到其丢失的原因,最根本的猜测就是大家不小心删除了。另外linux的问题我个人的经验就是顺藤摸瓜、掌握原理之后就很多解决了!</strong></p><img src ="//www.ot7t.com.cn/lingy/aggbug/369057.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/lingy/" target="_blank">林光?/a> 2012-01-31 10:53 <a href="//www.ot7t.com.cn/lingy/archive/2012/01/31/369057.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle DDL,DML,DCL,TCL 基础概念 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2010/08/17/329116.html林光?/dc:creator>林光?/author>Tue, 17 Aug 2010 08:50:00 GMT//www.ot7t.com.cn/lingy/archive/2010/08/17/329116.htmlDDL
Data Definition Language (DDL) statements are used to define the database structure or schema. Some examples:
  • CREATE - to create objects in the database
  • ALTER - alters the structure of the database
  • DROP - delete objects from the database
  • TRUNCATE - remove all records from a table, including all spaces allocated for the records are removed
  • COMMENT - add comments to the data dictionary
  • RENAME - rename an object

DML

Data Manipulation Language (DML) statements are used for managing data within schema objects. Some examples:
  • SELECT - retrieve data from the a database
  • INSERT - insert data into a table
  • UPDATE - updates existing data within a table
  • DELETE - deletes all records from a table, the space for the records remain
  • MERGE - UPSERT operation (insert or update)
  • CALL - call a PL/SQL or Java subprogram
  • EXPLAIN PLAN - explain access path to data
  • LOCK TABLE - control concurrency

DCL

Data Control Language (DCL) statements. Some examples:
  • GRANT - gives user's access privileges to database
  • REVOKE - withdraw access privileges given with the GRANT command

TCL

Transaction Control (TCL) statements are used to manage the changes made by DML statements. It allows statements to be grouped together into logical transactions.
  • COMMIT - save work done
  • SAVEPOINT - identify a point in a transaction to which you can later roll back
  • ROLLBACK - restore database to original since the last COMMIT
  • SET TRANSACTION - Change transaction options like isolation level and what rollback segment to use


作者:李敬然(Gnie?br /> 出处?a >{GnieTech} (//www.cnblogs.com/gnielee/?br /> 版权声明:本文的版权归作者与博客园共有。转载时须注明本文的详细链接,否则作者将保留追究其法律责任?/p>

]]>
linux 命令 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2010/08/17/329113.html林光?/dc:creator>林光?/author>Tue, 17 Aug 2010 08:28:00 GMT//www.ot7t.com.cn/lingy/archive/2010/08/17/329113.html 

insert into ali_zeus_access_area
select * from ali_zeus_access_area@zeus_dev;

script -q tty.log

sqlplus /nolog
conn rnd/mCQe88il@crmintsb
conn rnd/mCQe88il@crmint


scp tty.log guangyan.lingy@10.20.130.14:/home/guangyan.lingy/tty0601.log

export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
sqlplus rnd/mCQe88il@crmg

for remote in \
172.16.131.47 172.16.131.48 172.16.131.49 172.16.131.50 172.16.131.51 172.16.131.52 172.16.131.53 172.16.131.54 172.16.131.55 172.16.131.2 172.16.131.3 172.16.131.4 172.16.131.5 172.16.131.6 172.16.131.7 172.16.131.41 172.16.131.42 172.16.131.56 172.16.131.57 172.16.131.58 \
;do echo $remote; ssh $remote "grep 'sms webService visitor IP is' output/logs/user/martini_sales_tool.log"; done

 

daisy.louy
 louying
 
 
carvin hello123
//svn.alibaba-inc.com/repos/crm/martini/branches/20091209_dcs_guangyan.lingy_dev

weiming.shi
jinbo.yu
1234567890 alibaba-guest
我刚又试?/p>


中国的十大宜居小?中午的时候看?br /> //focus.news.163.com/10/0531/09/680LGN5L00011SM9.html
有泉?)

数据模型资源手册

需要低烟无卤阻燃电缆料的电缆企?/p>

]]>
《设计模式》之Java解读--桥接Bridge - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2010/07/29/327422.html林光?/dc:creator>林光?/author>Thu, 29 Jul 2010 05:56:00 GMT//www.ot7t.com.cn/lingy/archive/2010/07/29/327422.html阅读全文

]]>
无法定位程序输入点_except_handler4_common于动态链接库msvcrt.dll?/title><link>//www.ot7t.com.cn/lingy/archive/2010/07/05/325279.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Mon, 05 Jul 2010 06:12:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2010/07/05/325279.html</guid><description><![CDATA[<p>最近,多种软件都出现了一个启动时的错误提?“无法定位程序输入点_except_handler4_common于动态链接库msvcrt.dll?#8221;?/p> <p>出现这个提示情况是:Windows Xp 系统?软件包括:window live writer 2009, windows messenger 2009, firefox 3.5 等非常新的版本?/p> <p>这个提示出现后,点击确定,并不影响程序的使用。这个问题出现的原因,其实微软自己的问题。可谓是微软的Vista 后遗症吧?/p> <p>?Vista 系统里,有个挺酷的功能,就是“程序缩略?#8221;,有?D效果,这个功能,调用?dwmapi.dll 这个库,?dwmapi.dll 又引用了 msvcrt.dll 中的 _except_handler4_common 功能?/p> <p>然而,在XP系统中,系统自带?msvcrt.dll  ?Vista 中的 msvcrt.dll 版本不同?并没有这?_except_handler4_common ,结果就出现了启动程序时,遇到的 “无法定位程序输入点_except_handler4_common于动态链接库msvcrt.dll?#8221;的错误提示?/p> <p><strong class="yibqv">解决方法</strong>?/p> <div class="content-sub-title">      ?c:\windows\system32 下的 dwmapi.dll 改名,例如:改为 dwmapi.dll.bak?/div> <img src ="//www.ot7t.com.cn/lingy/aggbug/325279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/lingy/" target="_blank">林光?/a> 2010-07-05 14:12 <a href="//www.ot7t.com.cn/lingy/archive/2010/07/05/325279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle 回滚 sql操作 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2010/06/02/322585.html林光?/dc:creator>林光?/author>Wed, 02 Jun 2010 08:31:00 GMT//www.ot7t.com.cn/lingy/archive/2010/06/02/322585.html

]]>
Eclipse 启动运行速度调优 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/10/01/297077.html林光?/dc:creator>林光?/author>Thu, 01 Oct 2009 03:24:00 GMT//www.ot7t.com.cn/lingy/archive/2009/10/01/297077.html

JVM 提供了各种用于调整内存分配和垃圾回收行为的标准开关和非标准开关。其中一些设置可以提?JAVA IDE 的性能?
注意,由?-X (尤其是 -XX JVM)开关通常?JVM ?JVM 供应商特定的,本部分介绍的开关可用于 Sun Microsystems J2SE 1.4.2?/p>

以下设置在大多数系统上将产生比工厂更好的设置性能?
-vmargs - 表示将后面的所有参数直接传递到所指示?Java VM?/p>

-Xverify:none - 此开关关闭Java字节码验证,从而加快了类装入的速度,并使得在仅为验证目的而启动的过程中无需装入类。此开关缩短了启动时间,因此没有理由不使用它?

-Xms24m - 此设置指?Java 虚拟机将其初始堆大小设置?24 MB。通过指示 JVM 最初应分配给堆的内存数量,可以?JVM 不必?IDE 占用较多内存时增加堆大小?

-Xmx96m - 此设置指?Java 虚拟机应对堆使用的最大内存数量。为此数量设置上限表?Java 进程消耗的内存数量不得超过可用的物理内存数量。对于具有更多内存的系统可以增加此限制,96 MB 设置有助于确?IDE 在内存量?128MB ?256MB 的系统上能够可靠地执行操作。注意:不要将该值设置为接近或大于系统的物理内存量,否则将在主要回收过程中导致频繁的交换操作?

-XX:PermSize=20m - ?JVM 开关不仅功能更为强大,而且能够缩短启动时间。该设置用于调整内存"永久区域"(类保存在该区域中)的大小。因此我们向 JVM 提示它将需要的内存量。该设置消除了许多系统启动过程中的主要垃圾收集事件。SunONE Studio 或其它包含更多模块的 IDE 的用户可能希望将该数值设置得更高?
下面列出了其它一些可能对 ECLIPSE 在某些系统(不是所有系统)上的性能产生轻微或明显影响的 JVM 开关。尽管使用它们会产生一定的影响,但仍值得一试?

-XX:CompileThreshold=100 - 此开关将降低启动速度,原因是与不使用此开关相比,HotSpot 能够更快地将更多的方法编译为本地代码。其结果是提高了 IDE 运行时的性能,这是因为更多的 UI 代码将被编译而不是被解释。该值表示方法在被编译前必须被调用的次数?

-XX:+UseConcMarkSweepGC -XX:+UseParNewGC - 如果垃圾回收频繁中断,则请尝试使用这些开关。此开关导?JVM 对主要垃圾回收事件(如果在多处理器工作站上运行,则也适用于次要回收事件)使用不同的算法,这些算法不会影响整个垃圾回收进程。注意:目前尚不确定此收集器是提高还是降低单处理器计算机的性能?

-XX:+UseParallelGC - 某些测试表明,至少在内存配置相当良好的单处理器系统中,使用此回收算法可以将次要垃圾回收的持续时间减半。注意,这是一个矛盾的问题,事实上此回收器主要适用于具有千兆字节堆的多处理器。尚无可用数据表明它对主要垃圾回收的影响。注意:此回收器?-XX:+UseConcMarkSweepGC 是互斥的?/p>

我的机器?12MB的内?br /> 下面是我的eclipse启动参数:eclipse.exe -vmargs -Xverify:none -Xms64M -Xmx256M -XX:PermSize=20M  -XX:+UseParallelGC

-----

我的电脑?G内存, 有一次内存不足了... MyEclipse 就推荐我使用一个启动参? 现在我的启动参数?


eclipse.exe -vmargs -Xverify:none -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M -XX:+UseParallelGC



]]>
树结构和它的专用函数SYS_CONNECT_BY_PATH - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/09/20/295773.html林光?/dc:creator>林光?/author>Sun, 20 Sep 2009 13:32:00 GMT//www.ot7t.com.cn/lingy/archive/2009/09/20/295773.html 关于树的普通应?br /> 学习了下这个函数, 用ORGINDUSTRIES的表做了个测?
正常的树型结?br /> select lpad(' ',6*(level-1))||industry,indlevel,indid,pindid
from ORGINDUSTRIES
start with indid=1
connect by pindid=prior indid
结果显示如下
                 Indlevel  indid    pindid
        服装与服?nbsp;              1             1             0
              服装               2             2               1
                    女装        3             3               2

倒型?br /> 下面这个例子是个”倒数”—倒过来的树型结构
select lpad(' ',6*(level-1))||industry,indlevel,indid,pindid
from ORGINDUSTRIES
start with indid=20
connect by indid=prior pindid;
这是标准结果:
                             Indlevel indid    pindid
二手服装                      3        20       2
      服装                    2        2        1
            服装与服?nbsp;       1        1        0
结论
无论正树还是倒树, 关键就在于connect by的条?
正树:  必须?nbsp; ‘?#8217;= prior ‘?#8217;
倒树:  必须?nbsp; ‘?#8217;= prior ‘?#8217;

树型结构的条件过?br /> 采用树型结构的话, 如果我们想将树上的一个分支砍?  将分支后面的结构都抛弃掉, 这个可以实现麽?当然可以?但是不是用where?where条件只能去除单一的条件?br /> 所以, 这种树型的过滤条件就需要加在connect by上面?br />
测试如下:由于用真实环境比较贴近实际,所以提前用下SYS_CONNECT_BY_PATH函数来显示下环境

不加任何条件的环境:
select areaname,sys_connect_by_path(areaname,',')
from areas bb
start with areaname='中国大陆'
connect by parentareaid=prior areaid  

结果?br /> 1        中国大陆,中国大陆
2        北京        ,中国大陆,北京
3        北京        ,中国大陆,北京,北京
4        东城?nbsp;       ,中国大陆,北京,东城?br /> 5        西城?nbsp;       ,中国大陆,北京,西城?br /> 22        广东        ,中国大陆,广东
23        广州        ,中国大陆,广东,广州
24        汕尾        ,中国大陆,广东,汕尾
25        潮阳        ,中国大陆,广东,潮阳
46        上海        ,中国大陆,上海
47        上海        ,中国大陆,上海,上海
48        黄浦?nbsp;       ,中国大陆,上海,黄浦?br /> 49        闸北?nbsp;       ,中国大陆,上海,闸北?br />

加了where过滤条件的SQL:
select areaname,sys_connect_by_path(areaname,',')
from areas bb
where bb.areaid>861000
start with areaname='中国大陆'
connect by parentareaid=prior areaid

结果为:
2        北京        ,中国大陆,北京
3        北京        ,中国大陆,北京,北京
4        东城?nbsp;       ,中国大陆,北京,东城?br /> 5        西城?nbsp;       ,中国大陆,北京,西城?br /> 22        广东        ,中国大陆,广东
23        广州        ,中国大陆,广东,广州
24        汕尾        ,中国大陆,广东,汕尾
25        潮阳        ,中国大陆,广东,潮阳
46        上海        ,中国大陆,上海
47        上海        ,中国大陆,上海,上海
48        黄浦?nbsp;       ,中国大陆,上海,黄浦?br /> 49        闸北?nbsp;       ,中国大陆,上海,闸北?br />
结论:去掉了“1        中国大陆,中国大陆”数据

加了connect by的过滤条件:
select areaname,sys_connect_by_path(areaname,',')
from areas bb
where bb.areaid>861000
start with areaname='中国大陆'
connect by parentareaid=prior areaid  and areaname<>'广东'

结果为:
2        北京        ,中国大陆,北京
3        北京        ,中国大陆,北京,北京
4        东城?nbsp;       ,中国大陆,北京,东城?br /> 5        西城?nbsp;       ,中国大陆,北京,西城?br /> 46        上海        ,中国大陆,上海
47        上海        ,中国大陆,上海,上海
48        黄浦?nbsp;       ,中国大陆,上海,黄浦?br /> 49        闸北?nbsp;       ,中国大陆,上海,闸北?br />
结论:去掉了整个广东的分支,  在结果集中只有北京和上海


SYS_CONNECT_BY_PATH函数
采用SYS_CONNECT_BY_PATH函数?

select industry,sys_connect_by_path(industry,'/')
from ORGINDUSTRIES
start with indid=3
connect by indid=prior pindid;

结果?
女装               /女装
服装               /女装/服装
服装与服?nbsp;           /女装/服装/服装与服?br />
这样的话, 就可以实? 树结构的结果集的单行拼接:

我们只需要取最大的字段就OK?br />
测试如下?br />
select max(sys_connect_by_path(industry,'/'))
from ORGINDUSTRIES
start with indid=3
connect by indid=prior pindid;

结果为:
/女装/服装/服装与服?br />

复杂的树型结构――多列变单列
树型结构也分单树和多?我的称呼,实际上就是指单支和多?
对于下面的这种情况, 我们必须要构造的树就属于单支树?br /> 原始环境
环境如下?br /> select * from test?br />
结果为:
1        n1
1        n2
1        n3
1        n4
1        n5
3        t1
3        t2
3        t3
3        t4
3        t5
3        t6
2        m1

造树
脚本如下?br /> select no,q,
       no+row_number() over( order by no) rn,
       row_number() over(partition by no order by no) rn1
from test

结果如下?br /> No  Q  RN RN1
1        n1        2        1
1        n2        3        2
1        n3        4        3
1        n4        5        4
1        n5        6        5
2        m1        8        1
3        t1        10        1
3        t2        11        2
3        t3        12        3
3        t4        13        4
3        t5        14        5
3        t6        15        6

每列的目的是?br /> RN1列主要的目的是分组, 按照value?#8216;1’,我们可以start with使用它?br />
RN列主要用来做connect by使用?实际上它就是我们要的树?br /> 第一个支?2????
第二个支?8
第三个支?10?1?2?3?4?5

中间为什么要断掉?,9  目的就是为了区别每个分支?到后面看具体的SQL,就明白这里的说法了?br />
杀手锏
既然我们有了树, 就可以使用树型函数SYS_CONNECT_BY_PATH和connect by啦,来拼接我们所需要的多列值?br />
脚本如下?br /> select no,sys_connect_by_path(q,',')
from (
select no,q,
       no+row_number() over( order by no) rn,
       row_number() over(partition by no order by no) rn1
from test
)
start with rn1=1
connect by rn-1=prior rn

结果为:
1        ,n1
1        ,n1,n2
1        ,n1,n2,n3
1        ,n1,n2,n3,n4
1        ,n1,n2,n3,n4,n5
2        ,m1
3        ,t1
3        ,t1,t2
3        ,t1,t2,t3
3        ,t1,t2,t3,t4
3        ,t1,t2,t3,t4,t5
3        ,t1,t2,t3,t4,t5,t6

终极武器
最终我们要的值,是单列值, 其实想想?也就是最长的一行咯?那么就好办了?我们直接GROUP BY ,然后取MAX值?br /> 脚本如下?br /> select no,max(sys_connect_by_path(q,','))
from (
select no,q,
       no+row_number() over( order by no) rn,
       row_number() over(partition by no order by no) rn1
from test
)
start with rn1=1
connect by rn-1=prior rn
group by no

结果为:
1        ,n1,n2,n3,n4,n5
2        ,m1
3        ,t1,t2,t3,t4,t5,t6

如果觉得前面?#8216;?#8217;不好看,可以使用ltrim去掉?或者用substr也可以?br /> 如下?br /> ltrim(max(sys_connect_by_path(q,',')),',')
或?br /> substr(max(sys_connect_by_path(q,',')),2)


]]>
vim 到指定行 :3305 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/09/02/293577.html林光?/dc:creator>林光?/author>Wed, 02 Sep 2009 04:28:00 GMT//www.ot7t.com.cn/lingy/archive/2009/09/02/293577.html :number
eg:
:3305

]]>
Vim查找操作 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/09/02/293576.html林光?/dc:creator>林光?/author>Wed, 02 Sep 2009 04:25:00 GMT//www.ot7t.com.cn/lingy/archive/2009/09/02/293576.html 

" 搜索
/joe/e : 设置光标到匹?joe"的末?br /> /joe/e+1 : 设置光标到匹?joe"的末尾再后移一?br /> /joe/s-2 : 设置光标到匹?joe“的开头再前移两位
/^joe.*fred.*bill/ : 匹配?j'开头且"joe"?fred"?bill"之间至少有一个字?br /> /^[A-J]\+/ : 搜索'A'?#8217;J‘重复两次以上的开头行
/begin\_.*end : 多行匹配
/fred\_s*joe/i : 可以是任何空白字符包括\n,\t等等
/fred\|joe : 搜索fred或者joe
/.*fred\&.*joe : 搜索同时包括fred跟joe的行
/\<fred\>/i : 搜索独立的单词fred
/\<\d\d\d\d\> : 搜索独立?位数?br /> /\D\d\d\d\d\D : 搜索6位字符串中间4位数字前后两位不能为数字
/\<\d\{4}\> : ?\<\d\d\d\d\>
" 查找空行
/^\n\{3} : 匹配三连续的空行
" 使用正则表达式组查找
/\(fred\).*\(joe\).*\2.*\1
" 正则表达式重?br /> /^\([^,]*,\)\{8}
" visual searching
:vmap // y/<C-R>"<CR> : visually模式下的键盘映射,把//映射成匹配当前选中的文?br /> :vmap <silent> // y/<C-R>=escape(@", '\\/.*$^~[]')<CR><CR> : 包括空白字符
" \zs ?\ze 匹配?:h /\zs
/<\zs[^>]*\ze> : 匹配尖括号中的内?br /> " 零宽度匹?:h /\@=
/<\@<=[^>]*>\@= : search for tag contents, ignoring chevrons
/<\@<=\_[^>]*>\@= : search for tags across possible multiple lines
" 多行查找 \_ 的意思是包括换行?br /> /<!--\_p\{-}--> : 匹配<!--开始到-->结尾的所有内?br /> /fred\_s*joe/i : 匹配fred开始到joe,之间一定得是空白字?br /> /bugs\(\_.\)*bunny : 匹配所有bugs到bunny的字符串
:h \_ : help
" 查找函数声明,nmap为normal模式下的键盘映射
:nmap gx yiw/^\(sub\<bar>function\)\s\+<C-R>"<CR>
" 查找多个文件
:bufdo /searchstr/ : 在多个文件缓冲区里执行查?br /> " 更好的多文件查找定位方法
:bufdo %s/searchstr/&/gic : 在多个文件缓冲区里查找,按下n停止
" 怎样不使?/ 来查找网址
?
//www.vim.org/ : 向后查找
" 查找指定字符以外的字符串
/\c\v([^aeiou]&\a){4} : 查找4个辅音字?br /> ----------------------------------------
#替换
:%s/fred/joe/igc : 普通替换命?br /> :%s/\r//g : 删除 DOS 的换行符 ^M
" 你的文本文件是否乱七八糟的排成一行?使用如下命令
:%s/\r/\r/g : 转换 DOS 回车?^M 为真正的回车?br /> :%s= *$== : 删除行尾空白
:%s= \+$== : 同上
:%s#\s*\r\?$## : 删除尾部空白和dos换行?br /> :%s#\s*\r*$## : 同上
" 删除空行
:%s/^\n\{3}// : 删除连续3个空?br /> :%s/^\n\+/\r/ : 压缩空行,多个替换为一?br /> %s#<[^>]\+>##g : 删除html的tag部分
" IF YOU ONLY WANT TO KNOW ONE THING
:'a,'bg/fred/s/dick/joe/igc : 非常有用
# 译释?'a,''b指定一个范围:mark a ~ mark b
# g//用一个正则表达式指出了进行操作的行必须可以被fred匹配
# 看后面,g//是一个全局显示命令
# s/dick/joe/igc则对于这些满足条件的行进行替?br /> " 复制?br /> :%s= [^ ]\+$=&&= : 复制最后一?br /> :%s= \f\+$=&&= : 一?br /> :%s= \S\+$=&& : 晕,还一样!
" 记忆(反向引用)
:s/\(.*\):\(.*\)/\2 : \1/ : 将两个字段颠?br /> :%s/^\(.*\)\n\1$/\1/ : 删除重复?br /> " 非贪婪匹?\{-}
:%s/^.\{-}pdf/new.pdf/ : 删除第一个pdf
" use of optional atom \?
:%s#\<[zy]\?tbl_[a-z_]\+\>#\L&#gc : lowercase with optional leading characters
" 跨越尽量多的?br /> :%s/<!--\_.\{-}-->// : 删除多行注释
:help /\{-} : 查看非贪婪匹配的更多帮助
" 使用寄存器替?br /> :s/fred/<c-r>a/g : 将fred替换为寄存器a里的内容
:s/fred/<c-r>asome_text<c-r>s/g
:s/fred/\=@a/g : better alternative as register not displayed
" 在一行里写多种命?br /> :%s/\f\+\.gif\>/\r&\r/g | v/\.gif$/d | %s/gif/jpg/
:%s/a/but/gie|:update|:next : 当使?@: 来重?br /> " 或运?br /> :%s/suck\|buck/loopy/gc : 替换suck或者buck(这里|不是管道?br /> " 调用vim函数
:s/__date__/\=strftime("%c")/ : 将__date__替换成当前日期,使用strftime函数
" 处理列,替换所有在第三列中的str1
:%s:\(\(\w\+\s\+\)\{2}\)str1:\1str2:
" 交换第一列跟第四?br /> :%s:\(\w\+\)\(.*\s\+\)\(\w\+\)$:\3\2\1:
" 过滤form中的内容放在寄存器里
:redir @*|sil exec 'g#<\(input\|select\|textarea\|/\=form\)\>#p'|redir END
:nmap ,z :redir @*<Bar>sil exec 'g@<\(input\<Bar>select\<Bar>textarea\<Bar>
/\=form\)\>@p'<Bar>redir END<CR>
" 两位以上的数字减三(带进位。这个命令挺有趣?br /> :%s/\d\+/\=(submatch(0)-3)/
" 包含loc或者functions的行中的数字?
:g/loc\|function/s/\d/\=submatch(0)+6/
" 比上面更好的方法
:%s#txtdev\zs\d#\=submatch(0)+1#g
:h /\zs 查看帮助
" 前缀为gg的数字加6
:%s/\(gg\)\@<=\d\+/\=submatch(0)+6/
:h zero-width 查看帮助
" 替换一个特定字符串为数?br /> :let i=10 | 'a,'bg/Abc/s/yy/\=i/ |let i=i+1 # 将yy转换?0?1?2等等
" 比上面的更精?br /> :let i=10 | 'a,'bg/Abc/s/xx\zsyy\ze/\=i/ |let i=i+1 # 将xxyy 转换?xx11,xx12,
xx13
" find replacement text, put in memory, then use \zs to simplify substitute
:%s/"\([^.]\+\).*\zsxx/\1/
" Pull word under cursor into LHS of a substitute
:nmap <leader>z :%s#\<<c-r>=expand("<cword>")<cr>\>#
" Pull Visually Highlighted text into LHS of a substitute
:vmap <leader>z :<C-U>%s/\<<c-r>*\>/
----------------------------------------
" all following performing similar task, substitute within substitution
" Multiple single character substitution in a portion of line only
:%s,\(all/.*\)\@<=/,_,g : replace all / with _ AFTER "all/"
" Same thing
:s#all/\zs.*#\=substitute(submatch(0), '/', '_', 'g')#
" Substitute by splitting line, then re-joining
:s#all/#&^M#|s#/#_#g|-j!
" Substitute inside substitute
:%s/.*/\='cp '.submatch(0).' all/'.substitute(submatch(0),'/','_','g')/
----------------------------------------
" 全局显示命令
:g/gladiolli/# : 查找并显示匹配的行号
:g/fred.*joe.*dick/ : 显示所有含?fred,joe & dick的行
:g/\<fred\>/ : 显示单一单词fred
:g/^\s*$/d : 删除所有空?br /> :g!/^dd/d : 删除不含字符?'dd''的行
:v/^dd/d : 同上
:g/fred/,/joe/d : 删除所有的从fred到joe
:g/-------/.-10,.d : ?------为标记删除之前的10?br /> :g/{/ ,/}/- s/\n\+/\r/g : 删除 {...}之间的空?br /> :v/\S/d : Delete empty lines (both types)
:v/./,/./-j : 压缩空行
:g/^$/,/./-j : 同上
:g/<input\|<form/p : 或运?br /> :g/^/put_ : 双倍行?(pu = put)
:g/^/m0 : 颠倒文?(m = move)
:'a,'bg/^/m'b : 颠倒选中?a ?b
:g/^/t. : 重复?br /> :g/fred/t$ : 拷贝行从fred到结?br /> :g/stage/t'a : 拷贝行从stage ?marker a(a为标记的位置?br /> :g/\(^I[^^I]*\)\{80}/d : 删除最少包?0个tab的行
" perform a substitute on every other line
:g/^/ if line('.')%2|s/^/zz /
" match all lines containing "somestr" between markers a & b
" copy after line containing "otherstr"
:'a,'bg/somestr/co/otherstr/ : co(py) or mo(ve)
" as above but also do a substitution
:'a,'bg/str1/s/str1/&&&/|mo/str2/
:%norm jdd : 隔行删除
" 增加数字 (键入 <c-a>)
:.,$g/^\d/exe "norm! \<c-a>": 增加从当前行首到结尾的数?br /> :'a,'bg/\d\+/norm! ^A : 增加数字
" 保存全局命令的结?(注意必须使用添加模式) 你需要使?qaq 清空寄存器a.
"save results to a register/paste buffer 存储结果?寄存?粘贴 ?a
:g/fred/y A : 添加配备行到寄存器到 a
:g/fred/y A | :let @*=@a : 放入复制缓冲?br /> :let @a=''|g/Barratt/y A |:let @*=@a
:'a,'b g/^Error/ . w >> errors.txt
" 复制每一行,然后在复制出来的每一行两侧加上一?print '复制出来的内?
:g/./yank|put|-1s/'/"/g|s/.*/Print '&'/
" 用文件中的内容替换字符串?d 表示删除“标记”
:g/^MARK$/r tmp.ex | -d
" display prettily
:g/<pattern>/z#.5 : display with context
:g/<pattern>/z#.5|echo "==========" : display beautifully
" Combining g// with normal mode commands
:g/|/norm 2f|r* : replace 2nd | with a star
"send output of previous global command to a new window
:nmap <F3> :redir @a<CR>:g//<CR>:redir END<CR>:new<CR>:put! a<CR><CR>
----------------------------------------
" 全局命令和替换命令联?(强大的编辑能?
:'a,'bg/fred/s/joe/susan/gic : 可以使用反向引用来匹?br /> :g/fred/,/joe/s/fred/joe/gic : non-line based (ultra)
----------------------------------------
" 先找fred,然后找joe
:/fred/;/joe/-2,/sid/+3s/sally/alley/gIC
----------------------------------------
" create a new file for each line of file eg 1.txt,2.txt,3,txt etc
:g/^/exe ".w ".line(".").".txt"
----------------------------------------
" Absolutely essential
----------------------------------------
* # g* g# : 查找当前光标下的单词(单个单词) (<cword>) (向前/向后)
% : 匹配括号 {}[]()
. : 重复上次操作
@: : 重复上次的命?br /> matchit.vim : ?能匹?<script> <?php等标?br /> <C-N><C-P> : 插入模式下自动完成填?br /> <C-X><C-L> : 行自动完成(超级有用?br /> /<C-R><C-W> : 把单?lt;cword>单词放入搜索或者命令行
/<C-R><C-A> : 把字符串中有的单?lt;CWORD>放入搜索或者命令行
:set ignorecase : 忽略大小?br /> :syntax on : 打开语法高亮 Perl,HTML,PHP 等等
:h regexp<C-D> : 按ctrl+d得到包含regexp的列?br /> (按tab自动不齐)
----------------------------------------
" 简单编辑更?_vimrc文件
:nmap ,s :source $VIM/_vimrc :普通模式下的键盘映?,s映射成加载用户目录下?br /> _vimrc文件
:nmap ,v :e $VIM/_vimrc :,v映射成打开_vimrc文件
----------------------------------------
#VISUAL 模式 (方便增加 HTML 标签)
:vmap sb "zdi<C-R>z<ESC> : ?VISUALLY模式下将选中的文本前后分别加?br /> :vmap st "zdi<?= <C-R>z ?><ESC> : 加上 <?= ?>
----------------------------------------
" 浏览
:Exp(lore) : 浏览文件
:Sex(plore) : 分割窗口浏览文件
:ls : 显示缓冲?br /> :cd .. : 设置当前目录位置
:args : 查看当前打开的所有文?br /> :lcd %:p:h : 改变路径到当前编辑的文件
:autocmd BufEnter * lcd %:p:h : 放入.vimrc自动完成上面的命?br /> ----------------------------------------
" 缓冲区浏?一直排名前10的vim脚本)
" 需?bufexplorer.vim
//www.vim.org/script.php?script_id=42
\be : 缓冲浏览器中查看缓冲列表
\bs : 同上,但是分割窗?br /> ----------------------------------------
" 转换大小?br /> guu : 将正行的字母转换成小?br /> gUU : 将正行的字母转换成大?br /> Vu : 转换选中的行(小写)
VU : 转换选中的行(大写)
g~~ : 反向转换
vEU : 转换词大?br /> vE~ : 反向转换?br /> ggguG : 将当前编辑文件内容全部转换成小写
" Visually 模式下选择所有的字母及数?(放入 .vimrc文件?
vmap ,c :s/\<\(.\)\(\k*\)\>/\u\1\L\2/g<CR>
" 大写所有句子的第一个字?br /> :%s/[.!?]\_s\+\a/\U&\E/g
----------------------------------------
gf : 打开当前光标下或后的文件
:nnoremap gF :view <cfile><cr> : 打开当前光标下或后的文件, 如果不存在则创建
ga : 显示当前光标下单个字的ascii,十进制,十六进制……
ggVGg? : 将整个文件用rot13编码……(谁看得懂啊~~hoho)
ggg?G : 同上 (针对大文?
:8 | normal VGg? : 将第八行用rot13编码
:normal 10GVGg? : 同上
<C-A>,<C-X> : 增加,减少当前光标下的数?br /> win32 用户需要重定义 CNTRL-A
<C-R>=5*5 : 插入25 (小型计算?
----------------------------------------
" 几个彩蛋……
:h 42 : also
//www.google.com/search?q=42
:h holy-grail
:h!
----------------------------------------
" 标记 & 移动
'. : 跳回最后编辑的?(超有?
`. : 同上,但是定位编辑点
g; : 跳转到比较旧的编辑位置(如果有的话) (vim6.3后的新功?
g, : 这个是较心的位置 (同上)
:changes :打出改变?br /> :h changelist : 查看“改变表跳?#8221;的帮?br /> <C-O> : 依次沿着你的跳转记录向回?(从最近的一次开?
<C-I> : 依次沿着你的跳转记录向前?br /> :ju(mps) : 列出跳转轨迹
:help jump-motions
:history : 列出历史记录
:his c : 命令行历?br /> :his s : 搜索历史
q/ : 搜索命令历史的窗?br /> q: : 命令行命令历史的窗口
:<C-F> : 历史窗口
----------------------------------------
" 缩写 & 映射
:map <f7> :'a,'bw! c:/aaa/x
:map <f8> :r c:/aaa/x
:map <f11> :.w! c:/aaa/xr<CR>
:map <f12> :r c:/aaa/xr<CR>
:ab php : 查看以php开头的缩写
:map , : 列出所有的映射(以逗号开始的?br /> " 允许映射 F10 (win32)
set wak=no : :h winaltkeys
" 映射中常使用的表?br /> <CR> : 回车
<ESC> : Esc
<LEADER> : 右斜?br /> <BAR> : 管道符号
<BACKSPACE> : 退格键
<SILENT> : 不回?br /> #显示自定义的 RGB 颜色显示当前光标下的字符?例如 #445588
:nmap <leader>c :hi Normal guibg=#<c-r>=expand("<cword>")<cr><cr>
map <f2> /price only\\|versus/ :in a map need to backslash the \
----------------------------------------
" Simple PHP debugging display all variables yanked into register a
" 简单的 PHP 调试将所有显示的变量放入寄存器a
iab phpdb exit("<hr>Debug <C-R>a ");
----------------------------------------
" 使用寄存器来映射 (放入 .vimrc文件自动加载)
:let @m=":'a,'bs/"
:let @s=":%!sort -u"
----------------------------------------
" 列出寄存?br /> :reg : 显示当前所有的寄存?br /> :reg a : 显示寄存器a中的内容
"1p.... : 引用一个叫1的寄存器
:let @y='yy@"' : pre-loading registers (put in .vimrc)
qqq : 清空寄存?"q"
----------------------------------------
" 一些有用的决窍
"ayy@a : 把当前行作为命令执行
yy@" : 上面的匿名寄存器
u@. : 只执行键入的命令
----------------------------------------
" 从其它命令处获得输入(需要外部命令)
:r!ls.exe : 从ls 获得输入插入到当前位?br /> !!date : 从date获得输入(删除当前行?br /> " 使用外部sort排序
:%!sort -u : 用sort排序整个文件(结果覆盖整个文件)
:'a,'b!sort -u : 从mark a到mark b之间的内容进行排?br /> !1} sort -u : 排序一个段?br /> :g/^$/;,/^$/-1!sort : Sort each block (note the crucial ;)
----------------------------------------
" 多文件管?(基本?
:bn : 跳转到下一个buffer
:bp : 跳转到前一个buffer
:wn : 保存当前buffer并跳转到下一个buffer (超有?
:wp : 保存当前buffer并跳转到前一个buffer
:bd : 把当前文件从buffer移出 (超有?
:bun : 卸载当前buffer (关闭这个窗口但是不移?
:badd file.c : 添加file.c到buffer列表
:b 3 : 前往第三?buffer
:b main : 前往含有main的buffer?比如?main.c
:sav php.html : 把当前文件存为php.html并打开
:sav! %<.bak : 换一个后缀名保?(旧方?
:sav! %:r.cfm : 同上
:sav %:s/fred/joe/ : 替换文件?br /> :sav %:s/fred/joe/:r.bak2 : 替换文件和后缀
:!mv % %:r.bak : 重命名当前文?br /> :e! : 打开未修改之前的文件
:w c:/aaa/% : 存储文件到指定位?br /> :e # : 编辑标记?的文件在buffer?br /> :rew : 返回到第一个可编辑的文?br /> :brew : 回到第一个buffer
:sp fred.txt : 分割窗口打开fred.txt
:sball,:sb : 把所有的 buffers分割显示在一个窗口中 (超有?
:scrollbind : in each split window
:map <F5> :ls<CR>:e # : 按F5显示所有buffer, 并显示行?br /> :set hidden : 允许不保存当前buffer而进行切?br /> ----------------------------------------
" 在分割窗口中快速切?br /> map <C-J> <C-W>j<C-W>_
map <C-K> <C-W>k<C-W>_
----------------------------------------
" 录制命令 (最好的技?
qq # 录制命令放入 q寄存?br /> 输入一些命?br /> q # 录制结束
@q :执行放入寄存器q中的内容
@@ :重?br /> 5@@ :重??br /> " 编辑一?寄存?录制
"qp :显示寄存器q中的内容(普通模式下)
<ctrl-R>q :显示寄存器q中的内容 (插入模式?
" 你现在可以看到记录内容,随便编辑
"qdd :删除,重新存入q
@q :执行 录制/寄存?q
" 在可视块中运行记?br /> 1) 定义记录/寄存?br /> qq:s/ to/ from/g^Mq
2) 定义可视?br /> V}
3) 键入 : 将显示下面信?br /> :'<,'>
4)完成如下操作
:'<,'>norm @q
----------------------------------------
"combining a recording with a map (to end up in command mode)
nnoremap ] @q:w!<bar>bd
----------------------------------------
" 可视化模式提供一种灵活易用的方法选择一块文本供操作符使?br /> " 记出
v : 进入可视化模?br /> V : 进入可视化行选择模式
<C-V> : 进入可视化块选择模式
gv : 重新选择
o : 选择的区域头尾移?br /> "*y : 复制选择区域到paste buffer
V% : 选择一个匹配段
V}J : 合并一个段?br /> V}gJ : 合并一个段落,并保留空?br /> ----------------------------------------
" 删除选中?0行的前两个字符(不过这里应该假设是紧凑的排版格式,不能包含空格?br /> tab等字符的,可是经实验应该是钱3个字符才对啊???br /> 0<c-v>10j2ld
----------------------------------------
" 如何用可视块拷贝几列
" 可视?并非通常?v 命令)
<C-V>,然后通过移动命令选择?(win32 <C-Q>)
然后执行 c,d,y,r 等命?br /> ----------------------------------------
" how to overwrite a visual-block of text with another such block
Pick the first block: ctrl-v move "ay
Pick the second block: ctrl-v move c ctrl-o "aP <esc>
----------------------------------------
" _vimrc 基本设置
:set incsearch : 输入搜索命令时,立即显示目前输入的模式对应的匹配。匹配的字符?br /> 被高亮?br /> :set wildignore=*.o,*.obj,*.bak,*.exe : tab补全时忽略这些忽略这?br /> :set shiftwidth=3 : 设置自动缩进?个字?br /> :set vb t_vb=". : 安静模式,关闭响铃跟闪烁
:set browsedir=buffer : 设置文件浏览使用的目?br /> “注:
”last 使用文件浏览器最近访问相同的目录?br /> “buffer 使用相关缓冲区的目录?br /> ”current 使用当前目录?br /> “{path} 使用指定目录?br /> ----------------------------------------
" 启动windows中的IE
:nmap ,f :update<CR>:silent !start c:\progra~1\intern~1\iexplore.exe
file://%:p<CR>
:nmap ,i :update<CR>: !start c:\progra~1\intern~1\iexplore.exe <cWORD><CR>
----------------------------------------
" 在vim里打开ftp
cmap ,r :Nread
ftp://209.51.134.122/public_html/index.html
cmap ,w :Nwrite ftp://209.51.134.122/public_html/index.html
gvim ftp://www.somedomain.com/index.html # 使用 netrw.vim
----------------------------------------
" 向寄存器中添加内?(使用相应寄存器名称的大写)
" 复制5行放入a寄存器,然后向下跳转10行再复制5?br /> "a5yy
10j
"A5yy
----------------------------------------
[I : 显示当前行中字符的所有匹?超级有用)
----------------------------------------
" 常规缩进
:'a,'b>> :将mark a到mark b之间的内容进行两次缩?br /> " 虚拟模式下缩?(可重?
:vnoremap < <gv
”这是一个虚拟模式下的键盘映?< 映射?lt;gv
"< 意为向内缩进,gv 上面已有解释,为重复上次选区
“<gv 也就是先向内缩进然后再选择刚才的选区
“这样就可以只?< 实现重复缩进?br /> :vnoremap > >gv :向内缩进,原理同上
" 块缩?br /> >i{
>a{
" also
>% and <%
”自己试试看吧,涉及到?{ 的语言很有用,比如c,c++?br /> ----------------------------------------
" 重定?& 粘贴到寄存器 * ?为寄存器名称?br /> :redir @* : 重定向命令到paste缓冲?br /> :redir END : 结束
:redir >> out.txt : 重定向到文件
" 操作粘贴缓冲?br /> "*yy : 复制到寄存器
"*p : 从寄存器中粘贴一?br /> " 复制到粘贴缓冲区 (扩展模式)
:'a,'by* : 复制一个范围到粘贴寄存?br /> :%y* : 复制一个括号匹配到粘贴缓冲?br /> :.y* : 复制当前行到粘贴缓冲?br /> " 从剪贴板上过滤非可打印字?br /> " 当从一?GUI 程序粘贴时会有用?br /> :nmap <leader>p :let @* = substitute(@*,'[^[:print:]]','','g')<cr>"*p
----------------------------------------
" 重新格式化文?br /> gq} : 合并一个段?br /> gqap : 当前段落
ggVGgq : 全部段落
Vgq : 当前?br /> " ?0列的时候换?br /> :s/.\{,69\};\s*\|.\{,69\}\s\+/&\r/g
----------------------------------------
" 命令使用于多个文?br /> :argdo %s/foo/bar/e : 在所有文件上操做 :args
:bufdo %s/foo/bar/e
:windo %s/foo/bar/e
:argdo exe '%!sort'|w! : 包含外部命令
----------------------------------------
" 命令行技?br /> gvim -h : 显示帮助
ls | gvim - : 管道操作
cat xx | gvim - -c "v/^\d\d\|^[3-9]/d " : 从管道出过滤内容
gvim -o file1 file2 : 分割窗口显示两个文件
" 打开文件后执行一条命?br /> gvim.exe -c "/main" joe.c : 打开 joe.c & 跳转?"main"
" 在打开一个文件时执行多条命令
vim -c "%s/ABC/DEF/ge | update" file1.c
" 在一组文件上执行多条命令
vim -c "argdo %s/ABC/DEF/ge | update" *.c
" 从一系列文件中删除一块区?br /> vim -c "argdo /begin/+1,/end/-1g/^/d | update" *.c
" 自动编辑文件 (编辑命令序列Ex commands已经包含在convert.vim中了)
vim -s "convert.vim" file.c
#不加?vimrc跟任何plugin(干净清新?VIM^_^)
gvim -u NONE -U NONE -N
" Access paste buffer contents (put in a script/batch file)
gvim -c 'normal ggdG"*p' c:/aaa/xp
" 将paste中的内容送往默认的打印机
gvim -c 's/^/\=@*/|hardcopy!|q!'
" gvim 里的 grep (win32 or *nix)
:grep somestring *.php : 创建匹配的文件列?br /> " 使用 :cn(向后? :cp(向前) 操纵列表
:h grep :查看帮?br /> ----------------------------------------
" GVIM 的差异比?br /> gvim -d file1 file2 : vimdiff (比较不差?
dp : 把光标处的不同放到另一个文?br /> do : 在光标处从另一个文件取得不?br /> ----------------------------------------
" Vim traps
在正则表达式?+ | ( { 都要加上转义?反斜?
/fred\+/ : 匹配 fred/freddy 但不匹配 free
/\(fred\)\{2,3}/ : note what you have to break
----------------------------------------
" \v ,或叫做very magic (通常都是这么?可以取消转义?br /> /codes\(\n\|\s\)*where : 普通的正则表达?br /> /\vcodes(\n|\s)*where : very magic
----------------------------------------
" 把对象送到命令行或者搜索行
<C-R><C-W> : 执行当前光标下的单个单词
<C-R><C-A> : 执行当前光标下尽可能多的单词
<C-R>- : 送至一个小型寄存器(同样使用于插入模式?br /> <C-R>[0-9a-z] : 送至一个命名寄存器 (括弧同上)
<C-R>% : 送至文件?#也行) (同上)
<C-R>=somevar : 送至一个变?(例如 :let sray="ray[0-9]")
----------------------------------------
" 控制寄存?br /> :let @a=@_ : 清除寄存?a
:let @a="" : 同上 a
:let @*=@a : 拷贝寄存?a ?paste buffer
:let @*=@: : 拷贝最后执行的命令?paste buffer
:let @*=@/ : 拷贝最后执行的查找命令到paste buffer
:let @*=@% : 拷贝当前文件?paste buffer

map <f11> "qyy:let @q=@q."zzz"
----------------------------------------
" 帮助的帮助? (使用 TAB)
:h quickref : VIM 快速参考页
:h tips : Vim'自己的技巧帮?br /> :h visual<C-D><tab> : 虚拟模式的帮助列?br /> : 然后使用tab选择它们
:h ctrl<C-D> : 所有关于ctrl键的帮助列表
:helpg uganda : 过滤帮助文件 使用 :cn, :cp 查找下一个及后一?br /> :h :r : 关于 :ex 的命令帮?br /> :h CTRL-R : 普通模式相?br /> :h /\r : \r是什么的意?br /> :h \\zs : 使用双反斜线查找关于 \zs 的帮?br /> :h i_CTRL-R : 在插入模式中 <C-R>的解?br /> :h c_CTRL-R : 在命令模式中 <C-R> 的解?br /> :h v_CTRL-V : 虚拟模式
:h tutor : VIM 快速指?br /> <C-[>, <C-T> : Move back & Forth in HELP History
gvim -h : VIM 命令行帮?br /> ----------------------------------------
" 选项设置在那?br /> :scriptnames : 列出所有已经加载的 plugins, _vimrcs文件
:verbose set history? :显示 history的值并显示在那里定义的
:function : 列出所有函?br /> :func SearchCompl : 显示指定函数的细?br /> ----------------------------------------
" 制作你自己的VIM 帮助
:helptags /vim/vim64/doc : 重新编译所?*.txt 的帮助文件在这个目录?br /> :help add-local-help :如何添加本地帮?br /> ----------------------------------------
" 用外部程序运行文?(例如 php)
map <f9> :w<CR>:!c:/php/php.exe %<CR>
map <f2> :w<CR>:!perl -c %<CR>
----------------------------------------
" 在另一个buffer中,捕捉当前脚本的输?br /> :new | r!perl # : 新建一个buffer,从另一个buffer中读入结?br /> :new! x.out | r!perl # : 同上,并指定一个新文件?br /> :new+read!ls
----------------------------------------
" create a new buffer, paste a register "q" into it, then sort new buffer
:new +put q|%!sort
----------------------------------------
" 插入DOS换行?br /> :%s/$/\<C-V><C-M>&/g : (that's what you type
:%s/$/\<C-Q><C-M>&/g : for Win32) 对于Win32应该这样
:%s/$/\^M&/g : 你看到的^M是一个字?br /> ----------------------------------------
" 自动删除行尾 Dos回车符和空格
autocmd BufRead * silent! %s/[\r \t]\+$//
autocmd BufEnter *.php :%s/[ \t\r]\+$//e
----------------------------------------
" 对指定文件或文件类型执行某个动作
autocmd VimEnter c:/intranet/note011.txt normal! ggVGg?
autocmd FileType *.pl exec('set fileformats=unix')
----------------------------------------
" 把最后一个命令贴到当前位?br /> i<c-r>:
" 把最后一个搜索指令贴到当前位?br /> i<c-r>/
----------------------------------------
" 更多的完成功?br /> <C-X><C-F> :插入当前目录下的一个文件名到当前位?br /> # 在insert模式下使?br /> # 然后?Ctrl-P/Ctrl-N 翻页
----------------------------------------
" 替换一个visual区域
" 选择一个区域,然后输入 :s/Emacs/Vim/ 等等,vim会自动进?模式
:'<,'>s/Emacs/Vim/g : 前面? '<.'> 是vim自动添加?br /> gv : 重新选择前一个可视区?(ULTRA)
----------------------------------------
" 在文件中插入行号
:g/^/exec "s/^/".strpart(line(".")." ", 0, 4)
:%s/^/\=strpart(line(".")." ", 0, 5)
:%s/^/\=line('.'). ' '
----------------------------------------
#用VIM的方式来编号?br /> :set number : 显示行号
:map <F12> :set number!<CR> : Show linenumbers flip-flop
:%s/^/\=strpart(line('.')." ",0,&ts)
#从任意行开始编?需要perl)
:'a,'b!perl -pne 'BEGIN{$a=223} substr($_,2,0)=$a++'
#产生数字列表
#Type in number on line say 223 in an empty file
qqmnYP`n^Aq : in recording q repeat with @q
" 递增已存在数字到文件?br /> :.,$g/^\d/exe "normal! \<c-a>"
" 高级递增,参见:
//vim.sourceforge.net/tip_view.php?tip_id=150
----------------------------------------
" 高级递增 (真的很有?
" 把下面几句放?_vimrc
let g:I=0
function! INC(increment)
let g:I =g:I + a:increment
return g:I
endfunction
" 例如从mark a 到mark b 递增,从223开始,步长?
:let I=223
:'a,'bs/^/\=INC(5)/
" create a map for INC
cab viminc :let I=223 \| 'a,'bs/$/\=INC(5)/
----------------------------------------
" 生成?23-64 的数字列?br /> o23<ESC>qqYp<C-A>q40@q
----------------------------------------
" 在当前插入模式下编辑/移动 (真得很有?
<C-U> : 删除全部
<C-W> : 删除最后一个单?br /> <HOME><END> : 移动到行?行尾
<C-LEFTARROW><C-RIGHTARROW> : 向前/后移动一个单?br /> <C-X><C-E>,<C-X><C-Y> : scroll while staying put in insert
----------------------------------------
#加密(小心使用,不要忘了密?
:X : vim会提示你输入密码
:h :X
----------------------------------------
" 模式?(使文件只读等),必须在??5行内
// vim:noai:ts=2:sw=4:readonly:
" vim:ft=html: : 使用 HTML 语法高亮
:h modeline
----------------------------------------
" 建立你自己的菜单?br /> amenu Modeline.Insert\ a\ VIM\ modeline <Esc><Esc>ggOvim:ff=unix ts=4 ss=4<CR>
vim60:fdm=marker<esc>gg
----------------------------------------
" 一个保存当前光标下的狭义字到一个文件的函数
function! SaveWord()
normal yiw
exe ':!echo '.@0.' >> word.txt'
endfunction
map ,p :call SaveWord()
----------------------------------------
" 删除重复行的函数
function! Del()
if getline(".") == getline(line(".") - 1)
norm dd
endif
endfunction

:g/^/ call Del() #使用该函数的一个例?br /> ----------------------------------------
" 双字节编?(non alpha-numerics)
:digraphs : 显示编码?br /> :h dig : 帮助
i<C-K>e' : 输入 é
i<C-V>233 : 输入 é (Unix)
i<C-Q>233 : 输入 é (Win32)
ga : 查看字符的hex?br /> #删除?ascii 字符
:%s/[<C-V>128-<C-V>255]//gi : where you have to type the Control-V
:%s/[?-?]//gi : Should see a black square & a dotted y
:%s/[<C-V>128-<C-V>255<C-V>01-<C-V>31]//gi : All pesky non-asciis
:exec "norm /[\x00-\x1f\x80-\xff]/" : same thing
#Pull a non-ascii character onto search bar
yl/<C-R>" :
/[^a-zA-Z0-9_[:space:][:punct:]] : search for all non-ascii
----------------------------------------
" 文件名自动完?(例如 main_c.c)
:e main_<tab> : tab 键完?br /> gf : 打开光标处广义字命名的文?(normal模式)
main_<C-X><C-F> : 文件名自动完?insert模式)
----------------------------------------
" Vim复杂使用
" 交换两个单词
:%s/\<\(on\|off\)\>/\=strpart("offon", 3 * ("off" == submatch(0)), 3)/g
" 交换两个单词
:vnoremap <C-X> <Esc>`.``gvP``P
----------------------------------------
" 把text文件转换成html文件(oh,ft)
:runtime! syntax/2html.vim : 转换 txt ?html
:h 2html
----------------------------------------
" VIM 有一个内部自带的 grep 命令
:grep some_keyword *.c : 得到一个包含some_keyword的c文件名列?br /> :cn : 去下一个出现的位置
----------------------------------------
" 强制无扩展名的文件的语法着色方?br /> :set syntax=perl
" 取消语法着?(很有?
:set syntax off
" 改变色彩主题 (在~vim/vim??/colors中的任何文件)
:colorscheme blue
" 通过使用模式行强迫使?HTML 语法高亮
# vim:ft=html:
" 强制自动语法加亮(非标准的文件扩展)
au BufRead,BufNewFile */Content.IE?/* setfiletype html
----------------------------------------
:set noma (non modifiable) : 防止修改
:set ro (Read Only) : 只读保护
----------------------------------------
" 对话 (打开一堆文?
gvim file1.c file2.c lib/lib.h lib/lib2.h : ?对话"中加载这些文?br /> :mksession : 生成一个Session文件 (默认是Session.vim)
:q
gvim -S Session.vim : 重新加载所有文?br /> ----------------------------------------
#标记(tags) (跳转到子程序/函数)
taglist.vim : 很流行的插件
:Tlist : 显示标记 (函数列表)
<C-]> : 跳转到光标处的函?br /> ----------------------------------------
" columnise a csv file for display only as may crop wide columns
:let width = 20
:let fill=' ' | while strlen(fill) < width | let fill=fill.fill | endwhile
:%s/\([^;]*\);\=/\=strpart(submatch(1).fill, 0, width)/ge
:%s/\s\+$//ge
" Highlight a particular csv column (put in .vimrc)
function! CSVH(x)
execute 'match Keyword /^\([^,]*,\)\{'.a:x.'}\zs[^,]*/'
execute 'normal ^'.a:x.'f,'
endfunction
command! -nargs=1 Csv :call CSVH(<args>)
" call with
:Csv 5 : highlight fifth column
----------------------------------------
" 折叠:隐藏某些片断,使查看更容易
zf} : 使用动作命令折叠一个段?br /> v}zf : 使用可视模式折叠一个段?br /> zf'a : 折叠到一个标记上
zo : 打开折叠
zc : 重新关闭折叠
----------------------------------------
" 显示"不可见字?
:set list
:h listchars
----------------------------------------
" 如何在不进入插入模式的情况下粘贴"普通模式的命令"
:norm qqy$jq
----------------------------------------
" 处理文件?br /> :h filename-modifiers : 帮助
:w % : 写入当前文件
:w %:r.cfm : 改变文件扩展名为 .cfm
:!echo %:p : 显示完整路径和文件名
:!echo %:p:h : 只显示完整路?br /> :!echo %:t : 只显示文件名
:reg % : 显示文件?br /> <C-R>% : 插入文件?(插入模式)
"%p : 插入文件?(普通模?
/<C-R>% : 在文本中查找文件?br /> ----------------------------------------
" 删除,但不破?buffer 内容
"_d : 你一直想要的东西
"_dw : 例如:删除一个单?(使用黑洞???)
----------------------------------------
" 送完整的路径名到剪贴板,用于邮件附件?br /> nnoremap <F2> :let @*=expand("%:p")<cr> :unix
nnoremap <F2> :let @*=substitute(expand("%:p"), "/", "\\", "g")<cr> :win32
----------------------------------------
" 不用离开 Vim 就能修改文件名的简?shell 脚本
$ vim
:r! ls *.c
:%s/\(.*\).c/mv & \1.bla
:w !sh
:q!
----------------------------------------
" 在一个文本里计算单词?br /> g<C-G>
----------------------------------------
" 你自己设置高亮显示的例子
:syn match DoubleSpace " "
:hi def DoubleSpace guibg=#e0e0e0
----------------------------------------
" reproduce previous line word by word
imap ] @@@<ESC>hhkyWjl?@@@<CR>P/@@@<CR>3s
nmap ] i@@@<ESC>hhkyWjl?@@@<CR>P/@@@<CR>3s
" 根据文件类型映射快捷?br /> :autocmd bufenter *.tex map <F1> :!latex %<CR>
:autocmd bufenter *.tex map <F2> :!xdvi -hush %<.dvi&<CR>
----------------------------------------
" 读取 MS-Word 文,需?antiword
:autocmd BufReadPre *.doc set ro
:autocmd BufReadPre *.doc set hlsearch!
:autocmd BufReadPost *.doc %!antiword "%"
----------------------------------------
" a folding method
vim: filetype=help foldmethod=marker foldmarker=<<<,>>>
A really big section closed with a tag <<<
--- remember folds can be nested ---
Closing tag >>>
----------------------------------------
" Just Another Vim Hacker JAVH
vim -c ":%s%s*%Cyrnfr)fcbafbe[Oenz(Zbbyranne%|:%s)[[()])-)Ig|norm Vg?"
# 译释:呵呵,谁来解释一下吧?br /> # 其实不过是在启动vim的时候执行了一个命?br /> # 先写入了 Just Another Vim Hacker 的rot13编码
# 然后再解?/font>



]]>
vim 显示行号、语法高亮、自动缩进的设置 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/09/02/293574.html林光?/dc:creator>林光?/author>Wed, 02 Sep 2009 04:24:00 GMT//www.ot7t.com.cn/lingy/archive/2009/09/02/293574.html在Ubuntu中vim的配置文件存放在/etc/vim目录中,配置文件名为vimrc

在Fedora中vim的配置文件存放在/etc目录中,配置文件名为vimrc

在终?输入以下命令来编辑vimrc配置文件?br /> sudo vim /etc/vim/vimrc
或?sudo gedit /etc/vim/vimrc

1、显示行?br />   
在文件末端添加一新行,输?set nu

2、语法高?br /> 在文件中找到 "syntax on   这一行,去掉前面的双引号",双引号是注释的意?/p>

3、自动缩?/p>

在文件末尾添加一行,输入  set autoindent
在添加一行,输入         set cindent
其中 autoindent 是自动缩进; cindent是特别针?C语言语法自动缩进

注意:如果设置好以上设置后,VIM没有作出相应的动作,那么请你把你的VIM升级到最新版,一般只要在终端输入以下命令即可:sudo apt-get install vim

祝大家使用VIM愉快?/p>

 


下面告诉大家怎么在linux下学习C,C在linux下的编译器是gcc,你在终端用vim输入C的源?/p>

          如下保存到hello.c然后在命令行运行?/p>

 

          ?gcc hello.c -o hello

 

          这样会生成一个hello的可执行文件,在命令行里输入?/p>

 

          ?./hello

 

          就能运行刚刚你编译的C源码?/p>

 

            linux下同样也能编译C++,linux下C++编译器是g++,特别提示:

            C++的头文件是iostream不是iostream.h另外还需加入命名空间std,例如:

            //hello.cpp

            #include <iostream>

            using namespace std;

            int main ()

            {

                  cout<<"helloworld!"<<endl;

             }

 

            这样才能正常编译,在该目录下,终端输入:

 

            # g++ hello.cpp -o hello

          

            这样就生成一个hello的可执行文件,同?/hello命令运行?/p>

 

本文来自CSDN博客,转载请标明出处://blog.csdn.net/Dreamcode/archive/2009/05/11/4166995.aspx



]]>
Java Class Loader - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/08/30/293221.html林光?/dc:creator>林光?/author>Sun, 30 Aug 2009 12:54:00 GMT//www.ot7t.com.cn/lingy/archive/2009/08/30/293221.html程序编制一般需经编辑、编译、连接、加载和运行几个步骤。在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译?#8220;?#8221;文件;在连接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中。这种库称为静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝?/p>

为了克服这个缺点可以采用动态连接库。这个时候连接器仅仅是在可执行文件中打上标志,说明需要使用哪些动态连接库;当运行程序时,加载器根据这些标志把所需的动态连接库加载到内存?/p>

另外在当前的编程环境中,一般都提供方法让程序在运行的时候把某个特定的动态连接库加载并运行,也可以将其卸载(例如Win32的LoadLibrary()&FreeLibrary()和Posix的dlopen()&dlclose())。这个功能被广泛地用于在程序运行时刻更新某些功能模块或者是程序外观?/p>

What is ClassLoader?

与普通程序不同的是,Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVM(Java虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader?/p>

JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader,和JVM一样,Bootstrap ClassLoader是用本地代码实现的,它负责加载核心Java Class(即所有java.*开头的类)。另外JVM还会提供两个ClassLoader,它们都是用Java语言编写的,由Bootstrap ClassLoader加载;其中Extension ClassLoader负责加载扩展的Java class(例如所有javax.*开头的类和存放在JRE的ext目录下的类),Application ClassLoader负责加载应用程序自身的类?/p>

When to load the class?

什么时候JVM会使用ClassLoader加载一个类呢?当你使用java去执行一个类,JVM使用Application ClassLoader加载这个类;然后如果类A引用了类B,不管是直接引用还是用Class.forName()引用,JVM就会找到加载类A的ClassLoader,并用这个ClassLoader来加载类B?/p>

Why use your own ClassLoader?

似乎JVM自身的ClassLoader已经足够了,为什么我们还需要创建自己的ClassLoader呢?

因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,如果编写你自己的ClassLoader,你可以做到?br /> 1)在执行非置信代码之前,自动验证数字签名
2)动态地创建符合用户特定需要的定制化构建类
3)从特定的场所取得java class,例如数据库?br /> 4) 等等

事实上当使用Applet的时候,就用到了特定的ClassLoader,因为这时需要从网络上加载java class,并且要检查相关的安全信息?/p>

目前的应用服务器大都使用了ClassLoader技术,即使你不需要创建自己的ClassLoader,了解其原理也有助于更好地部署自己的应用?nbsp;

ClassLoader Tree & Delegation Model

当你决定创建你自己的ClassLoader时,需要继承java.lang.ClassLoader或者它的子类。在实例化每个ClassLoader对象时,需要指定一个父对象;如果没有指定的话,系统自动指定ClassLoader.getSystemClassLoader()为父对象。如下图?/p>

在Java 1.2后,java class的加载采用所谓的委托模式(Delegation Modle),当调用一个ClassLoader.loadClass()加载一个类的时候,将遵循以下的步骤?br /> 1)检查这个类是否已经被加载进来了?br /> 2)如果还没有加载,调用父对象加载该类
3)如果父对象无法加载,调用本对象的findClass()取得这个类?/p>

所以当创建自己的Class Loader时,只需要重载findClass()这个方法?/p>

Unloading? Reloading?

当一个java class被加载到JVM之后,它有没有可能被卸载呢?我们知道Win32有FreeLibrary()函数,Posix有dlclose()函数可以被调用来卸载指定的动态连接库,但是Java并没有提供一个UnloadClass()的方法来卸载指定的类?/p>

在Java中,java class的卸载仅仅是一种对系统的优化,有助于减少应用对内存的占用。既然是一种优化方法,那么就完全是JVM自行决定如何实现,对Java开发人员来说是完全透明的?/p>

在什么时候一个java class/interface会被卸载呢?Sun公司?a class or interface may be unloaded if and only if its class loader is unreachable. Classes loaded by the bootstrap loader may not be unloaded."

事实上我们关心的不是如何卸载类的,我们关心的是如何更新已经被加载了的类从而更新应用的功能。JSP则是一个非常典型的例子,如果一个JSP文件被更改了,应用服务器则需要把更改后的JSP重新编译,然后加载新生成的类来响应后继的请求?/p>

其实一个已经加载的类是无法被更新的,如果你试图用同一个ClassLoader再次加载同一个类,就会得到异常(java.lang.LinkageError: duplicate class definition),我们只能够重新创建一个新的ClassLoader实例来再次加载新类。至于原来已经加载的类,开发人员不必去管它,因为它可能还有实例正在被使用,只要相关的实例都被内存回收了,那么JVM就会在适当的时候把不会再使用的类卸载?/p>

]]>
TOMCAT源码总结一 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/08/30/293216.html林光?/dc:creator>林光?/author>Sun, 30 Aug 2009 12:05:00 GMT//www.ot7t.com.cn/lingy/archive/2009/08/30/293216.html首先不得不说这个类org.apache.tomcat.util.net.JIoEndpoint,它负责所有的TCP请求连接,实现了一个服务器模式,启用一个后台监听线程,负责接收到来的socket,然后从线程池中取出响应的worker,扔给worker进行处理,自己继续监听。其次worker是一个负责处理socket的一个线程,就是它带着用户的请求开始进入Tomcat世界的,默认的worker总共?00个,即:最?00个线程。当处理完一个请求的时候,这个线程并不会销毁,而是进入wait阻塞,这个线程的对象也不会销毁,是进入了一个栈里面,对应workstack那个数据结构。每当接收线程拿到一个socket的时候,就先从栈里面拿出一个已有的线程对象,然后就利用该对象的assign方法,将这个socket给它,并调用notify重新唤醒这个worker的处理线程。以后我们做小型服务器的时候,可以借鉴它的实现方式。正在研究多线程的朋友,这个类绝对让你可以学的透彻?/p>

相对应的还有一个org.apache.tomcat.util.net.NioEndpoint,这个和前面那个功能差不多,但是用了NIO包里的API,有一个最大的区别就是,接收线程接收一个socket之后,可能会将这个socket先放入缓存池,然后worker从池里面拿socket去处理,比前面那个类看起来功能和性能都会提升很多,不过代码行?K多,相当复杂,设计不够精巧,有兴趣可以去研究下?/p>

org.apache.tomcat.util.buf.MessageBytes:这是一个接近底层的字符串处理类,为什么说是接近底层,是因为socket接收进来的都是字节类型,而java用的是char或者String,这之间的转换涉及到编码问题和性能问题,所以凡是socket收进来的信息,全部都用这个类表示,只有当要输出字符串的时候,才会将里面的字节进行转换,实现一种延迟加载的懒模式,被Tomcat底层所使用的Request类,就是大量使用了这个类来存放数据。我们来小小窥视一下,Request类:

  1. private MessageBytes methodMB = MessageBytes.newInstance();
  2.     private MessageBytes unparsedURIMB = MessageBytes.newInstance();
  3.     private MessageBytes uriMB = MessageBytes.newInstance();
  4.     private MessageBytes decodedUriMB = MessageBytes.newInstance();
  5.     private MessageBytes queryMB = MessageBytes.newInstance();
  6.     private MessageBytes protoMB = MessageBytes.newInstance();
  7.  
  8.     // remote address/host
  9.     private MessageBytes remoteAddrMB = MessageBytes.newInstance();
  10.     private MessageBytes localNameMB = MessageBytes.newInstance();
  11.     private MessageBytes remoteHostMB = MessageBytes.newInstance();
  12.     private MessageBytes localAddrMB = MessageBytes.newInstance();
  13.     
  14.     private MimeHeaders headers = new MimeHeaders();

或许大家会觉得,构造出这么多的类,性能会高到哪里去,其实不是这样的,不停的构造和销毁对象的确会损耗相当的性能,但是一个对象被构造出来,可以重复利用,那就相当完美了,这个类就是如此的设计,其中有一个回收资源的方法,叫recycle(),这个方法可以清空里面的数组,清空里面的对象,而不会销毁自己本身,因为使用它的对象,只要调用recycle,以后又可以重复使用了?/p>

MessageBytes其实内置?个重要的类,org.apache.tomcat.util.buf.ByteChunk和org.apache.tomcat.util.buf.CharChunk,这2个类带我们回到了C时代,为什么这么说?因为它简直就是一个字符串处理类,一些眼熟的算法全部映入眼帘,比如字符转匹配算法,indexOf,startsWith,判断字符转是否相等,查找字符,等等,比之JDK提供的性能更好,功能更强大(这句话说过了,呵呵?/p>

还有一个实用的值得学习的数据结构是,org.apache.tomcat.util.buf.Ascii,如果知道表驱动的朋友们,一定对这个类很熟悉了,判断大小写?判断是不是英文单词?判断是不是空白符?判断是不是数字,将字节类型转换为int、long类型,大小写转换,等等。这些都是大学计算机课程的课后练习题



]]>
如何处理HTTP POST/GET请求 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/08/29/293078.html林光?/dc:creator>林光?/author>Sat, 29 Aug 2009 03:56:00 GMT//www.ot7t.com.cn/lingy/archive/2009/08/29/293078.html
    [全屏查看全文]
Servlet通过下面的方法来提供服务?
  • 实现service方法?br />
  • 实现HttpServlet的doMethod方法(doGet、doDelete、doOptions?doPost、doPut、doTrace)?/li>
    通常,service方法用来从客户请求(request)中提取信息,访问扩展资源,并基于上面的信息提供响应(response)?

    对于HTTP Servlets,正确提供响应的过程是首先填写响应(response)的头信息,然后从响应(response)中得到输出流,最后向输出流中写入内容信息。响应(response)头信息必须最先设置。下面将描述如何从请求(request)中获得信息和产生HTTP响应(response)?

    
  • 取得客户端请?
        一个HttpServletRequest对象提供到达HTTP 头部数据,也允许你获取客户端的数据。怎样获取这些数据取决于HTTP端请求方法。不管用任何HTTP方式,你都可以用 getParameterValues方法返回特定名称的参数值。对于用 HTTP GET 请求的方式,这个getQueryString方法将会返回一个可以用来分析的值?

        客户端请求(request)包含了从客户端传递到Servlet的数据。所有的请求(request)都实现了ServletRequest接口。这个接口定义了一些方法访问下面的信息,如?4-1所示?

    ?4-1  ServletRequest接口方法
                ????                         ????
                参数,用来在客户端和Servlet之间传送信?getAttribute(String name)
                getAttributeNames()
                getInputStream()
                getParameter(String name)
                getParameterMap()
                getParameterNames()
                getParameterValues(String name)
                对象值属性,用来在Servlet容器和Servlet
                之间,或者协作的Servlet之间传递信?    removeAttribute(String name)
                setAttribute(String name, Object o)
                有关请求使用的协议信息,
                客户端和服务器在请求中的调用	   getContentLength()
                getContentType()
                getProtocol()
                getReader()
                getRealPath(String path)
                getRemoteAddr()
                getRemoteHost()
                getRequestDispatcher(String path)
                有关请求使用的协议信息,
                客户端和服务器在请求中的调用       getScheme()
                getServerName()
                getServerPort()
                isSecure()
                有关localization的信?       getCharacterEncoding()
                getLocale()
                getLocales()
                setCharacterEncoding(String env)


        下面的代码段示范了如何使用request中的方法获得客户端信息?

    Enumeration params = request.getParameterNames();
                String paramName = null;
                String[] paramValues = null;
                while (params.hasMoreElements()) {
                paramName = (String) params.nextElement();
                paramValues = request.getParameterValues(paramName);
                System.out.println("\nParameter name is " + paramName);
                for (int i = 0; i < paramValues.length; i++) {
                System.out.println(", value " + i + " is " + paramValues[i].toString());
                }
                }


        HTTP Servlets使用HTTP request对象(HttpServletRequest),它包含了request URL、HTTP头信息、查询字符串,等等。HTTP request URL 包括几个部分?br />     //: ?

        一般情况下?

    requestURI = contextPath + servletPath + pathInfo
                Context path:通过getContextPath方法获得?
                Servlet Path:通过getServletPath方法获得?
                PathInfo:通过getPathInfo方法获得?/ccid_code>


        如表14-2所示?

    ?4-2  路径的对?
                Request Path	            Path Elements
                /catalog/help/feedback.jsp	ContextPath: /catalog ServletPath:
                /help/feedback.jsp PathInfo: null


        
  • 提供HTTP响应
        响应(response)包含了在服务器和客户端之间传递的数据。所有的响应(response)都实现了ServletResponse接口。这个接口定义了一些方法提供给开发人员使用,如表14-3所示?

    ?4-3  ServletResponse接口方法
                ????                          ????
                获得向客户端发送数据的输出? 发送字符流:getWriter()
                发送字节流:getOutputStream()
                指示响应返回的内容类型(例如:text/html?
                已经注册的内容类型名称保存在IANA
                (Internet Assigned Numbers Authority?setContentType(java.lang.String type)
                指出是否是缓冲输出。默认情况下写入输出?
                内容被立即发送到客户端。使用缓冲后写入输出的内容先
                不发送到客户端,这样Servlet有更多的时间设置相应?
                状态码和头信息,或者转移到其他的Web资源	 flushBuffer()
                getBufferSize()
                isCommitted()
                reset()
                resetBuffer()
                setBufferSize(int size)
                setContentLength(int len)
                设置localization信息	            getCharacterEncoding()
                getLocale()
                setLocale(java.util.Locale loc)


        HTTP response类(HttpServletResponse)有一些代表HTTP头信息的域:
        
  • 状态码用来指出响应(response)失败的原因?


        
  • Cookies在客户端存储应用相关的信息,有时cookies用来维护和标识用户的session?

        Servlet首先设置响应(response)头信息,包括响应(response)的内容类别和缓冲区大小,然后在doGet方法中从响应(response)获得PrintWriter ,最后向输出中写入HTML代码,调用close()方法提交这次对客户端的响应(response)。示范代码如下:

    public void doGet (HttpServletRequest request,
                HttpServletResponse response)
                throws ServletException, IOException
                {
                // 设置头信?
                response.setContentType("text/html");
                response.setBufferSize(8192);
                PrintWriter out = response.getWriter();
                // 向response中输?
                out.println("<html>" +
                "<head><title>+
                messages.getString("TitleBookDescription")
                +</title></head>");
                ...
                out.println("</body></html>");
                // 关闭输出?
                out.close();
                }


  • 林光?/a> 2009-08-29 11:56 发表评论
    ]]>
    TOMCAT源码分析(消息处理) - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/08/26/292716.html林光?/dc:creator>林光?/author>Wed, 26 Aug 2009 12:53:00 GMT//www.ot7t.com.cn/lingy/archive/2009/08/26/292716.html我们知道了tomcat的整体框架了?也明白了里面都有些什么组件, 以及各个组件是干什么用的了?/span>

    //www.csdn.net/Develop/read_article.asp?id=27225

    我想,接下来我们应该去了解一?tomcat 是如何处理jsp和servlet请求的?/span>

    1.  我们以一个具体的例子,来跟踪TOMCAT?/span>看看它是如何?/span>Request一层一层地递交给下一个容器,并最后交?/span>Wrapper来处理的?/span>

    ?/span>//localhost:8080/web/login.jsp为例?/span>

    (以下例子,都是?/span>tomcat4 源码为参考)

    这篇心得主要分为3个部分: 前期?中期?和末期?/span>

     前期:讲解了在浏览器里面输入一个URL,是怎么被tomcat抓住的?/span>

    中期:讲解了被tomcat抓住后,又是怎么在各个容器里面穿梭, 最后到达最后的处理地点?/span>

    末期:讲解到达最后的处理地点后,又是怎么具体处理的?/span>

    2?/span> 前期 Request的born.

        在这里我先简单讲一下request这个东西?/span>

         我们先看着这个URL?/span>//localhost:8080/web/login.jsp 它是动用?080端口来进行socket通讯的?/span>

         我们知道, 通过

           InputStream in = socket.getInputStream() ?/span>

           OutputStream out = socket.getOutputStream()

         就可以实现消息的来来往往了?/span>

         但是如果把Stream给应用层看,显然操作起来不方便?

         所以,在tomcat 的Connector里面?socket被封装成了Request和Response这两个对象?/span>

         我们可以简单地把Request看成管发到服务器来的数据,把Response看成想发出服务器的数据?/span>

         

         但是这样又有其他问题了啊?Request这个对象是把socket封装起来了, 但是他提供的又东西太多了?/span>

         诸如Request.getAuthorization(), Request.getSocket()?nbsp;像Authorization这种东西开发人员拿来基本上用不太着,而像socket这种东西,暴露给开发人员又有潜在的危险?而且啊, 在Servlet Specification里面标准的通信类是ServletRequest和HttpServletRequest,而非这个Request类?So, So, So. Tomcat必须得捣持捣持Request才行?最后tomcat选择了使用捣持模式(应该叫适配器模式)来解决这个问题。它把org.apache.catalina.Request 捣持成了 org.apache.coyote.tomcat4.CoyoteRequest?而CoyoteRequest又实现了ServletRequest和HttpServletRequest 这两种接口?这样就提供给开发人员需要且刚刚需要的方法了?/span>

     

        ok, ?/span>我们?tomcat的顶层容?- StandardEngin 的invoke()方法这里设置一个断点, 然后访问

        //localhost:8080/web/login.jsp?我们来看看在前期都会路过哪些地方?/span>

           1. run(): 536, java.lang.Thread, Thread.java

           CurrentThread

          2. run():666, org.apache.tomcat.util.threads.ThreadPool$ControlRunnable, ThreadPool.java

                   ThreadPool

           3. runIt():589, org.apache.tomcat.util.net.TcpWorkerThread, PoolTcpEndpoint.java

             ThreadWorker

    4.        processConnection():  549

    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler, Http11Protocol.java

                      http protocol parser

          5. Process(): 781, org.apache.coyote.http11.Http11Processor, Http11Processor.java

              http request processor

           6. service(): 193, org.apache.coyote.tomcat4.CoyoteAdapter,CoyoteAdapter.java

             adapter

           7. invoke(): 995, org.apache.catalina.core.ContainerBase, ContainerBase.java

       StandardEngin

        1. 主线?/span>

        2. 启动线程?

        3. 调出线程池里面空闲的工作线程?/span>

        4. ?080端口传过来由httpd协议封装的数据,解析成Request和Response对象?/span>

        5. 使用Http11Processor来处理request

        6. ?/span>Http11Processor里面?又会call CoyoteAdapter来进行适配处理,把Request适配成实现了ServletRequest和HttpServletRequest接口?/span>CoyoteRequest.

    7. 到了这里,前期的去毛拔皮工作就基本上搞定,可以交?/span>StandardEngin 做核心的处理工作了?/span>

    3. 中期?在各个容器间的穿梭?/span>

        Request在各个容器里面的穿梭大致是这样一种方式:

        每个容器里面都有一个管道(pipline), 专门用来传送Request用的?/span>

        管道里面又有好几个阀门(valve), 专门用来过滤Request用的?/span>

        在管道的低部通常都会放上一个默认的阀们?这个阀们至少会做一件事情,就是把Request交给子容器?/span>

        让我们来想象一下:

         当一个Request进入一个容器后?它就在管道里面流动,波罗~ 波罗~ 波罗~ 地穿过各个阀门。在流到最后一个阀门的时候,吧唧~ 那个该死的阀门就把它扔给了子容器?然后又开?波罗~ 波罗~ 波罗~ ... 吧唧~.... 波罗~ 波罗~ 波罗~ ....吧唧~....

        就是通过这种方式?Request 走完了所有的容器。( 感觉有点像消化系统,最后一个地方有点像那里~ ?/span>

        OK?让我们具体看看都有些什么容器, 各个容器里面又都有些什么阀门,这些阀们都对我们的Request做了些什么吧?/span>

    3.1 StandardEngin 的pipeline里面放的是:StandardEnginValve

    在这里,VALVE做了三件事:

    1.   验证传递过来的request是不?/span>httpservletRequest.

    2    验证传递过来的 request 是否携带?/span>host header信息.

    3    选择相应?/span>host去处理它。(一般我们都只有一个host:localhost,也就是127.0.0.1)?/span>

    到了这个地方?/span>我们?/span>request就已经完成了?/span>Engin这个部分的历史使命,通向前途未卜的下一站: host了?/span>

    3.2 StandardHost 的pipline里面放的是: StandardHostValve

    1.   验证传递过来的request是不?/span>httpservletRequest.

    2.   根据Request来确定哪?/span>Context来处理?/span>

    Context其实就是webapp?/span>比如//localhost:8080/web/login.jsp

    这里web就是Context罗!

    3.   既然确定了是哪个Context了,那么就应该把那个Context?/span>classloader付给当前线程了?/span>

            Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());

       这样request就只看得见指定的context下面?/span>classes啊, jar啊这些,而看不见tomcat本身的类?/span>什?/span>Engin啊, Valve啊?/span>不然还得了啊?/span>

    4. 既然request到了这里了,看来用户是准备访问web这个web app了,咋们得更新一下这个用户的session不是?Ok , 就由manager更新一下用户的session信息

    5. 交给具体的Context 容器去继续处理Request.

    6. Context处理完毕了,?/span>classloader还回来?/span>

    3.3 StandardContext 的pipline里面放的是: StandardContextValve

    1.   验证传递过来的request是不?/span>httpservletRequest.

    2.   如果request意图不轨,想要访?/span>/meta-inf, /web-inf这些目录下的东西,呵呵,没有用D!

    3.   这个时候就会根?/span>Request到底?/span>Servlet?/span>还是jsp?/span>还是静态资源来决定到底用哪?/span>Wrapper来处理这?/span>Reqeust了?/span>

    4.   一旦决定了到底用哪?/span>Wrapper?/span>OK,交给那?/span>Wrapper处理?/span>

    4. 末期?不同的需求是怎么处理?

    StandardWrapper

    之前对Wrapper没有做过讲解,其实它是这样一种东西?/span>

    我们在处理Request的时候,可以分成3种?/span>

    处理静态的?org.apache.catalina.servlets.DefaultServlet  

    处理jsp的:org.apache.jasper.servlet.JspServlet

    处理servlet的:org.apache.catalina.servlets.InvokerServlet

    不同的request就用?种不同的servlet去处理?/span>

    Wrapper就是对它们的一种简单的封装,有了Wrapper后,我们就可以轻松地拦截每次的Request。也可以容易地调用servlet的init()和destroy()方法?便于管理嘛!

    具体情况是这么滴?/span>

       如果request是找jsp文件,StandardWrapper里面就会封装一个org.apache.jasper.servlet.JspServlet去处理它?/span>

       如果request是找 静态资?,StandardWrapper里面就会封装一个org.apache.jasper.servlet.DefaultServlet 去处理它?/span>

       如果request是找servlet ,StandardWrapper里面就会封装一个org.apache.jasper.servlet.InvokerServlet 去处理它?/span>

    StandardWrapper同样也是容器,既然是容器?那么里面一定留了一个管道给request去穿,管道低部肯定也有一个阀??),用来做最后一道拦截工?

    在这最底部的阀门里,其实就主要做了两件?

       一是启动过滤器,让request在N个过滤器里面筛一通,如果OK?那就PASS?否则就跳到其他地方去了?/span>

       二是servlet.service((HttpServletRequest) request,(HttpServletResponse) response); 这个方法.

         如果?JspServlet?那么先把jsp文件编译成servlet_xxx, 再invoke servlet_xxx的servie()方法?/span>

         如果?DefaultServlet?就直接找到静态资源,取出内容?发送出去?/span>

         如果?InvokerServlet?就调用那个具体的servlet的service()方法?/span>

       ok! 完毕?/span>

    ?: StandardWrapper 里面的阀门是最后一道关口了?如果这个阀门欲意把request交给StandardWrapper 的子容器处理?对不起, 在设计考虑的时候, Wrapper就被考虑成最末的一个容器, 压根儿就不会给Wrapper添加子容器的机会?如果硬是要调用addChild(), 立马抛出IllegalArgumentException?/span>

    参考:

         <//jakarta.apache.org/tomcat/>
       <
    //www.onjava.com/pub/a/onjava/2003/05/14/java_webserver.html>

     


    作者Blog?/strong>//blog.csdn.net/ThomasHuang/
    相关文章


    ]]>
    TOMCAT源码分析(启动框架 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/08/26/292715.html林光?/dc:creator>林光?/author>Wed, 26 Aug 2009 12:49:00 GMT//www.ot7t.com.cn/lingy/archive/2009/08/26/292715.html
    TOMCAT源码分析(启动框架)     选择?ThomasHuang ?Blog
    关键?/font>   tomcat 源代?源码 source code architecture
    出处  

    TOMCAT源码分析(启动框架)
    前言?br />    本文是我阅读了TOMCAT源码后的一些心得?主要是讲解TOMCAT的系统框架, 以及启动流程。若有错漏之处,敬请批评指教?br /> 建议?br />    毕竟TOMCAT的框架还是比较复杂的?单是从文字上理解?是不那么容易掌握TOMCAT的框架的?所以得实践、实践、再实践?建议下载一份TOMCAT的源码, 调试通过?然后单步跟踪其启动过程?如果有不明白的地方, 再来查阅本文?看是否能得到帮助?我相信这样效果以及学习速度都会好很多!
      
    1. Tomcat的整体框架结?br />    Tomcat的基本框架, 分为4个层次?br />    Top Level Elements:
        Server
        Service  
       Connector
        HTTP
        AJP
       Container
       Engine
         Host
       Context
       Component 
        manager
       logger
       loader
       pipeline
       valve
             ...
       站在框架的顶层的是Server和Service
       Server:  其实就是BackGroud程序?在Tomcat里面的Server的用处是启动和监听服务端事件(诸如重启、关闭等命令?在tomcat的标准配置文件:server.xml里面?我们可以看到“<Server port="8005" shutdown="SHUTDOWN" debug="0">”这里?SHUTDOWN"就是server在监听服务端事件的时候所使用的命令字?br />    Service?在tomcat里面?service是指一类问题的解决方案?nbsp; 通常我们会默认使用tomcat提供的:Tomcat-Standalone 模式的service?在这种方式下的service既给我们提供解析jsp和servlet的服务, 同时也提供给我们解析静态文本的服务?br />   
       Connector: Tomcat都是在容器里面处理问题的?而容器又到哪里去取得输入信息呢?
    Connector就是专干这个的?他会把从socket传递过来的数据?封装成Request, 传递给容器来处理?br />    通常我们会用到两种Connector,一种叫http connectoer?用来传递http需求的?另一种叫AJP?在我们整合apache与tomcat工作的时候, apache与tomcat之间就是通过这个协议来互动的?(说到apache与tomcat的整合工作, 通常我们的目的是为了让apache 获取静态资源, 而让tomcat来解析动态的jsp或者servlet。)
       Container: 当http connector把需求传递给顶级的container: Engin的时候, 我们的视线就应该移动到Container这个层面来了?br />    在Container这个层, 我们包含?种容器: Engin, Host, Context.
       Engin: 收到service传递过来的需求, 处理后, 将结果返回给service( service 是通过 connector 这个媒介来和Engin互动?).
       Host: Engin收到service传递过来的需求后,不会自己处理, 而是交给合适的Host来处理?br /> Host在这里就是虚拟主机的意思, 通常我们都只会使用一个主机,?#8220;localhost”本地机来处理?
       Context: Host接到了从Host传过来的需求后?也不会自己处理, 而是交给合适的Context来处理?
       比如?<//127.0.0.1:8080/foo/index.jsp>
             <//127.0.1:8080/bar/index.jsp>
       前者交给foo这个Context来处理, 后者交给bar这个Context来处理?br />    很明显吧?context的意思其实就是一个web app的意思?br />    我们通常都会在server.xml里面做这样的配置
       <Context path="/foo" docBase="D:/project/foo/web" />
       这个context容器,就是用来干我们该干的事儿的地方的?br />   
       Compenent: 接下来, 我们继续讲讲component是干什么用的?br />    我们得先理解一下容器和组件的关系?br />    需求被传递到了容器里面, 在合适的时候, 会传递给下一个容器处理?br />    而容器里面又盛装着各种各样的组件, 我们可以理解为提供各种各样的增值服务?br />    manager: 当一个容器里面装了manager组件后,这个容器就支持session管理了, 事实上在tomcat里面的session管理?就是靠的在context里面装的manager component.
       logger: 当一个容器里面装了logger组件后, 这个容器里所发生的事情, 就被该组件记录下来啦?我们通常会在logs/ 这个目录下看?catalina_log.time.txt 以及 localhost.time.txt 和localhost_examples_log.time.txt?这就是因为我们分别为:engin, host以及context(examples)这三个容器安装了logger组件?这也是默认安装, 又叫做标?:)
       loader: loader这个组件通常只会给我们的context容器使用?loader是用来启动context以及管理这个context的classloader用的?br />     pipline: pipeline是这样一个东西, 当一个容器决定了要把从上级传递过来的需求交给子容器的时候, 他就把这个需求放进容器的管道(pipeline)里面去?而需求傻呼呼得在管道里面流动的时候, 就会被管道里面的各个阀门拦截下来?比如管道里面放了两个阀门?第一个阀门叫?#8220;access_allow_vavle”?也就是说需求流过来的时候,它会看这个需求是哪个IP过来的, 如果这个IP已经在黑名单里面了, sure, 杀?第二个阀门叫?#8220;defaul_access_valve”它会做例行的检查, 如果通过的话,OK?把需求传递给当前容器的子容器?就是通过这种方式?需求就在各个容器里面传递,流动?最后抵达目的地的了?br />     valve: 就是上面所说的阀门啦?br />    Tomcat里面大概就是这么些东西, 我们可以简单地这么理解tomcat的框架,它是一种自上而下?容器里又包含子容器的这样一种结构?br /> 2. Tomcat的启动流?br />    这篇文章是讲tomcat怎么启动的,既然我们大体上了解了TOMCAT的框架结构了?那么我们可以望文生意地就猜到tomcat的启动, 会先启动父容器,然后逐个启动里面的子容器?启动每一个容器的时候, 都会启动安插在他身上的组件?当所有的组件启动完毕?所有的容器启动完毕的时候, tomcat本身也就启动完毕了?br />    顺理成章地, 我们同样可以猜到?tomcat的启动会分成两大部分?第一步是装配工作?第二步是启动工作?
       装配工作就是为父容器装上子容器, 为各个容器安插进组件的工作?这个地方我们会用到digester模式?至于digester模式什么, 有什么用?怎么工作? 请参?<//software.ccidnet.com/pub/article/c322_a31671_p2.html>
       启动工作是在装配工作之后?一旦装配成功了?我们就只需要点燃最上面的一根导线, 整个tomcat就会被激活起来?这就好比我们要开一辆已经装配好了的汽车的时候一样,我们只要把钥匙插进钥匙孔,一拧,汽车的引擎就会发动起来,空调就会开起来?安全装置就会生效?如此一来,汽车整个就发动起来了。(这个过程确实和TOMCAT的启动过程不谋而和?让我们不得不怀?TOMCAT的设计者是在GE做JAVA开发的)?br /> 2.1 一些有意思的名称?br />    Catalina
       Tomcat
       Bootstrap
       Engin
       Host
       Context
       他们的意思很有意思:
       Catalina: 远程轰炸?br />    Tomcat: 熊猫轰炸?-- 轰炸机的一种(这让我想起了让国人引以为豪的熊猫手机,是不是英文可以叫做tomcat??? ?又让我想起了另一则广告: 波导-手机中的战斗机、波?客机中的战斗??br />    Bootstap: 引导
       Engin: 发动?br />    Host: 主机,领?br />    Context: 内容?目标?上下?br />   
       ... 在许多许多年后, 现代人类已经灭绝?后现代生物发现了这些单词零落零落在一块?一个自以为聪明的家伙把这些东西翻译出来了:
       在地勤人员的引导(bootstrap)下, 一架轰炸架(catalina)腾空跃起?远看是熊猫轰炸机(tomcat)?近看还是熊猫轰炸机! 凭借着优秀的发动机技?engin)?这架熊猫轰炸机飞临了敌国的领土上?host)?对准目标(context)投下了毁天灭地的核弹头,波~ 现代生物就这么隔屁了~
     
       综上所述, 这又不得不让人联想到GE是不是也参与了军事设备的生产呢?
       反对美帝国主义! 反对美霸权主义! 和平万岁?自由万岁?br />   
    2.2  历史就是那么惊人的相似! tomcat的启动就是从org.apache.catalina.startup.Bootstrap这个类悍然启动的?br />    在Bootstrap里做了两件事?br />    1. 指定?种类型classloader:
          commonLoader: common/classes、common/lib、common/endorsed
          catalinaLoader: server/classes、server/lib、commonLoader
          sharedLoader?nbsp; shared/classes、shared/lib、commonLoader
       2. 引导Catalina的启动?br />       用Reflection技术调用org.apache.catalina.startup.Catalina的process方法?并传递参数过去?br />   
    2.3 Catalina.java
       Catalina完成了几个重要的任务?br />    1. 使用Digester技术装配tomcat各个容器与组件?br />       1.1 装配工作的主要内容是安装各个大件?比如server下有什么样的servcie?Host会容纳多少个context?Context都会使用到哪些组件等等?
          1.2 同时呢, 在装配工作这一步, 还完成了mbeans的配置工作?在这里,我简单地但不十分精确地描述一下mbean是什么,干什么用的?br />           我们自己生成的对象, 自己管理?天经地义?但是如果我们创建了对象了?想让别人来管?怎么办呢?我想至少得告诉别人我们都有什么, 以及通过什么方法可以找?nbsp; 吧! JMX技术给我们提供了一种手段?JMX里面主要?种东西。Mbean, agent, connector.
           Mbean?用来映射我们的对象。也许mbean就是我们创建的对象, 也许不是?但有了它?就可以引用到我们的对象了?br />        Agent:  通过它, 就可以找到mbean了?br />        Connector: 连接Agent的方式?可以是http的, 也可以是rmi的,还可以直接通过socket?br />       发生在tomcat 装配过程中的事情:  GlobalResourcesLifecycleListener 类的初始化会被触发:
             protected static Registry registry = MBeanUtils.createRegistry();  会运?br />          MBeanUtils.createRegistry()  会依?org/apache/catalina/mbeans/mbeans-descriptors.xml这个配置文件创建 mbeans. Ok, 外界就有了条途径访问tomcat中的各个组件了。(有点像后门儿?br />    2. 为top level 的server 做初始化工作?实际上就是做通常会配置给service的两条connector.(http, ajp)
       3. 从server这个容器开始启动, 点燃整个tomcat.
       4. 为server做一个hook程序?检测当server shutdown的时候, 关闭tomcat的各个容器用?br />    5. 监听8005端口?如果发?SHUTDOWN"(默认培植下字符串)过来?关闭8005serverSocket?br /> 2.4 启动各个容器
       1. Server
          触发Server容器启动?before_start)?启动?start)?启动?after_start)3个事件, 并运行相应的事件处理器?br />       启动Server的子容器:Servcie.
       2. Service
          启动Service的子容器:Engin
          启动Connector
       3. Engin
          到了Engin这个层次,以及以下级别的容器?Tomcat就使用了比较一致的启动方式了?br />       首先?nbsp; 运行各个容器自己特有一些任?br />       随后?nbsp; 触发启动前事?br />       立即?nbsp; 设置标签,就表示该容器已经启?br />       接着?nbsp; 启动容器中的各个组件?loader, logger, manager等等
          再接着,启动mapping组件。(??br />       紧跟着,启动子容器?br />       接下来,启动该容器的管道(pipline)
          然后?nbsp; 触发启动中事?br />       最后,  触发启动后事件?br />  
          Engin大致会这么做?Host大致也会这么做, Context大致还是会这么做?那么很显然地?我们需要在这里使用到代码复用的技术?tomcat在处理这个问题的时候, 漂亮地使用了抽象类来处理?ContainerBase. 最后使得这部分完成复杂功能的代码显得干净利落?干练爽快?实在是令人觉得叹为观止, 细细品来?直觉如享佳珍?另人齿颊留香?留恋往返啊?br />      
          Engin的触发启动前事件里, 会激活绑定在Engin上的唯一一个Listener:EnginConfig?br />       这个EnginConfig类基本上没有做什么事情, 就是把EnginConfig的调试级别设置为和Engin相当?另外就是输出几行文本?表示Engin已经配置完毕?并没有做什么实质性的工作?br />       ?: mapping组件的用处是?当一个需求将要从父容器传递到子容器的时候, 而父容器又有多个子容器的话, 那么应该选择哪个子容器来处理需求呢?这个由mapping 组件来定夺?br />    
       4. Host
           同Engin一样, 也是调用ContainerBase里面的start()方法?不过之前做了些自个儿的任?就是往Host这个容器的通道(pipline)里面, 安装了一个叫?br />  “org.apache.catalina.valves.ErrorReportValve”的阀门?br />        这个阀门的用处是这样的?nbsp; 需求在被Engin传递给Host后, 会继续传递给Context做具体的处理?这里需求其实就是作为参数传递的Request, Response?所以在context把需求处理完后, 通常会改动response?而这个org.apache.catalina.valves.ErrorReportValve的作用就是检察response是否包含错误?如果有就做相应的处理?br />    5. Context
           到了这里?就终于轮到了tomcat启动中真正的重头戏,启动Context了?br />  StandardContext.start() 这个启动Context容器的方法被StandardHost调用.
     5.1 webappResources 该context所指向的具体目?br />  5.2 安装defaultContex, DefaultContext 就是默认Context?如果我们在一个Host下面安装了DefaultContext,而且defaultContext里面又安装了一个数据库连接池资源的话?那么其他所有的在该Host下的Context, 都可以直接使用这个数据库连接池, 而不用格外做配置了?br />   5.3 指定Loader. 通常用默认的org.apache.catalina.loader.WebappLoader这个类?nbsp;  Loader就是用来指定这个context会用到哪些类啊, 哪些jar包啊这些什么的?br />  5.4 指定 Manager. 通常使用默认的org.apache.catalina.session. StandardManager ?Manager是用来管理session的?br />      其实session的管理也很好实现?以一种简单的session管理为例?当需求传递过来的时候, 在Request对象里面有一个sessionId 属性?OK?得到这个sessionId后, 我们就可以把它作为map的key,而value我们可以放置一个HashMap. HashMap里边儿, 再放我们想放的东西?br />  5.5 postWorkDirectory (). Tomcat下面有一个work目录?我们把临时文件都扔在那儿去?这个步骤就是在那里创建一个目录?一般说来会?CATALINA_HOME%/work/Standalone\localhost\ 这个地方生成一个目录?br /> 5.6  Binding thread。到了这里, 就应该发?class Loader 互换了?之前是看得见tomcat下面所有的class和lib. 接下来需要看得见当前context下的class?所以要设置contextClassLoader, 同时还要把旧的ClassLoader记录下来,因为以后还要用的?br /> 5.7  启动 Loader. 指定这个Context具体要使用哪些classes?用到哪些jar文件?如果reloadable设置成了true, 就会启动一个线程来监视classes的变化, 如果有变化就重新启动Context?br /> 5.8  启动logger
    5.9  触发安装在它身上的一个监听器?br />  lifecycle.fireLifecycleEvent(START_EVENT, null);
     作为监听器之一,ContextConfig会被启动. ContextConfig就是用来配置web.xml的?比如这个Context有多少Servlet?又有多少Filter?就是在这里给Context装上去的?br />  5.9.1 defaultConfig. 每个context都得配置 tomcat/conf/web.xml 这个文件?br />  5.9.2 applicationConfig 配置自己?WEB-INF/web.xml 文件
    5.9.3 validateSecurityRoles 权限验证?通常我们在访?admin 或?manager的时候,需要用户要么是admin的要么是manager的, 才能访问?而且我们还可以限制那些资源可以访问, 而哪些不能?都是在这里实现的?br /> 5.9.4 tldScan: 扫描一下, 需要用到哪些标?tag lab)
    5.10 启动 manager
    5.11 postWelcomeFiles() 我们通常会用到的3个启动文件的名称?br /> index.html、index.htm、index.jsp 就被默认地绑在了这个context?br />  5.12 listenerStart 配置listener
     5.13 filterStart 配置 filter
     5.14 启动带有<load-on-startup>1</load-on-startup>的Servlet.
      顺序是从小到大: 1,2,3… 最后是0
      默认情况下, 至少会启动如?个的Servlet:
      org.apache.catalina.servlets.DefaultServlet  
          处理静态资源的Servlet. 什么图片啊?html啊, css啊, js啊都找他
      org.apache.catalina.servlets.InvokerServlet
          处理没有做Servlet Mapping的那些Servlet.
      org.apache.jasper.servlet.JspServlet
          处理JSP文件?
           5.15  标识context已经启动完毕?br />  走了多少个步骤啊?Context总算是启动完毕喽?br />     OK! 走到了这里, 每个容器以及组件都启动完毕?Tomcat终于不辞辛劳地为人民服务了!
    3. 参考文献:
        <//jakarta.apache.org/tomcat/>
        <//www.onjava.com/pub/a/onjava/2003/05/14/java_webserver.html>
       
    4. 后记
        这篇文章是讲解tomcat启动框架的,还有篇文章是讲解TOMCAT里面的消息处理流程的细节的?文章内容已经写好了, 现在正在整理阶段?相信很快就可以做出来?大家共同研究共同进步?br />     这篇文章是独自分析TOMCAT源码所写的?所以一定有地方是带有个人主观色彩, 难免会有片面之处。若有不当之处敬请批评指教,这样不仅可以使刚开始研究TOMCAT的兄弟们少走弯路?我也可以学到东西?br />     email: sojan_java@yahoo.com.cn

    5. tomcat源码分析(消息处理)



    ]]>
    用Digester简化XML文处理 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/08/26/292713.html林光?/dc:creator>林光?/author>Wed, 26 Aug 2009 12:27:00 GMT//www.ot7t.com.cn/lingy/archive/2009/08/26/292713.html 

    Digester框架属于Jakarta Commons,它以规则和模式为基础处理XML文。与SAX和DOM之类的标准API相比,Digester不涉及太多的细节问题,非常适合于对XML文进行简单的处理?

    在Java和XML开发中,一个常见的任务是把XML文转换成对应的Java Bean对象的层次结构。人们经常用标准的SAX和DOM API来完成这个任务。虽然这两种API都很强大和灵活,但对于某些简单的任务来说,它们显得操作层次太低,也就是说,涉及了太多的细节问题。Jakarta Digester框架能够很好地满足这类场合的需要?

    Digester框架简?

    Jakarta的Digester框架从Struts框架发展而来,原先被用来处理struts-config.xml配置文件,但很快人们认识到它有着更广泛的用途,把它转入了Jakarta Commons项目。Jakarta Commons的目标是提供一?#8220;可重用Java组件的仓?#8221;。Digester最新的版本?.3,于2002??3日发布?

    Digester框架允许开发者指定一组动作,当解析器在XML文中发现某些特定的简单模式时动作被执行。Digester框架带有10个预定义的规则(Rule),涵盖了unmarshalling XML(例如创建Bean或设置Bean属性)的大多数需求( marshalling的原意是?#8220;配制整齐,编组列?#8221;,marshalling是在内存中为Java对象生成XML描述文的过程,而unmarshalling是指把XML形式的描述转换到可用Java代码操作的对象的过程,我们称之为“反配?#8221;),但必要时用户可以定义和实现自己的规则?

    在本文的例子中,我们将反配制下面这个XML文?

    <?xml version="1.0"?>
                <catalog library="somewhere">
                <book>
                <author>Author 1</author>
                <title>Title 1</title>
                </book>
                <book>
                <author>Author 2</author>
                <title>His One Book</title>
                </book>
                <magazine>
                <name>Mag Title 1</name>
                <article page="5">
                <headline>Some Headline</headline>
                </article>
                <article page="9">
                <headline>Another Headline</headline>
                </article>
                </magazine>
                <book>
                <author>Author 2</author>
                <title>His Other Book</title>
                </book>
                <magazine>
                <name>Mag Title 2</name>
                <article page="17">
                <headline>Second Headline</headline>
                </article>
                </magazine>
                </catalog>

    下面是Bean的代码。注意使用Digester框架时,Bean类必须定义成public?

    import java.util.Vector;
                public class Catalog {
                private Vector books;
                private Vector magazines;
                public Catalog() {
                books = new Vector();
                magazines = new Vector();
                }
                public void addBook( Book rhs ) {
                books.addElement( rhs );
                }
                public void addMagazine( Magazine rhs ) {
                magazines.addElement( rhs );
                }
                public String toString() {
                String newline = System.getProperty( "line.separator" );
                StringBuffer buf = new StringBuffer();
                buf.append( "--- Books ---" ).append( newline );
                for( int i=0; i<books.size(); i++ ){
                buf.append( books.elementAt(i) ).append( newline );
                }
                buf.append( "--- Magazines ---" ).append( newline );
                for( int i=0; i<magazines.size(); i++ ){
                buf.append( magazines.elementAt(i) ).append( newline );
                }
                return buf.toString();
                }
                }
                //===================================================
                public class Book {
                private String author;
                private String title;
                public Book() {}
                public void setAuthor( String rhs ) { author = rhs; }
                public void setTitle(  String rhs ) { title  = rhs; }
                public String toString() {
                return "Book: Author='" + author + "' Title='" + title + "'";
                }
                }
                //===================================================
                import java.util.Vector;
                public class Magazine {
                private String name;
                private Vector articles;
                public Magazine() {
                articles = new Vector();
                }
                public void setName( String rhs ) { name = rhs; }
                public void addArticle( Article a ) {
                articles.addElement( a );
                }
                public String toString() {
                StringBuffer buf = new StringBuffer( "Magazine: Name='" + name + "' ");
                for( int i=0; i<articles.size(); i++ ){
                buf.append( articles.elementAt(i).toString() );
                }
                return buf.toString();
                }
                }
                //===================================================
                public class Article {
                private String headline;
                private String page;
                public Article() {}
                public void setHeadline( String rhs ) { headline = rhs; }
                public void setPage(     String rhs ) { page     = rhs; }
                public String toString() {
                return "Article: Headline='" + headline + "' on page='" + page + "' ";
                }
                }

    1 2 下一?gt;>

    Digester框架以模式(Pattern)和规则(Rule)为基础处理输入的XML。模式必须与XML元素匹配,包括其名字和在文树内的位置。描述匹配模式的语法类似于XPath匹配模式,例如:catalog模式匹配顶层?ccid_code><catalog>元素,catalog/book模式匹配直接嵌套?lt;catalog>元素内的<book>元素(但不匹配文?内其他位置?lt;book>元素?/ccid_code>?

    所有的模式都必须指定其完整名称——从根元素开始的完整路径。唯一的例外是包含通配符(“*”)的模式,例?/name模式匹配XML文内任何位置的<name>元素。但是根元素不必特别指出,因为所有的路径都是从根元素开始的绝对路径?

    当Digester发现一个指定的模式,它就执行关联的任务。由此可见,Digester框架显然与SAX解析器有着密切的关系(实际上,Digester类实现了org.xml.sax.ContentHandler,并维护着解析栈)。所有在Digester中使用的规则必须扩展org.apache.commons.digester.Rule,后者本身提供了一些类似于SAX的ContentHandler回调函数的方法。例如,当遇到匹配元素的开始标记和结束标记时,begin()方法和end()方法将分别被调用?

    一旦遇到匹配元素的内容,body()方法被调用;最后被调用的方法是finish(),这个方法在匹配元素的结束标记处理完毕之后被调用,用来执行可能需要的事后清理任务。然而,大多数时候我们不必关注这些方法,因为框架提供的标准规则很可能已经提供了所有必需的功能?

    要反配制一个文?,首先创建一个org.apache.commons.digester.Digester类的实例,如果必要的话,进行一些配置操作,指定必需的模式和规则,最后向parse()方法传递一个XML文件的引用。下面的DigesterDriver示范了这一处理过程(必须在命令行上指定输入XML文的名称)?

    import org.apache.commons.digester.*;
                import java.io.*;
                import java.util.*;
                public class DigesterDriver {
                public static void main( String[] args ) {
                try {
                Digester digester = new Digester();
                digester.setValidating( false );
                digester.addObjectCreate( "catalog", Catalog.class );
                digester.addObjectCreate( "catalog/book", Book.class );
                digester.addBeanPropertySetter( "catalog/book/author", "author" );
                digester.addBeanPropertySetter( "catalog/book/title", "title" );
                digester.addSetNext( "catalog/book", "addBook" );
                digester.addObjectCreate( "catalog/magazine", Magazine.class );
                digester.addBeanPropertySetter( "catalog/magazine/name", "name" );
                digester.addObjectCreate( "catalog/magazine/article", Article.class );
                digester.addSetProperties( "catalog/magazine/article", "page", "page" );
                digester.addBeanPropertySetter( "catalog/magazine/article/headline" );
                digester.addSetNext( "catalog/magazine/article", "addArticle" );
                digester.addSetNext( "catalog/magazine", "addMagazine" );
                File input = new File( args[0] );
                Catalog c = (Catalog)digester.parse( input );
                System.out.println( c.toString() );
                } catch( Exception exc ) {
                exc.printStackTrace();
                }
                }
                }

    在上面的代码中,我们首先创建了Digester类的一个实例digester,然后指定它不要用DTD验证XML文的合法性——这是因为我们没有为XML文定义DTD。接下来,我们指定了模式和关联的规则:ObjectCreateRule创建指定类的一个实例,并将它压入解析栈。SetPropertiesRule把Bean属性设置成当前XML元素的属性值——规则的第一个参数是XML属性的名称,第二个参数是Bean属性的名称?

    SetPropertiesRule获取的是XML属性的值,而BeanPropertySetterRule获取的是位于当前元素内的原始字符数据值。使用BeanPropertySetterRule时不必指定要设置的Bean属性名字,默认是当前XML元素的名称。在上面的例子中,在匹配catalog/magazine/article/headline模式的规则定义中使用的就是默认值。最后,SetNextRule弹出解析栈顶部的对象,并把该对象传递给它下面对象的指定名称的方法——通常用来把一个配置完毕的Bean插入父对象?

    注意,我们可以为同一个模式注册多个规则。如果注册了多个规则,则这些规则按照它们被加入到Digester的次序执行,例如,如果要处理catalog/magazine/article?article>元素,我们首先创建合适的article Bean,然后设置page属性,最后弹出完成后的article Bean,并把它插入magazine?

    调用任意方法

    我们不仅可以设置Bean的属性,而且还可以调用堆栈内对象的任意方法。这通过CallMethodRule完成,我们只需指定方法名字,如有必要,再说明调用的参数类型和数量。CallParamRule用来定义传递给被调用函数的参数值,参数值可以从当前XML元素的命名的属性获取,也可以从当前元素包含的原始字符数据获取。例如,在前面实现DigesterDriver的例子中,我们可以不用BeanPropertySetterRule,而是通过显式调用属性的set方法达到同样的目的:

    digester.addCallMethod( "catalog/book/author", "setAuthor", 1 );
                digester.addCallParam( "catalog/book/author", 0 );

    上面的第一行代码给出了要调用的方法(即setAuthor()),以及该调用需要的参数数量(即1)。第二行代码的意思是?author>元素包含的字符数据获取函数参数的值,把它作为参数数组的第一个传入(即索引是0的数组元素)。如果我们指定了XML元素属性的名称(例如digester.addCallParam( "catalog/book/author", 0, "author" );),则参数值将从当前元素的相应属性值获取?

    这里必须注意的是?#8220;digester.addCallMethod( "pattern", "methodName", 0 );”这个语句不是指定了一个不带参数的方法调用,而是指定了带有一个参数的方法调用,它的值就是当前XML元素的字符数据!这样,我们又有了另一种替代BeanPropertySetterRule的办法:

    digester.addCallMethod( "catalog/book/author", "setAuthor", 0 );

    如果要调用一个确实没有参数的方法,必须采用如下形式:digester.addCallMethod( "pattern", "methodName" );?

    标准规则概要

    下面简要说明所有标准规则?

    创建

    ObjectCreateRule:利用指定类的默认构造函数,创建该类的一个对象,并把对象压入栈。当元素处理结束时,对象被弹出。被实例化的类可通过class对象或类的全称给出?

    FactoryCreateRule:利用指定的工厂类创建一个对象,把对象压入栈。对于没有提供默认构造函数的类,这一规则很有用。用于该规则的工厂类必须实现org.apache.commons.digester.ObjectCreationFactory接口?

    设置属?

    SetPropertiesRule:利用指定名称的XML元素属性值,设置顶层Bean的一个或者多个指定名称的属性。XML元素的属性名称和Bean的属性名称以String[]数组形式传入该规则(通常用来处理

    之类的结构)?

    BeanPropertySetterRule:把顶层Bean的指定名称的属性设置成当前XML元素包含的字符数据。(通常用来处理<page>10</page>之类的结构)?

    SetPropertyRule:设置顶层Bean的一个属性。无论是Bean属性的名称,还是赋予该属性的值,都在当前XML元素中以属性的形式指定,例如:<article key="page" value="10" />?

    管理?子关?

    SetNextRule:弹出栈顶的对象,把它传递给紧接其下的另一个对象的指定名称的方法。通常用来把一个已经初始化的Bean插入到父对象?

    SetTopRule:把栈里面上数第二的对象传递给顶层的对象。当子对象提供了一个setParenet方法时,这一规则很有用?

    SetRootRule:调用栈底对象的一个方法,并把栈顶的对象作为参数传入?

    调用任意方法

    CallMethodRule:调用顶层Bean的指定名称的方法。被调用的方法可以有任意多个参数,参数的值通过后继的CallParamRule给出?

    CallParamRule:表示方法调用的参数。参数的值或者取自指定名称的XML元素的属性,或者是当前元素包含的原始字符数据。这个规则要求用一个整数指定它在参数列表中的位置?

    通过XML指定规则

    在前面的内容中,我们用程序代码的方式指定模式和规则,这些模式和规则都是在编译的时候就已经确定,虽然从概念上来讲比较简单,但却不能说尽善尽美:Digester框架的总体目标是在运行时识别和处理各种数据结构,但如果我们用编程的方法指定模式和规则,则所有行为在编译时已经固定!如果Java源程序中包含了大量固定的字符串,通常意味着程序在执行某些配置操作,这部分操作可以被(或许是应该被)延迟到运行时进行?

    org.apache.commons.digester.xmlrules包解决了这个问题。这个包提供了一个DigesterLoader类,它能够从XML文读取模式/规则对,返回配置好的Digester对象。用来配置Digester对象的XML文必须遵从digester-rules.dtd,这个DTD是xmlrules包的一部分?

    下面就是本文例子的配置文件rules.xml。有几点必须说明?

    首先,模式可以用两种方式指定:或者使?ccid_code><pattern>元素,或者通过代表规则的XML元素的属性。这两种办法可以混合使用,且<pattern>元素是可以嵌套的。其次,<alias>元素?lt;set-properties-rule>一起使用,用来把XML属性映射到Bean属性。最后,就当前发行的Digester软件包而言,我们不能在配置文件中指定BeanPropertySetterRule,正如前面所介绍的,我们用CallMethodRule来达到同样的目标?

    <?xml version="1.0"?>
                <digester-rules>
                <object-create-rule pattern="catalog" classname="Catalog" />
                <set-properties-rule pattern="catalog" >
                <alias attr-name="library" prop-name="library" />
                </set-properties-rule>
                <pattern value="catalog/book">
                <object-create-rule classname="Book" />
                <call-method-rule pattern="author" methodname="setAuthor"
                paramcount="0" />
                <call-method-rule pattern="title" methodname="setTitle"
                paramcount="0" />
                <set-next-rule methodname="addBook" />
                </pattern>
                <pattern value="catalog/magazine">
                <object-create-rule classname="Magazine" />
                <call-method-rule pattern="name" methodname="setName" paramcount="0" />
                <pattern value="article">
                <object-create-rule classname="Article" />
                <set-properties-rule>
                <alias attr-name="page" prop-name="page" />
                </set-properties-rule>
                <call-method-rule pattern="headline" methodname="setHeadline"
                paramcount="0" />
                <set-next-rule methodname="addArticle" />
                </pattern>
                <set-next-rule methodname="addMagazine" />
                </pattern>
                </digester-rules>

    现在,所有实际的操作都转移到了Digester和DigesterLoader类,XmlRulesDriver类就变得相当简单。运行下面的XmlRulesDriver时,在第一个命令行参数中指定目录文?的名字,在第二个参数中指定rules.xml(注意,DigesterLoader不是从File或者org.xml.sax.InputSource读取rules.xml文件,而是要求指定一个URL,因此,下面代码中File引用被转换成了等价的URL)?

    import org.apache.commons.digester.*;
                import org.apache.commons.digester.xmlrules.*;
                import java.io.*;
                import java.util.*;
                public class XmlRulesDriver {
                public static void main( String[] args ) {
                try {
                File input = new File( args[0] );
                File rules = new File( args[1] );
                Digester digester = DigesterLoader.createDigester( rules.toURL() );
                Catalog catalog = (Catalog)digester.parse( input );
                System.out.println( catalog.toString() );
                } catch( Exception exc ) {
                exc.printStackTrace();
                }
                }
                }

    结束语:本文对Jakarta Commons Digester的介绍就到这里结束。当然,还有许多内容这里尚未涉及。其中一个在这里忽略的主题是XML名称空间:Digester允许把规则定义成只能对某一个名称空间内定义的元素起作用?

    另外,我们简单地提及了通过扩展Rule类开发定制规则的问题。按照习惯,Digester类提供了push()、peek()和pop()方法,使得开发者能够自由地直接操作解析栈?

    参考:

    Jakarta Commons Digester Homepage

    Jakarta Struts Homepage



    ]]>ThreadLocal与synchronized - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/08/25/292559.html林光?/dc:creator>林光?/author>Tue, 25 Aug 2009 12:36:00 GMT//www.ot7t.com.cn/lingy/archive/2009/08/25/292559.html相关文章:  
    正确理解ThreadLocal
    ThreadLocal与synchronized

    推荐圈子: Pipboy
    更多相关推荐
    昨天上Java版块逛了一圈,一??千人浏览的帖子引起了偶滴注意 ThreadLocal与synchronized ?页以上的回复,足见大家对这个问题的兴趣?

    老实说,从看到这个帖子的题目开始,就觉得帖子的作者估计是在概念上有所混淆?于是乎想写个咚咚,同大家分享一下自己的心得?

    帖子上,讨论的人很多,高手不乏,各抒己见,但不知新手们看明白没有,因此,这里偶以最简洁列表方式来说一说相关问题?

    1.区别ThreadLocal ?synchronized

    ThreadLocal是一个线程隔?或者说是线程安?的变量存储的管理实体(注意:不是存储用的),它以Java类方式表现;
    synchronized是Java的一个保留字,只是一个代码标识符,它依靠JVM的锁机制来实现临界区的函数、变量在CPU运行访问中的原子性?
    两者的性质、表现及设计初衷不同,因此没有可比较性?

    2.理解ThreadLocal中提到的变量副本
    事实上,我们向ThreadLocal中set的变量不是由ThreadLocal来存储的,而是Thread线程对象自身保存。当用户调用ThreadLocal对象的set(Object o)时,该方法则通过Thread.currentThread()获取当前线程,将变量存入Thread中的一个Map内,而Map的Key就是当前的ThreadLocal实例。请看源码,这是最主要的两个函数,能看出ThreadLocal与Thread的调用关系:

    Java代码
    public void set(T value) {   
            Thread t = Thread.currentThread();   
            ThreadLocalMap map = getMap(t);   
            if (map != null)   
                map.set(this, value);   
            else  
                createMap(t, value);   
    }   
      
    ThreadLocalMap getMap(Thread t) {   
            return t.threadLocals;   
    }  
    public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
    }

    ThreadLocalMap getMap(Thread t) {
            return t.threadLocals;
    }

    (有兴趣的朋友可以阅读Java的ThreadLocal源码)因此,我们可以知道,所谓的变量副本,即是对Object Reference(对象引用)的拷贝?

    3.理解Thread?ThreadLocal对变量的引用关系
    实际上Thread和ThreadLocal对变量引用关系就像是坐标系中的X轴和Y轴,是从两个维度上来组织对变量的引用的?

    首先说Thread?我们知道一个ThreadOne的执行会贯穿多个方法MethodA、MethodB、MethodC这些方法可能分布于不同的类实例。假设,这些方法分别使用了ThreadLocalA、ThreadLocalB、ThreadLocalC来保存线程本地变量,那么这些变量都存于ThreadOne的Map中,并使用各自的ThreadLocal实例作为key?因此,可以认为,借助ThreanLocal的set方法,在X轴上,Thread横向关联同一线程上下文中来自多个Method的变量引用副本?


     


    接着说ThreadLocal?一个MethodA中的X变量将被多个线程ThreadOne、ThreadTwo、ThreadThree所访问。假设MethodA使用ThreadLocal存储X,通过set方法,以ThreadLocal作为key值,将不同线程来访时的不同的变量值引用保存于ThreadOne、ThreadTwo、ThreadThree的各自线程上下文中,确保每个线程有自己的一个变量值。因此,可以认为,ThreadLocal是以Method为Y轴,纵向关联了处于同一方法中的不同线程上的变量?


     

    希望能对大家有所帮助,这样可以少走很多弯路哦?

    本文来自CSDN博客,转载请标明出处://blog.csdn.net/yangairong1984/archive/2008/04/15/2294572.aspx



    ]]>
    理解ThreadLocal - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/08/25/292558.html林光?/dc:creator>林光?/author>Tue, 25 Aug 2009 12:35:00 GMT//www.ot7t.com.cn/lingy/archive/2009/08/25/292558.htmlThreadLocal是什?/p>

    早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序?/p>

    ThreadLocal很容易让人望文生义,想当然地认为是一?#8220;本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些?/p>

    当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本?/p>

    从线程的角度看,目标变量就象是线程的本地变量,这也是类名?#8220;Local”所要表达的意思?/p>

    线程局部变量并不是Java的新发明,很多语言(如IBM IBM XL FORTRAN)在语法层面就提供线程局部变量。在Java中没有提供在语言级支持,而是变相地通过ThreadLocal的类提供支持?/p>

    所以,在Java中编写线程局部变量的代码相对来说要笨拙一些,因此造成线程局部变量没有在Java开发者中得到很好的普及?/p>

    ThreadLocal的接口方?/p>

    ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

    void set(Object value)
    设置当前线程的线程局部变量的值?/p>

    public Object get()
    该方法返回当前线程所对应的线程局部变量?/p>

    public void remove()
    将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度?/p>

    protected Object initialValue()
    返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null?/p>

    值得一提的是,在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal<T>。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()?/p>

    ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。我们自己就可以提供一个简单的实现版本?/p>

    代码清单1 SimpleThreadLocal

    public class SimpleThreadLocal {

    private Map valueMap = Collections.synchronizedMap(new HashMap());

    public void set(Object newValue) {

    valueMap.put(Thread.currentThread(), newValue);①键为线程对象,值为本线程的变量副本

    }

    public Object get() {

    Thread currentThread = Thread.currentThread();

    Object o = valueMap.get(currentThread);②返回本线程对应的变?/p>

    if (o == null && !valueMap.containsKey(currentThread)) {③如果在Map中不存在,放到Map

    中保存起来?/p>

    o = initialValue();

    valueMap.put(currentThread, o);

    }

    return o;

    }

    public void remove() {

    valueMap.remove(Thread.currentThread());

    }

    public Object initialValue() {

    return null;

    }

    }

    虽然代码清单9?这个ThreadLocal实现版本显得比较幼稚,但它和JDK所提供的ThreadLocal类在实现思路上是相近的?/p>

    一个TheadLocal实例

    下面,我们通过一个具体的实例了解一下ThreadLocal的具体使用方法?/p>

    代码清单2 SequenceNumber

    package com.baobaotao.basic;

    public class SequenceNumber {

    ①通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始?/p>

    private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>(){

    public Integer initialValue(){

    return 0;

    }

    };

    ②获取下一个序列?/p>

    public int getNextNum(){

    seqNum.set(seqNum.get()+1);

    return seqNum.get();

    }

    public static void main(String[] args)

    {

    SequenceNumber sn = new SequenceNumber();

    ?3个线程共享sn,各自产生序列号

    TestClient t1 = new TestClient(sn);

    TestClient t2 = new TestClient(sn);

    TestClient t3 = new TestClient(sn);

    t1.start();

    t2.start();

    t3.start();

    }

    private static class TestClient extends Thread

    {

    private SequenceNumber sn;

    public TestClient(SequenceNumber sn) {

    this.sn = sn;

    }

    public void run()

    {

    for (int i = 0; i < 3; i++) {④每个线程打?个序列?/p>

    System.out.println("thread["+Thread.currentThread().getName()+

    "] sn["+sn.getNextNum()+"]");

    }

    }

    }

    }

     
    通常我们通过匿名内部类的方式定义ThreadLocal的子类,提供初始的变量值,如例子中①处所示。TestClient线程产生一组序列号,在③处,我们生?个TestClient,它们共享同一个SequenceNumber实例。运行以上代码,在控制台上输出以下的结果?/p>

    thread[Thread-2] sn[1]

    thread[Thread-0] sn[1]

    thread[Thread-1] sn[1]

    thread[Thread-2] sn[2]

    thread[Thread-0] sn[2]

    thread[Thread-1] sn[2]

    thread[Thread-2] sn[3]

    thread[Thread-0] sn[3]

    thread[Thread-1] sn[3]

    考察输出的结果信息,我们发现每个线程所产生的序号虽然都共享同一个SequenceNumber实例,但它们并没有发生相互干扰的情况,而是各自产生独立的序列号,这是因为我们通过ThreadLocal为每一个线程提供了单独的副本?/p>

    Thread同步机制的比?/p>

    ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题?/p>

    在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大?/p>

    而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal?/p>

    由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用,代码清单 9 2就使用了JDK 5.0新的ThreadLocal<T>版本?/p>

    概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用?#8220;以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响?/p>

    Spring使用ThreadLocal解决线程安全问题

    我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了?/p>

    一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程,如图9?所示:

     

    ?同一线程贯通三?/p>

    这样你就可以根据需要,将一些非线程安全的变量以ThreadLocal存放,在同一次请求响应的调用线程中,所有关联的对象引用到的都是同一个变量?/p>

    下面的实例能够体现Spring对有状态Bean的改造思路?/p>

    代码清单3 TopicDao:非线程安全

    public class TopicDao {

    private Connection conn;①一个非线程安全的变?/p>

    public void addTopic(){

    Statement stat = conn.createStatement();②引用非线程安全变量

    }

    }

    由于①处的conn是成员变量,因为addTopic()方法是非线程安全的,必须在使用时创建一个新TopicDao实例(非singleton)。下面使用ThreadLocal对conn这个非线程安全的“状?#8221;进行改造:

    代码清单4 TopicDao:线程安?/p>

    import java.sql.Connection;

    import java.sql.Statement;

    public class TopicDao {

    ①使用ThreadLocal保存Connection变量

    private static ThreadLocal<Connection> connThreadLocal = new ThreadLocal<Connection>();

    public static Connection getConnection(){

    ②如果connThreadLocal没有本线程对应的Connection创建一个新的Connection?/p>

    并将其保存到线程本地变量中?/p>

    if (connThreadLocal.get() == null) {

    Connection conn = ConnectionManager.getConnection();

    connThreadLocal.set(conn);

    return conn;

    }else{

    return connThreadLocal.get();③直接返回线程本地变?/p>

    }

    }

    public void addTopic() {

    ④从ThreadLocal中获取线程对应的Connection

    Statement stat = getConnection().createStatement();

    }

    }

    不同的线程在使用TopicDao时,先判断connThreadLocal.get()是否是null,如果是null,则说明当前线程还没有对应的Connection对象,这时创建一个Connection对象并添加到本地线程变量中;如果不为null,则说明当前的线程已经拥有了Connection对象,直接使用就可以了。这样,就保证了不同的线程使用线程相关的Connection,而不会使用其它线程的Connection。因此,这个TopicDao就可以做到singleton共享了?/p>

    当然,这个例子本身很粗糙,将Connection的ThreadLocal直接放在DAO只能做到本DAO的多个方法共享Connection时不发生线程安全问题,但无法和其它DAO共用同一个Connection,要做到同一事务多DAO共享同一Connection,必须在一个共同的外部类使用ThreadLocal保存Connection?/p>

    小结

    ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性?/p>

     

    本文来自CSDN博客,转载请标明出处://blog.csdn.net/qjyong/archive/2008/03/08/2158097.aspx



    ]]>
    owner - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/07/24/288258.html林光?/dc:creator>林光?/author>Fri, 24 Jul 2009 12:13:00 GMT//www.ot7t.com.cn/lingy/archive/2009/07/24/288258.htmlowner_4
    客户服务人员

    应该是owner_2客服支持人员

    3是制作人?br /> 4是服务人?br /> 31没看?/font>

    ]]>
    ilevel - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/07/23/287998.html林光?/dc:creator>林光?/author>Thu, 23 Jul 2009 03:51:00 GMT//www.ot7t.com.cn/lingy/archive/2009/07/23/287998.html
     
    ilevel ?,2,3,4时分别是什么意思啊
    3--区域
    4--组管?br /> 1--
    2--?
     
     
    3 区域 ?nbsp;大区
    1 全国 ?nbsp;乱七八糟?nbsp;服务拍摄之类?/font>
    2是论七八糟服务拍摄的下一?/font>
     
    这个在那张表定义?我在ali_zeus_resourece表里找不?/font>
     
    在ali_zeus_access_area


    ]]>
    ilevel - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/07/23/287997.html林光?/dc:creator>林光?/author>Thu, 23 Jul 2009 03:51:00 GMT//www.ot7t.com.cn/lingy/archive/2009/07/23/287997.html
     
    ilevel ?,2,3,4时分别是什么意思啊
    3--区域
    4--组管?br /> 1--
    2--?
     
     
    3 区域 ?nbsp;大区
    1 全国 ?nbsp;乱七八糟?nbsp;服务拍摄之类?/font>
    2是论七八糟服务拍摄的下一?/font>
     
    这个在那张表定义?我在ali_zeus_resourece表里找不?/font>
     
    在ali_zeus_access_area


    ]]>
    EXECUTE IMMEDIATE用法小解 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/07/16/287019.html林光?/dc:creator>林光?/author>Thu, 16 Jul 2009 11:42:00 GMT//www.ot7t.com.cn/lingy/archive/2009/07/16/287019.html 它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL?动态创建和执行SQL语句性能超前,EXECUTE IMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码.尽管DBMS_SQL仍然可用,但是推荐使用EXECUTE IMMEDIATE,因为它获的收益在包之上?


    -- 使用技?br />

    1. EXECUTE IMMEDIATE将不会提交一个DML事务执行,应该显式提?br /> 如果通过EXECUTE IMMEDIATE处理DML命令?br /> 那么在完成以前需要显式提交或者作为EXECUTE IMMEDIATE自己的一部分.
    如果通过EXECUTE IMMEDIATE处理DDL命令,它提交所有以前改变的数据


    2. 不支持返回多行的查询,这种交互将用临时表来存储记录(参照例子如下)或者用REF cursors.


    3. 当执行SQL语句时,不要用分号,当执行PL/SQL块时,在其尾部用分号.


    4. 在Oracle手册中,未详细覆盖这些功能?br /> 下面的例子展示了所有用到Execute immediate的可能方?希望能给你带来方?


    5. 对于Forms开发?当在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功?


    EXECUTE IMMEDIATE -- 用法例子


    1. 在PL/SQL运行DDL语句


    begin
       execute immediate 'set role all';
    end;


    2. 给动态语句传?USING 子句)


    declare
       l_depnam varchar2(20) := 'testing';
       l_loc     varchar2(10) := 'Dubai';
       begin
       execute immediate 'insert into dept values   (:1, :2, :3)'
         using 50, l_depnam, l_loc;
       commit;
    end;


    3. 从动态语句检索?INTO子句)


    declare
       l_cnt     varchar2(20);
    begin
       execute immediate 'select count(1) from emp'
         into l_cnt;
       dbms_output.put_line(l_cnt);
    end;


    4. 动态调用例?例程中用到的绑定变量参数必须指定参数类型.
    黓认为IN类型,其它类型必须显式指定


    declare
       l_routin    varchar2(100) := 'gen2161.get_rowcnt';
       l_tblnam    varchar2(20) := 'emp';
       l_cnt       number;
       l_status    varchar2(200);
    begin
       execute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'
         using in l_tblnam, out l_cnt, in out l_status;

       if l_status != 'OK' then
          dbms_output.put_line('error');
       end if;
    end;


    5. 将返回值传递到PL/SQL记录类型;同样也可?rowtype变量


    declare
       type empdtlrec is record (empno   number(4),
                                ename   varchar2(20),
                                deptno   number(2));
       empdtl empdtlrec;
    begin
       execute immediate 'select empno, ename, deptno ' ||
                        'from emp where empno = 7934'
         into empdtl;
    end;


    6. 传递并检索?INTO子句用在USING子句?br />

    declare
       l_dept     pls_integer := 20;
       l_nam      varchar2(20);
       l_loc      varchar2(20);
    begin
       execute immediate 'select dname, loc from dept where deptno = :1'
         into l_nam, l_loc
         using l_dept ;
    end;


    7. 多行查询选项.对此选项用insert语句填充临时表,
    用临时表进行进一步的处理,也可以用REF cursors纠正此缺?

    declare
       l_sal    pls_integer := 2000;
    begin
       execute immediate 'insert into temp(empno, ename) ' ||
                        '           select empno, ename from emp ' ||
                        '           where   sal > :1'
         using l_sal;
       commit;
    end;


            对于处理动态语?EXECUTE IMMEDIATE 比以前可能用到的更容易并且更高效.
    当意图执行动态语句时,适当地处理异常更加重?应该关注于捕获所有可能的异常.
    我是无聊的人,所以做无聊的事情?/em>


    ]]>
    使用 TRUNCATE TABLE 删除所有行 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/07/16/287018.html林光?/dc:creator>林光?/author>Thu, 16 Jul 2009 11:41:00 GMT//www.ot7t.com.cn/lingy/archive/2009/07/16/287018.html
    SQL Server 2008 联机丛书?009 ?5 月)
    使用 TRUNCATE TABLE 删除所有行

    若要删除表中的所有行,则 TRUNCATE TABLE 语句是一种快速、有效的方法。TRUNCATE TABLE 与不?WHERE 子句?DELETE 语句类似。但是,TRUNCATE TABLE 速度更快,并且使用更少的系统资源和事务日志资源?/p>

    ?DELETE 语句相比,TRUNCATE TABLE 具有以下优点?/p>

    • 所用的事务日志空间较少?br /> DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一个项。TRUNCATE TABLE 通过释放用于存储表数据的数据页来删除数据,并且在事务日志中只记录页释放?br />
    • 使用的锁通常较少?br /> 当使用行锁执?DELETE 语句时,将锁定表中各行以便删除。TRUNCATE TABLE 始终锁定表和页,而不是锁定各行?br />
    • 如无例外,在表中不会留有任何页?br /> 执行 DELETE 语句后,表仍会包含空页。例如,必须至少使用一个排?(LCK_M_X) 表锁,才能释放堆中的空表。如果执行删除操作时没有使用表锁,表(堆)中将包含许多空页。对于索引,删除操作会留下一些空页,尽管这些页会通过后台清除进程迅速释放?br />

    ?DELETE 语句相同,使?TRUNCATE TABLE 清空的表的定义与其索引和其他关联对象一起保留在数据库中。如果表中包含标识列,该列的计数器将重置为该列定义的种子值。如果未定义种子,则使用默认?1。若要保留标识计数器,请使用 DELETE?/p>

    Microsoft SQL Server 引入一种功能,此功能可删除或截断超?128 个区的表,而无需同时保留需要删除的所有区的锁。有关详细信息,请参?a id="ctl00_MTContentSelector1_mainContentContainer_ctl04" onclick="javascript:Track('ctl00_MTContentSelector1_mainContentContainer_cpe28768_c|ctl00_MTContentSelector1_mainContentContainer_ctl04',this);" >删除并重新生成大型对?/a>?/p>

    下面的示例删?JobCandidate 表中的所有数据。在 TRUNCATE TABLE 语句之前和之后使?SELECT 语句来比较结果?/p>

    USE AdventureWorks;
    GO
    SELECT COUNT(*) AS BeforeTruncateCount
    FROM HumanResources.JobCandidate;
    GO
    TRUNCATE TABLE HumanResources.JobCandidate;
    GO
    SELECT COUNT(*) AS AfterTruncateCount
    FROM HumanResources.JobCandidate;
    GO
    


    ]]>
    一个简单的逻辑备份策略学习 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/07/10/286287.html林光?/dc:creator>林光?/author>Fri, 10 Jul 2009 08:58:00 GMT//www.ot7t.com.cn/lingy/archive/2009/07/10/286287.html一个简单的逻辑备份策略学习
    需求:
    每天19:00备份一次业务用?br /> 每个备份最多保??br /> 每个备份用日期作为备份文件的名称

    [root@localhost opt]# cat /home/autoBackup/ora_env
    export ORACLE_BASE=/opt/oracle
    export ORACLE_HOME=/opt/oracle/product/10.2.0
    export ORACLE_SID=STAPLES
    export ORACLE_TERM=xterm
    #export NLS_LANG="AMERICAN_AMERICA.ZHS16GBK"
    export ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data
    export CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib
    export PATH=$PATH:$ORACLE_HOME/bin

    export TNS_ADMIN=$ORACLE_HOME/network/admin
    export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORACLE_HOME/jlib
    export JAVA_HOME=$ORACLE_HOME/jdk
    export ORA_NLS10=$ORACLE_HOME/nls/data
    export LC_CTYPE=en_US.UTF-8

    [root@localhost opt]# cat /opt/backup_exp.sh
    #!/bin/sh
    #CREATOR:daimin
    #function:backup database with expdp
    #usage:crontab on linux
    #last modify:tuolei 2007-08-29 create
    #set environment variable
    . /home/autoBackup/ora_env  #设置exp的环境变?br /> #开始备份,假定目录backupPath已经创建,并且backupPath=/opt/oracle/backup
    backupPath='/opt/oracle/backup/'
    FILE=`date +%Y%m%d`'.dmp'
    LOGFILE=`date +%Y%m%d`'.log'
    exp daimin/daimin@STAPLES file=$backupPath$FILE.dmp log=$backupPath$LOGFILE

    #删除以前过期的备?br /> find /opt/oracle/backup/* -name "*.dmp" -mtime +4 -exec rm {} \;

     

    [root@localhost etc]# crontab -e
    0 19 * * * /opt/backup_exp.sh > /opt/oracle/backup/logs/backup_exp.log 2>&1
    ~
    "crontab.XXXXmfkudb" 1L, 76C written
    crontab: installing new crontab
    [root@localhost etc]# crontab -l
    0 19 * * * /opt/backup_exp.sh > /opt/oracle/backup/logs/backup_exp.log 2>&1

    注意?br /> 1?opt/backup_exp.sh需要具有可执行权限,才可以被root用户执行
    [root@localhost backup]# chmod +x /opt/backup_exp.sh
    否则会出?bin/sh: /opt/backup_exp.sh: Permission denied错误
    2、需要在脚本的第一行加#!/bin/sh
    否则会出?bin/sh: /opt/backup_exp.sh: cannot execute binary file错误
    3、注意在执行exp命令之前,需要设置环境变量,所以在逻辑备份脚本中执行了. /home/autoBackup/ora_env 命令;


    参考网页:
    //blog.csdn.net/wzy0623/archive/2008/10/31/3193150.aspx
    //www.linuxsir.org/main/?q=node/209


    本文来自CSDN博客,转载请标明出处://blog.csdn.net/daimin1983/archive/2008/12/13/3511380.aspx



    ]]>
    Linux系统利用Crontab命令实现定时重启 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/07/10/286193.html林光?/dc:creator>林光?/author>Fri, 10 Jul 2009 03:01:00 GMT//www.ot7t.com.cn/lingy/archive/2009/07/10/286193.html  Crontab是一个很方便的在unix/linux系统上定?循环)执行某个任务的程?

      使用cron服务,用 service crond status 查看 cron服务状态,如果没有启动?service crond start启动它,

      cron服务是一个定时执行的服务,可以通过crontab 命令添加或者编辑需要定时执行的任务?

      crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数

      crontab -l //列出某个用户cron服务的详细内?

      crontab -r //删除没个用户的cron服务

      crontab -e //编辑某个用户的cron服务

      比如说root查看自己的cron设置:crontab -u root -l

      再例如,root想删除fred的cron设置:crontab -u fred -r

      在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e

      进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt

      编辑/etc/crontab文件,在末尾加上一行: 30 5 * * * root init 6 这样就将系统配置为了每天早上5?0自动重新启动?

      需要将crond设置为系统启动后自动启动的服务,可以?etc/rc.d/rc.local 中,在末尾加?

      service crond start

      如果还需要在系统启动十加载其他服务,可以继续加上其他服务的启动命令?

      比如?service mysqld start

      基本用法:

      1. crontab -l

      列出当前的crontab任务

      2. crontab -d

      删除当前的crontab任务

      3. crontab -e (solaris5.8上面?crontab -r)

      编辑一个crontab任务,ctrl_D结束

      4. crontab filename

      以filename做为crontab的任务列表文件并载入

      crontab file的格?

      crontab 文件中的行由 6 个字段组成,不同字段间用空格?tab 键分隔。前 5 个字段指定命令要运行的时?

      分钟 (0-59)

      小时 (0-23)

      日期 (1-31)

      月份 (1-12)

      星期?0-6,其?0 代表星期?

      ?6 个字段是一个要在适当时间执行的字符串

      例子:

      #MIN HOUR DAY MONTH DAYOFWEEK COMMAND

      #每天早上6?0?

      10 6 * * * date

      #每两个小?

      0 */2 * * * date (solaris 5.8似乎不支持此种写?

      #晚上11点到早上8点之间每两个小时,早??

      0 23-7/2? * * * date

      #每个月的4号和每个礼拜的礼拜一到礼拜三的早?1?

      0 11 4 * mon-wed date

      #1月份日早??

      0 4 1 jan * date

      补充:在使用crontab的时候,要特别注意的是运行脚本中能够访问到的环境变量和当前测试环境中的环境变量未必一致,一个比较保险的做法是在运行的脚本程序中自行设置环境变量(export)

      (1)先建一个文件crond.txt如下?每天早上5?6分重新启?

      36 5 * * * reboot

      (2)上传?opt目录

      (3)运行命令

      crontab /opt/crond.txt

      crontab -l

      让配置文件生效:如果让配置文件生效,还得重新启动cron,切记,既然每个用户下的cron配置文件修改后。也要重新启动cron服务器?

      在Fedora 和Redhat中,我们应该用;

      [root@localhost ~]# /etc/init.d/crond restart

      如果让crond 在开机时运行,应该改变其运行级别?

      [root@localhost ~]# chkconfig --levels 35 crond on

      service crond status 查看 cron服务状态,如果没有启动?service crond start启动它, cron服务是一个定时执行的服务,可以通过crontab 命令添加或者编辑需要定时执行的任务

    Crontab文件的每一行由六个?minutes、hours、day of month、month、day of week?command)?成,域之间用空格或Tab分开,其中:

    minutes?分钟域,值的范围??9

    hours?小时域,值的范围??3

    day of month?日期,值的范围??1

    month?月份,值的范围??2

    day of week?星期,值的范围??,星期日值为0

    command?所要运行的命令

    如果一个域?,表明命令可以在该域所有可能的取值范围内执行?

    如果一个域是由连字符隔开的两个数字,表明命令可以在两个数字之间的范围内执行(包括两个数字 本身)?

    如果一个域是由逗号隔开的一系列值组成的,表明命令可以在这些值组成的范围内执行?

    如果日期域和星期域都有值,则这两个域都有效?

    编写一个文件,用以启动自动备份进程?

    cd /opt

    touch reboot.txt

    在reboot.txt中添加一下内?

    0 4 * * * reboot

    crontab /opt/reboot.txt

    用crontab -e编辑定时操作,例如加入下行命令:

    用crontab -l命令来查?

    注意:需要启动服?添加在rc.local?

    重启crond任务

    /etc/init.d/cron restart (ubuntu?

    第一?在Fedora或Redhat 等以RPM包管理的系统中;

    [root@localhost ~]# /etc/init.d/crond start

    [root@localhost ~]# /etc/init.d/crond stop

    [root@localhost ~]# /etc/init.d/crond restart

    /etc/rc.d/init.d/crond restart

    命令简?

    crontab-操作每个用户的守护程序和该执行的时间表?

    部分参数说明

    crontab file [-u user]-用指定的文件替代目前的crontab?

    crontab-[-u user]-用标准输入替代目前的crontab.

    crontab-1[user]-列出用户目前的crontab.

    crontab-e[user]-编辑用户目前的crontab.

    crontab-d[user]-删除用户目前的crontab.

    crontab-c dir- 指定crontab的目录?

    crontab文件的格式:M H D m d cmd.

    M: 分钟?-59)?

    H:小时(0-23)?

    D:天?-31)?

    m: 月(1-12)?

    d: 一星期内的天(0~6?为星期天)?

    cmd要运行的程序,程序被送入sh执行,这个shell只有USER,HOME,SHELL这三个环境变量?

    下面是一个例子文件:

    #MIN HOUR DAY MONTH DAYOFWEEK COMMAND
                #每天早上6?
                106* * * date
                #每两个小?
                0*/2* * * date
                #晚上11点到早上8点之间每两个小时,早上部?
                0 23-7/2?* * * date
                #每个月的4号和每个礼拜的礼拜一到礼拜三的早?1?
                0 11 4* mon-wed date
                #1月份日早??
                0 4 1 jan* date
                范例
                lark:~>crontab-1 列出用户目前的crontab.
                #MIN HOUR DAY MONTH DAYOFWEEK COMMAND
                10 6* * * date
                0*/2* * * date
                0 23-7/2,8 * * * date
                lark:~>

    (责任编辑:云子?



    ]]>
    Linux定时任务系统Cron入门 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/07/09/286135.html林光?/dc:creator>林光?/author>Thu, 09 Jul 2009 10:38:00 GMT//www.ot7t.com.cn/lingy/archive/2009/07/09/286135.htmlcron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业。由于Cron 是Linux的内置服务,但它不自动起来,可以用以下的方法启动、关闭这个服务:

     

    /sbin/service crond start //启动服务

    /sbin/service crond stop //关闭服务

    /sbin/service crond restart //重启服务

    /sbin/service crond reload //重新载入配置

     

     

    你也可以将这个服务在系统启动的时候自动启动:

     

    ?etc/rc.d/rc.local这个脚本的末尾加上:

    /sbin/service crond start

     

    现在Cron这个服务已经在进程里面了,我们就可以用这个服务了,Cron服务提供以下几种接口供大家使用:

     

    1.直接用crontab命令编辑

     

    cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明?/p>

     

    crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数

     

    crontab -l //列出某个用户cron服务的详细内?/p>

     

    crontab -r //删除没个用户的cron服务

     

    crontab -e //编辑某个用户的cron服务

     

    比如说root查看自己的cron设置:crontab -u root -l

     

    再例如,root想删除fred的cron设置:crontab -u fred -r

     

    在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e

     

    进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt

     

    这个格式的前一部分是对时间的设定,后面一部分是要执行的命令,如果要执行的命令太多,可以把这些命令写到一个脚本里面,然后在这里直接调用这个脚本就可以了,调用的时候记得写出命令的完整路径。时间的设定我们有一定的约定,前面五?号代表五个数字,数字的取值范围和含义如下?/p>

     

    分钟 ?-59?/p>

     

    小時 ?-23?/p>

     

    日期 ?-31?/p>

     

    月份 ?-12?/p>

     

    星期 ?-6?/0代表星期?/p>

     

    除了数字还有几个个特殊的符号就是"*"?/"?-"?,"?代表所有的取值范围内的数字,"/"代表每的意?"*/5"表示?个单位,"-"代表从某个数字到某个数字,","分开几个离散的数字。以下举几个例子说明问题?/p>

     

    每天早上6?/p>

     

    0 6 * * * echo "Good morning." >> /tmp/test.txt //注意单纯echo,从屏幕上看不到任何输出,因为cron把任何输出都email到root的信箱了?/p>

     

    每两个小?/p>

     

    0 */2 * * * echo "Have a break now." >> /tmp/test.txt

     

    晚上11点到早上8点之间每两个小时,早上八?/p>

     

    0 23-7/2? * * * echo "Have a good dream:)" >> /tmp/test.txt

     

    每个月的4号和每个礼拜的礼拜一到礼拜三的早?1?/p>

     

    0 11 4 * 1-3 command line

     

    1?日早??/p>

     

    0 4 1 1 * command line

     

    每次编辑完某个用户的cron设置后,cron自动?var/spool/cron下生成一个与此用户同名的文件,此用户的cron信息都记录在这个文件中,这个文件是不可以直接编辑的,只可以用crontab -e 来编辑。cron启动后每过一份钟读一次这个文件,检查是否要执行里面的命令。因此此文件修改后不需要重新启动cron服务?/p>

     

    2.编辑/etc/crontab 文件配置cron

     

    cron服务每分钟不仅要读一?var/spool/cron内的所有文件,还需要读一?etc/crontab,因此我们配置这个文件也能运用 cron服务做一些事情。用crontab配置是针对某个用户的,而编?etc/crontab是针对系统的任务。此文件的文件格式是?/p>

     

    SHELL=/bin/bash

    PATH=/sbin:/bin:/usr/sbin:/usr/bin

    MAILTO=root //如果出现错误,或者有数据输出,数据作为邮件发给这个帐?/p>

    HOME=/ //使用者运行的路径,这里是根目录

    # run-parts

    01 * * * * root run-parts /etc/cron.hourly //每小时执?etc/cron.hourly内的脚本

    02 4 * * * root run-parts /etc/cron.daily //每天执行/etc/cron.daily内的脚本

    22 4 * * 0 root run-parts /etc/cron.weekly //每星期执?etc/cron.weekly内的脚本

    42 4 1 * * root run-parts /etc/cron.monthly //每月去执?etc/cron.monthly内的脚本

     

    大家注意"run-parts"这个参数了,如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是文件夹名了



    ]]>
    over partition by与group by 的区?/title><link>//www.ot7t.com.cn/lingy/archive/2009/06/29/284658.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Mon, 29 Jun 2009 11:04:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2009/06/29/284658.html</guid><description><![CDATA[<div id="message10586007" class="t_msgfont">各位好!<br /> over partition by ?group by 都是与统计类函数用,这两个有什么区别呢?br /> 目前我只知道一个这样的区别?br /> 比如有一张表saraly:CREATE TABLE SALARY AS SELECT 'A' NAME,10 DEPT,1000 SALARY FROM DUAL UNION ALL SELECT 'B',10,2000 FROM DUAL UNION ALL SELECT 'C' ,20,1500 FROM DUAL UNION ALL SELECT 'D',20,3000 FROM DUAL UNION ALL<br /> SELECT 'E',10,1000 FROM DUAL;<br /> NAME DEPT SALARY<br /> A         10     1000<br /> B         10     2000<br /> C         20     1500<br /> D         20     3000<br /> E         10     1000   <br /> 用over partition by 我就可以查询到每位员工本来的具体信息和它所在部门的总工资:<br /> select name,dept,salary,sum(salary) over (partition by dept) total_salary from salary;  <br /> name       dept         salary      tatal_salary<br /> A        10        1000        4000<br /> B        10        2000        4000<br /> E        10        1000        4000<br /> C        20        1500        4500<br /> D        20        3000        4500<br /> <br /> 用goup by 就没办法做到这点,只能查询到每个部门的总工资:<br /> select dept,sum(salary) total_salary from salary group by dept<br /> dept        total_salary<br /> 10        4000<br /> 20        4500<br /> 另外over partion by 还可以做到查询每位员工占部门总工资的百分比:<br /> select name,dept,salary,salary*100/sum(salary) over (partition by dept) percent from salary;<br /> <br /> name       dept         salary     percent<br /> A        10        1000        25<br /> B        10        2000        50<br /> E        10        1000        25<br /> C        20        1500        33.3333333333333<br /> D        20        3000        66.6666666666667<br /> 用group by 也没办法做到这个.不知道我的理解正不正确,请各位朋友指点,特别是over partition by 与group by 的更多区别请各位一起分享,谢谢?br /> <br /> 20        4500<br /> <br /> </div> <img src ="//www.ot7t.com.cn/lingy/aggbug/284658.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/lingy/" target="_blank">林光?/a> 2009-06-29 19:04 <a href="//www.ot7t.com.cn/lingy/archive/2009/06/29/284658.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle中的NULL(八?/title><link>//www.ot7t.com.cn/lingy/archive/2009/06/29/284559.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Mon, 29 Jun 2009 02:59:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2009/06/29/284559.html</guid><description><![CDATA[<p style="text-indent: 21pt"><span style="font-family: 宋体">最近在论坛上经常看到,很多人提出和<span lang="EN-US">NULL有关的问题。NULL其实是数据库中特有的类型,Oracle中很多容易出现的错误都是和NULL有关的?/span></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体">打算简单的总结一?span lang="EN-US">NULL的相关知识?/span></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体">这一篇描述一下在<span lang="EN-US">SQL和PLSQL中一些处理NULL的一些问题?/span></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">Oracle中的NULL(一):<a >//yangtingkun.itpub.net/post/468/244434</a></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">Oracle中的NULL(二):<a >//yangtingkun.itpub.net/post/468/245107</a></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">Oracle中的NULL(三):<a >//yangtingkun.itpub.net/post/468/245259</a></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">Oracle中的NULL(四):<a >//yangtingkun.itpub.net/post/468/245697</a></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">Oracle中的NULL(五):<a >//yangtingkun.itpub.net/post/468/247492</a></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">Oracle中的NULL(六):<a >//yangtingkun.itpub.net/post/468/251496</a></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">Oracle中的NULL(七):<a >//yangtingkun.itpub.net/post/468/258467</a></span></p> <p style="text-indent: 21pt"></p> <br /> <span style="display: none">8\![ Q!x;]$Yf0</span> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">NULL的最大的特点就是两个NULL是不相等的。如果用等号来判断两个NULL是否相等得到的结果一定是NULL。从唯一约束的特点也可以看到,对于建立了唯一约束的列,Oracle允许插入多个NULL值,这时因为Oracle不认为这些NULL是相等的?/span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> CREATE TABLE T (ID NUMBER, CONSTRAINT UN_T UNIQUE(ID));</font></span></p> <p><span style="font-size: 10.5pt"><font face="宋体">表已创建?/font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> INSERT INTO T VALUES (1);</font></span></p> <p><span style="font-size: 10.5pt"><font face="宋体">已创?span lang="EN-US"> 1 行?/span></font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> INSERT INTO T VALUES (1);<br /> <span style="display: none">| Pw6I)A#P,x_0</span>INSERT INTO T VALUES (1)<br /> <span style="display: none">+h:w|3~ N0</span>*<br /> <span style="display: none">LCB-P#b{$C0</span>ERROR 位于?1 ?<br /> <span style="display: none">f9i vJ Y%T0</span>ORA-00001: 违反唯一约束条件 (YANGTK.UN_T)</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><br /> <span style="display: none">&rSq _0P7QvYN0</span><font face="宋体">SQL> INSERT INTO T VALUES (NULL);</font></span></p> <p><span style="font-size: 10.5pt"><font face="宋体">已创?span lang="EN-US"> 1 行?/span></font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> INSERT INTO T VALUES (NULL);</font></span></p> <p><span style="font-size: 10.5pt"><font face="宋体">已创?span lang="EN-US"> 1 行?/span></font></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体">但是有的时候,<span lang="EN-US">Oracle会认为NULL是相同的,比如在GROUP BY和DISTINCT操作中。这个时候,Oracle会认为所有的NULL都是一类的?/span></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体">还有一种情况,就是?span lang="EN-US">DECODE函数中。如果表达式为DECODE(COL, NULL, 0, 1),那么如果COL的值为NULL,Oracle会认为这种情况与第二个参数的NULL值相匹配,会返回0。不过这里只是给人感觉NULL值是相等的,Oracle在实现DECODE函数的时候,仍然是通过IS NULL的方式进行的判断?/span></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体">对于大多数的常用函数来说,如果输入为<span lang="EN-US">NULL,则输出也是NULL。NVL、NVL2、DECODE和||操作是个例外。他们在输入参数为NULL的时候,结果可能不是NULL。不过归结其原因是因为,这些函数都有多个参数,当多个参数不全为NULL时,结果可能不是NULL,如果输入参数均为NULL,那么得到的输出结果也是NULL?/span></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体" lang="EN-US">NULL还有一个特点,就是一般聚集函数不会处理NULL值。不管是MAX、MIN、AVG还是SUM,这些聚集函数都不会处理NULL。注意这里说的不会处理NULL,是指聚集函数会直接忽略NULL值记录的存在。除非是聚集函数处理的列中包含的全部记录都是NULL,这种情况下,上面这些聚集函数会返回NULL值?/span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> DELETE T WHERE ID = 1;</font></span></p> <p><span style="font-size: 10.5pt"><font face="宋体">已删?span lang="EN-US"> 1 行?/span></font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> SELECT NVL(TO_CHAR(ID), 'NULL') FROM T;</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">NVL(TO_CHAR(ID),'NULL')<span style="display: none">ITPUB个人空间 Z,I Pa;o~)t/Tm7L</span><br /> ----------------------------------------<br /> <span style="display: none">L B d-f-A/o*c0</span>NULL<span style="display: none">ITPUB个人空间(C"}5Q5A#L#t</span><br /> NULL</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> SELECT MAX(ID) FROM T;</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">MAX(ID)<br /> <span style="display: none">!C Cs"Ys5|'`0</span>----------</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><br /> <span style="display: none">G_S.c d5mk)O#c0</span><font face="宋体">SQL> SELECT AVG(ID) FROM T;</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">AVG(ID)<span style="display: none">ITPUB个人空间*O.Ylk0OU(Oy4Dq$vQr</span><br /> ----------</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><br /> <span style="display: none">RFf+Lf{] y0</span><font face="宋体">SQL> INSERT INTO T VALUES (1);</font></span></p> <p><span style="font-size: 10.5pt"><font face="宋体">已创?span lang="EN-US"> 1 行?/span></font></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体">聚集函数中比较特殊的?span lang="EN-US">COUNT,第一个特殊点是COUNT不会返回NULL值,即使表中没有记录,或者COUNT(COL)中,COL列的记录全为NULL,COUNT也会返回0值而不是NULL。第二个特殊点就是COUNT(*)或COUNT(常量)的形式。这种形式使得COUNT可以计算包含NULL记录在内的记录总数?/span></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> SELECT COUNT(*), COUNT(1), COUNT('A'), COUNT(ID), COUNT(NULL) FROM T;</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">COUNT(*) COUNT(1) COUNT('A') COUNT(ID) COUNT(NULL)<span style="display: none">ITPUB个人空间-NNOH2z</span><br /> ---------- ---------- ---------- ---------- -----------<br /> <span style="display: none">;s t:O8t3o.y0t0</span> 3 3 3 1 0</font></span></p> <p style="text-indent: 21pt"><span style="font-family: 宋体">最后简单说一?span lang="EN-US">AVG,AVG(COL)等价于SUM(COL)/COUNT(COL),不等价于SUM(COL)/COUNT(*)?/span></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">SQL> SELECT AVG(ID), SUM(ID)/COUNT(ID), SUM(ID)/COUNT(*) FROM T;</font></span></p> <p><span style="font-size: 10.5pt" lang="EN-US"><font face="宋体">AVG(ID) SUM(ID)/COUNT(ID) SUM(ID)/COUNT(*)<br /> <span style="display: none">6~{9O*mL9C7c)p0</span>---------- ----------------- ----------------<br /> <span style="display: none">6@:[S'L&k\&V9{VR0</span> 1 1 .333333333</font></span></p> <p style="text-indent: 21pt"></p> <p style="text-indent: 21pt"></p> <br /> <img src ="//www.ot7t.com.cn/lingy/aggbug/284559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/lingy/" target="_blank">林光?/a> 2009-06-29 10:59 <a href="//www.ot7t.com.cn/lingy/archive/2009/06/29/284559.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>能否按照DECODE条件来COUNT???/title><link>//www.ot7t.com.cn/lingy/archive/2009/06/29/284556.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Mon, 29 Jun 2009 02:57:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2009/06/29/284556.html</guid><description><![CDATA[<p>表A   <br />       DW               WP             BJ   <br />       ----------------   <br />       A                 M1             Y   <br />       B                 M2             N   <br />       C                 M3             Y   <br />       D                 M1             Y   <br />     <br />   我向统计BJ?Y‘的DW有多少个和总DW多少个??  <br />     我用COUNT(DW),COUNT(DECODE(A.BJ,'Y',DW,0))   <br />   这样不行啊??  <br />   SQL应该怎么写啊???不要用兼套语句,这样太罗嗦?<span class="yibqv">问题点数?0、回复次数:3</span><a >Top</a> </p> <div class="tagad"></div> <h3><strong class="yibqv"><a class="anchor" name="r_34342834">1 ?/a>Visual_Studio_Net(打鼠英雄)<input class="user5" title="五级用户 该版得分小于等于5000分,大于2000? type="button" /></strong><span class="yibqv">回复?2006-04-22 20:08:49 得分 <em>15</em></span></h3> <p>SELECT   COUNT(DW),SUM(DECODE(BJ,'Y',1,0))   FROM   A<a >Top</a></p> <h3><strong class="yibqv"><a class="anchor" name="r_34342852">2 ?/a>chliang315()<input class="user3" title="三级用户 该版得分小于等于1000分,大于500? type="button" /></strong><span class="yibqv">回复?2006-04-22 20:11:32 得分 <em>35</em></span></h3> <p>可以?  <br />   COUNT(DW),COUNT(DECODE(A.BJ,'Y',DW,null))<a >Top</a></p> <h3><strong class="yibqv"><a class="anchor" name="r_34342979">3 ?/a>bbcboy(烦猪哥哥)<input class="user1" title="一级用?该版得分小于等于100? type="button" /></strong><span class="yibqv">回复?2006-04-22 20:30:58 得分 0 </span></h3> <p>两位都是好人啊!?  <br />   非常感谢!!   <br />   </p> <img src ="//www.ot7t.com.cn/lingy/aggbug/284556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/lingy/" target="_blank">林光?/a> 2009-06-29 10:57 <a href="//www.ot7t.com.cn/lingy/archive/2009/06/29/284556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ant+cactus+tomcat5.5容器内单元测?/title><link>//www.ot7t.com.cn/lingy/archive/2009/06/22/283575.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Mon, 22 Jun 2009 07:06:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2009/06/22/283575.html</guid><description><![CDATA[ 一、下载并解压缩cactus<br />   下载地址为//Java.chinaitlab.com/tools/45970.Html 。将cactus的lib目录下的cactus-ant-1.7.1.jar复制到ant的lib目录?br />   二、配置cactus<br />   cactus的配置很简单,新建一个cactus.properties文件,并把它放在ant脚本中的cactus任务的classpath下,文件中包括如下内?br />   cactus.sysproperties=cactus.contextURL<br highlighted="1" />   #cactus-sample-servlet-cactified就是你的测试应用所在路径,8080?zmkey style="border-bottom: #ff6c00 2px dotted; float: none; cursor: pointer; font-weight: bold; margin-right: 3px; cssfloat: none" class="zoomino-searchword" offset="52" path="body > div:eq(0) > div:eq(3) > table:eq(2) > tbody:eq(0) > tr:eq(0) > td:eq(0) > div:eq(0) > #content:eq(0) > br:eq(4)" anchorType="previous" jQuery1245654007453="6">端口?img style="border-bottom: medium none; border-left: medium none; padding-bottom: 0px; margin: 0px; padding-left: 0px; width: 12px; padding-right: 0px; display: inline; background-position: -18px -23px; float: none; height: 14px; border-top: medium none; border-right: medium none; padding-top: 0px; cssfloat: none" class="zoominoBgImage" src="//static.zoomino.cn/static-ox/images/blank.gif" width="1" height="1" alt="" /></zmkey><br />   cactus.contextURL = //localhost:8080/cactus-sample-servlet-cactified<br />   cactus.servletReDirectorName = ServletRedirector<br />   cactus.jspRedirectorName = JspRedirector<br />   cactus.filterRedirectorName = FilterRedirector <br />   具体的做法结合ant脚本再进一步解释?br />   三、运行ant脚本<br />    ant脚本主要执行以下任务<br />   1、设定classpath<br />   <path id="project.classpath"><br />    <fileset dir="${lib.dir}"><br />    <include name="*.jar"/><br />    </fileset><br />    <!-- cactus.properties文件就需要放在lib.dir所对应的路径中 --><br />    <pathelement location="${lib.dir}"/><br />    <pathelement location="${tomcat.home}/common/lib/jsp-api.jar"/><br />    <pathelement location="${tomcat.home}/common/lib/servlet-api.jar"/><br />    </path><br />   2、定义相关任?br />   <taskdef resource="cactus.tasks" classpathref="project.classpath"/><br />    <taskdef name="runservertests" classname="org.apache.cactus.integration.ant.RunServerTestsTask"><br />    <classpath><br />    <path refid="project.classpath"/><br />    </classpath><br />    </taskdef><br />   3、编译应用的类文件和测试的类文件<br />   4、打包整个应用为war文件<br />   需要注重的是,不仅要打包应用类,测试类也要打包<br />   <target name="war" depends="compile.java"<br />    description="Generate the runtime war"><br />    <war warfile="${target.dir}/${project.name}.war"<br />    webXML="${src.webapp.dir}/WEB-INF/web.xml"><br />    <fileset dir="${src.webapp.dir}"><br />    <exclude name="cactus-report.xsl"/><br />    <exclude name="WEB-INF/cactus-web.xml"/><br />    <exclude name="WEB-INF/web.xml"/><br />    </fileset><br />    <classes dir="${target.classes.java.dir}"/><br />    <!-- 别忘了打包测试类 --><br />    <classes dir="${target.classes.test.dir}"/><br />    <!-- 别忘了打包各种相关的jar文件 --><br />    < lib dir="project.classpath"/><br />    </war><br />    </target><br />   5、在应用的web.xml文件中添加测试所需的各种映?br />   cactus提供了两个task来完成这个工作,CactifyWar和WebXmlMerge?br />   CactifyWar的功能是自动在已经打包的应用的web.xml文件中添加所需的映射。WebXmlMerge是提供合并两个web.xml文件的功能?br />   <target name="test.prepare"<br />    depends="war, compile.cactus, test.prepare.logging"><br />    <!-- Cactify the web-app archive --><br />    <cactifywar srcfile="${target.dir}/${project.name}.war"<br />    destfile="${tomcat.home}/webapps/${project.name}-cactified.war"<br />    ><br />    <classes dir="${target.classes.java.dir}"/><br />    <classes dir="${target.classes.test.dir}"/><br />    <lib dir="project.classpath"/><br />    </cactifywar><br />   </target><br />   6、运行测?br />   cactus提供了cactus和RunServerTests两个task来运行测试?br highlighted="1" />   "cactus" task是通过复制容器服务器的最小文件并运行来运行测试,因此需要制定容器服务器的类型,启动速度稍快点,另外配置比较方便,但是无法测试象tomcat<zmkey style="border-bottom: #ff6c00 2px dotted; float: none; cursor: pointer; font-weight: bold; margin-right: 3px; cssfloat: none" class="zoomino-searchword" offset="84" path="body > div:eq(0) > div:eq(3) > table:eq(2) > tbody:eq(0) > tr:eq(0) > td:eq(0) > div:eq(0) > #content:eq(0) > br:eq(64)" anchorType="previous" jQuery1245654007453="7">连接?img style="border-bottom: medium none; border-left: medium none; padding-bottom: 0px; margin: 0px; padding-left: 0px; width: 12px; padding-right: 0px; display: inline; background-position: -18px -23px; float: none; height: 14px; border-top: medium none; border-right: medium none; padding-top: 0px; cssfloat: none" class="zoominoBgImage" src="//static.zoomino.cn/static-ox/images/blank.gif" width="1" height="1" alt="" /></zmkey>等资源。另外对tomcat5.5的支持也不好?br />   "RunServerTests"是通过直接启动容器服务起来运行测试,因此速度稍慢,且配置较麻烦,但能测试各种资源?br />   <target name="test" depends="test.prepare"<br />    description="Run tests on Tomcat "><br />    <!-- Start the servlet engine, wait for it to be started, run the<br />    unit tests, stop the servlet engine, wait for it to be stopped.<br />    The servlet engine is stopped if the tests fail for any reason --><br />    <!-- 8080是服务器的端口号?{project.name}-cactified是项目的路径,和上一步的cactifywar 的destfile相对?--><br />    <runservertests<br />    testURL="//localhost:8080/${project.name}-cactified/ServletRedirector?Cactus_Service=RUN_TEST"<br />    startTarget="_StartTomcat"<br />    stopTarget="_StopTomcat"<br />    testTarget="_Test"/><br />    </target><br />   <!-- _Test就是一个普通的junit任务 --><br />    <target name="_Test"><br />    <junit printsummary="yes" fork="yes"><br />    <classpath><br />    <path refid="project.classpath"/><br />    <pathelement location="${target.classes.java.dir}"/><br />    <pathelement location="${target.classes.test.dir}"/><br />    </classpath><br />    <formatter type="brief" usefile="false"/><br />    <formatter type="xml"/><br />    <batchtest><br />    <fileset dir="${src.test.dir}"><br />    <!-- Due to some Cactus synchronization bug, the 'unit' tests need<br />    to run before the 'sample' tests --><br />    <include name="**/Test*.java"/><br />    <exclude name="**/Test*All.java"/><br />    </fileset><br />    </batchtest><br />    </junit><br />    </target><br />   文章来源: baike.duba.net <img src ="//www.ot7t.com.cn/lingy/aggbug/283575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/lingy/" target="_blank">林光?/a> 2009-06-22 15:06 <a href="//www.ot7t.com.cn/lingy/archive/2009/06/22/283575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>给servlet写单元测试的总结 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/06/22/283551.html林光?/dc:creator>林光?/author>Mon, 22 Jun 2009 05:39:00 GMT//www.ot7t.com.cn/lingy/archive/2009/06/22/283551.html 给servlet写单元测试的总结收藏
    servlet的测试一般来说需要容器的支持,不是像通常的java类的junit测试一样简单,
     
    下面通过对HelloWorld代码的测试阐述了几种servlet测试方法?br />  
    被测试的HelloWorld类的代码如下?br />  
    /**
     * 被测试的servlet
     */

    import java.io.IOException;
     
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.cactus.WebRequest;
    import org.apache.cactus.server.HttpServletRequestWrapper;
     
    public class HelloWorld extends HttpServlet{
     
     public void saveToSession(HttpServletRequest request) {

             request.getSession().setAttribute("testAttribute",request.getParameter("testparam"));

     }
     
     public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException{

             String username=request.getParameter("username");

             response.getWriter().write(username+":Hello World!");
           
     }
     
     public boolean authenticate(){
            
            return true;
     
     }

    }
     
    以HelloWorld为例,我总结了Servlet的多种测试方法如下:
     
    一.使用HttpUnit测试
     
    import com.meterware.httpunit.GetMethodWebRequest;
    import com.meterware.httpunit.WebRequest;
    import com.meterware.httpunit.WebResponse;
    import com.meterware.servletunit.InvocationContext;
    import com.meterware.servletunit.ServletRunner;
    import com.meterware.servletunit.ServletUnitClient;
    import junit.framework.Assert;
    import junit.framework.TestCase;
     
    public class HttpUnitTestHelloWorld extends TestCase {
     
     protected void setUp() throws Exception {
      super.setUp();
     }
     
     protected void tearDown() throws Exception {
      super.tearDown();
     }
     
     public void testHelloWorld() {
     
      try {

       // 创建Servlet的运行环?/p>

       ServletRunner sr = new ServletRunner();

       // 向环境中注册Servlet

       sr.registerServlet("HelloWorld", HelloWorld.class.getName());
     
       // 创建访问Servlet的客户端

       ServletUnitClient sc = sr.newClient();

       // 发送请?/p>

       WebRequest request = new GetMethodWebRequest("//localhost/HelloWorld");
       request.setParameter("username", "testuser");

       InvocationContext ic = sc.newInvocation(request);

       HelloWorld is = (HelloWorld) ic.getServlet();
     
       // 测试servlet的某个方?/p>

       Assert.assertTrue(is.authenticate());

       // 获得模拟服务器的信息

       WebResponse response = sc.getResponse(request);

       // 断言

       Assert.assertTrue(response.getText().equals("testuser:Hello World!"));

      } catch (Exception e) {

       e.printStackTrace();

      }

     }
     
    }
     
    上述例子其实是junit的一个测试例子,在其中使用了httpunit模拟的servlet环境,使用上述方法测试
     
    servlet可以脱离容器,容易把该测试写入ant或maven脚本,让测试进行?br />  
    httpunit网址://httpunit.sourceforge.net/
     
    使用该种方法测试的弱点就是:如果要使用request(response)的setCharercterEncoding方法时,测试会出现一些问?
     
    而且httpunit在测试servlet行为时,采用的是完全模拟浏览器,有时测试比较难写?br />  
    ?使用cactus测试
     
    /**
     * cactus测试servlet的例?br />  * 必须要有tomcat的支?br />  *
     */
     
    import junit.framework.Test;
    import junit.framework.TestSuite;
    import org.apache.cactus.ServletTestCase;
    import org.apache.cactus.WebRequest;
    import org.apache.cactus.WebResponse;
    public class CactusHelloWorld extends ServletTestCase{
     
         HelloWorld servlet;
         public CactusHelloWorld(String theName) {
             super(theName);
         }
     
         protected void setUp() throws Exception {
             super.setUp();
             servlet = new HelloWorld();
         }
     
         protected void tearDown() throws Exception {
             super.tearDown();
         }
     
         /**
          * 测试方法测试参数在此设置
          *
          * @param webrequest
          */
     
         public void beginSaveToSessionOK(WebRequest request) {
             request.addParameter("testparam", "it works!");
         }
        
         /**
          * 测试方法测试参数在此设置
          *
          * @param webrequest
          */
     
         public void beginDoGet(WebRequest request) {
             request.addParameter("username", "testuser");
         }
     
         /**
          * 调用servlet的测试方?br />       * 
          */

         public void testSaveToSessionOK() {
             servlet.saveToSession(request);
             assertEquals("it works!", session.getAttribute("testAttribute"));
         }
     
         public void testDoGet() {
             try {
                 servlet.doGet(request, response);
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     
         /**
          * 此方法可以判断测试方法的输出,会传递测试方法的reponse给end***,并且格式化为cactus
          * 的WebResponse或者可以跟httpunit集成,格式化为httpunit的response
          *
          * @param response
          */

         public void endDoGet(WebResponse response) {
             String content;        
             content = response.getText();
             assertEquals("testuser:Hello World!", content);
         }
    }
     
    cactus具备丰富灵活的测试功能,如要测试doGet方法,分为beginDoGet(模拟测试参数设置)、DoGet(执行测试)、endDoGet(状态结果验?
     
    相比httpunit来说,写测试更为容易,测试servlet更为专业,流程更为清晰,但是cactus需要容器支持,使得测试不可以自动进行,但是
     
    如果使用一个嵌入式的容器,测试就可以自动了?br />  
    cactus是一个servlet和jsp的测试框?//jakarta.apache.org/cactus/getting_started.html
     
    ?使用Jetty作为嵌入式容器测试servlet.
     
    /**
     * 一个关于嵌入式jetty测试的例子,jetty作为stubs的一个例?br />  *
     */
    package com.easyjf.testexample;
     
    import org.mortbay.jetty.Connector;
    import org.mortbay.jetty.Server;
    import org.mortbay.jetty.bio.SocketConnector;
    import org.mortbay.jetty.servlet.ServletHandler;
     
    import com.meterware.httpunit.WebClient;
    import com.meterware.httpunit.WebConversation;
    import com.meterware.httpunit.WebResponse;
     
    import junit.framework.Assert;
    import junit.framework.TestCase;
     
    public class JettySampleTest extends TestCase {
     
     Server server;
     protected void setUp() throws Exception {
          //通过代码设置并启动一个服务器,该服务器是servlet的测试容?br />       super.setUp();
          server = new Server();
          Connector connector=new SocketConnector();
          connector.setPort(80);
          server.setConnectors(new Connector[]{connector});
          ServletHandler handler=new ServletHandler();
          server.setHandler(handler);
          handler.addServletWithMapping("HelloWorld", "/");
          server.start();
     }
     
     protected void tearDown() throws Exception {
      super.tearDown();
      server.stop();
     }
     
     public void testHellWorld() {
      try {
       WebConversation wc = new WebConversation();
       WebResponse web = wc.getResponse("//127.0.0.1/HelloWorld");
       String result=web.getText();
       Assert.assertEquals(result,"it works!");
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
    }
     
    可以发现,jetty可以充当一个servlet的容器,方便的是,jetty支持嵌入式服务,即可以通过代码来启动,
     
    所以要写自动测试的例子很方便,可以结合httpunit或者cactus进行servlet测试?br />  
    jetty主页://docs.codehaus.org/display/JETTY/Embedding+Jetty


    ?使用mock对象,此处使用easymock
     
    import java.io.PrintWriter;
    import java.io.Writer;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    import junit.framework.Assert;
    import junit.framework.TestCase;
    import static org.easymock.EasyMock.*;
    public class MockTestServlet extends TestCase {
     
        public void testService() throws Exception {

            System.out.println("service");

            HttpServletRequest request = createMock(HttpServletRequest.class);

            HttpServletResponse response = createMock(HttpServletResponse.class);

            //Creating the ServletConfig mock here

            ServletConfig servletConfig = createMock(ServletConfig.class);

            //Creating the ServletContext mock here

            ServletContext servletContext = createMock(ServletContext.class);
           
            //Create the target object 
         
            HelloWorld4 instance = new HelloWorld();

            //初始化servlet,一般由容器承担,一般调用servletConfig作为参数初始化,此处模拟容器行为

            instance.init(servletConfig);
     
            //在某些方法被调用时设置期望的返回值,如下这样就不会去实际调用servletConfig的getServletContext方法,而是直接返回
     
            //servletContext,由于servletConfig是mock出来的,所以可以完全控制?/p>

            expect(servletConfig.getServletContext()).andReturn(servletContext).anyTimes();

            expect(request.getParameter("username")).andReturn("testuser");

            PrintWriter pw=new PrintWriter(System.out,true);

            expect(response.getWriter()).andReturn(pw).anyTimes();
           
            //以上均是录制,下面为重放,该种机制为easymock测试机制,要理解请看easymock测试的一些资?br />         replay(request);
            replay(response);
            replay(servletConfig);
            replay(servletContext);
     
            instance.doGet(request, response);

            pw.flush();
           
     
            //验证结果是否预期,如果预期,则会在pw上写出testuser.
            verify(request);
            verify(response);
            verify(servletConfig);
            verify(servletContext);
       }
    }
     
    mock测试注重行为,mock对象其实都是模拟的对象,方法一般直接给出一个返回值,没有具体的对象逻辑,mock对象
     
    是用来帮助测试要测试的类的。比如要测试servlet的内部行为,又不想要容器等环境,就可以采用mock测试?br />  
    easymock是mock测试的一个框架://www.easymock.org/
     
    发表?@ 2007?2?0?22:13:00|评论(2)

    新一? 设计模式之创建模?| 旧一? 服务定位器模?service locator)wldandanpig 发表?007??4?10:09:40  IP:举报
    请问楼主
    public String saveInfo()
    {
    String reqInfo = request.getParameter("reqInfo");
    String sessInfo = (String)request.getSession().getAttribute("sessInfo");

    request.setAttribute("reqInfo" , "response:"+reqInfo);
    request.getSession().setAttribute("sessInfo", "response:"+reqInfo);

    return "SUCCESS";
    }
    这个方法怎么测试啊cz_hyf 发表?007??4?17:20:23  IP:举报
    如果用httpunit的话

    public void testHelloWorld() {

    try {

    // 创建Servlet的运行环?/p>

    ServletRunner sr = new ServletRunner();

    // 向环境中注册Servlet

    sr.registerServlet("HelloWorld", HelloWorld.class.getName());

    // 创建访问Servlet的客户端

    ServletUnitClient sc = sr.newClient();

    // 发送请?/p>

    WebRequest request = new GetMethodWebRequest("//localhost/HelloWorld");
    request.setParameter("reqInfo", "......");

    InvocationContext ic = sc.newInvocation(request);

    HelloWorld is = (HelloWorld) ic.getServlet();

    // 测试servlet的某个方?/p>

    Assert.assertEquals(is.saveInfo,"SUCCESS");

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    如果还不放心,不妨把request和request.session中的值取出来看看是否是你放进去的


    本文来自CSDN博客,转载请标明出处://blog.csdn.net/cz_hyf/archive/2007/02/10/1507211.aspx



    ]]>
    oracle trunc()函数的用?/title><link>//www.ot7t.com.cn/lingy/archive/2009/06/19/283162.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Fri, 19 Jun 2009 01:39:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2009/06/19/283162.html</guid><description><![CDATA[<span class="bold"><span class="smalltxt">TRUNC()函數分兩?img src="//blog.csdn.net/Emoticons/tongue_smile.gif" alt="" /><br /> <br /> </span></span>1.TRUNC(for dates)<br />         TRUNC函数为指定元素而截去的日期值?br />         其具体的语法格式如下?br />         TRUNC(date[,fmt]?br />         其中?br />         date        一个日期?br />         fmt                日期格式,该日期将由指定的元素格式所截去。忽略它则由最近的日期截去<br />         下面是该函数的使用情况:<br />         TRUNC(TO_DATE(’24-Nov-1999 08:00 pm’,’dd-mon-yyyy hh:mi am’)?br />                 =’24-Nov-1999 12:00:00 am’<br />         TRUNC(TO_DATE(’24-Nov-1999 08:37 pm’,’dd-mon-yyyy hh:mi am’,’hh’)?nbsp;       =’24-Nov-1999 08:00:00 am’<br /> <br /> 2.TRUNC(for number)<br />         TRUNC函数返回处理后的数值,其工作机制与ROUND函数极为类似,只是该函数不对指定小数前或后的部分做相应舍入选择处理,而统统截去?br />         其具体的语法格式如下<br />         TRUNC(number[,decimals]?br />         其中?br />         number        待做截取处理的数?br />         decimals        指明需保留小数点后面的位数。可选项,忽略它则截去所有的小数部分<br />         下面是该函数的使用情况:<br />         TRUNC?9.985??89.98<br />         TRUNC?9.985?89<br />         TRUNC?9.985?1?80<br />         注意:第二个参数可以为负数,表示为小数点左边指定位数后面的部分截去,即均?记?<br /> <img src ="//www.ot7t.com.cn/lingy/aggbug/283162.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/lingy/" target="_blank">林光?/a> 2009-06-19 09:39 <a href="//www.ot7t.com.cn/lingy/archive/2009/06/19/283162.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle merge into 的用法详?实例 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/06/18/283070.html林光?/dc:creator>林光?/author>Thu, 18 Jun 2009 08:10:00 GMT//www.ot7t.com.cn/lingy/archive/2009/06/18/283070.htmloracle merge into 的用法详?实例
    oracle merge into 的用法详?实例

    作用:merge into 解决用B表跟新A表数据,如果A表中没有,则把B表的数据插入A表;

    语法?/p>

    MERGE INTO [your table-name] [rename your table here]

    USING ( [write your query here] )[rename your query-sql and using just like a table]

    ON ([conditional expression here] AND [...]...)

    WHEN MATHED THEN [here you can execute some update sql or something else ]

    WHEN NOT MATHED THEN [execute something else here ! ]

    -------------------------------------实例-----------------------------------------------------------------

    merge into tfa_alarm_act_nms a
    using (select FP0,FP1,FP2,FP3,REDEFINE_SEVERITY
    from tfa_alarm_status) b
    on (a.fp0=b.fp0 and a.fp1=b.fp1 and a.fp2=b.fp2 and a.fp3=b.fp3)
    when matched then update set a.redefine_severity=b.redefine_severity
    when not matched then insert (a.fp0,a.fp1,a.fp2,a.fp3,a.org_severity,a.redefine_severity,a.event_time
    ,a.int_id)
    values (b.fp0,b.fp1,b.fp2,b.fp3,b.REDEFINE_SEVERITY,b.redefine_severity,sysdate,7777778);

    作用:利用表 tfa_alarm_status跟新?font color="#0000ff">tfa_alarm_act_nms 的b.redefine_severity?/font>条件?font color="#0000ff">a.fp0=b.fp0 and a.fp1=b.fp1 and a.fp2=b.fp2 and a.fp3=b.fp3?/font>如果tfa_alarm_act_nms表中没有该条件的数据就插入?/font>

    如果你的数据量很大,此sql效率非常高?/p>



    ]]>
    解析:怎样使用Oracle的DECODE()函数 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/06/18/283067.html林光?/dc:creator>林光?/author>Thu, 18 Jun 2009 08:08:00 GMT//www.ot7t.com.cn/lingy/archive/2009/06/18/283067.html 

    DECODE()函数,它将输入数值与函数中的参数列表相比较,根据输入值返回一个对应值。函数的参数列表是由若干数值及其对应结果值组成的若干序偶形式。当然,如果未能与任何一个实参序偶匹配成功,则函数也有默认的返回值?

    区别于SQL的其它函数,DECODE函数还能识别和操作空值?

    语法:DECODE(control_value,value1,result1[,value2,result2…][,default_result]);

    control _value试图处理的数值。DECODE函数将该数值与后面的一系列的偶序相比较,以决定返回值?

    value1是一组成序偶的数值。如果输入数值与之匹配成功,则相应的结果将被返回。对应一个空的返回值,可以使用关键字NULL于之对应

    result1 是一组成序偶的结果值?

    default_result 未能与任何一个值匹配时,函数返回的默认值?

    例如?

    selectdecode( x , 1 , ‘x is 1 ’, 2 , ‘x is 2 ’, ‘others’) from dual

    当x等于1时,则返?#8216;x is 1’?

    当x等于2时,则返?#8216;x is 2’?

    否则,返回others’?

    需要,比较2个值的时候,可以配合SIGN()函数一起使用?

    SELECT DECODE( SIGN(5 -6), 1 'Is Positive', -1, 'Is Nagative', 'Is Zero')

    同样,也可以用CASE实现?

    SELECT CASE SIGN(5 - 6)
                WHEN  1  THEN  'Is Positive'
                WHEN -1 THEN  'Is Nagative'
                ELSE 'Is Zero' END
                FROM DUAL

    此外,还可以在Order by中使用Decode?

    例如:表table_subject,有subject_name列。要求按照:语、数、外的顺序进行排序。这时,就可以非常轻松的使用Decode完成要求了?

    select * from table_subject order by decode(subject_name, '语文', 1, '数学', 2, , '外语',3)(责任编辑:卢兆林)



    ]]>
    怎样从一个过程返回一个结果集 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/lingy/archive/2009/06/18/283045.html林光?/dc:creator>林光?/author>Thu, 18 Jun 2009 06:22:00 GMT//www.ot7t.com.cn/lingy/archive/2009/06/18/283045.htmlcreate or replace procedure p_stu_lst(result out sys_refcursor) is
    BEGIN
       OPEN RESULT FOR SELECT * FROM test;
    end p_stu_lst;
    SQL> select * from test;

    NAME       KM                 CJ
    ---------- ---------- ----------
    张三       语文               80
    张三       数学               86
    张三       英语               75
    李四       语文               78
    李四       数学               85
    李四       英语               78
    李四       物理               90

    已选择7行?br />
    SQL> exec p_stu_lst(:aaa);

    PL/SQL 过程已成功完成?br />
    SQL> print aaa

    NAME       KM                 CJ
    ---------- ---------- ----------
    张三       语文               80
    张三       数学               86
    张三       英语               75
    李四       语文               78
    李四       数学               85
    李四       英语               78
    李四       物理               90

    已选择7行?/div>

    ]]>
    Oracle PL/SQL游标的学?/title><link>//www.ot7t.com.cn/lingy/archive/2009/06/18/283042.html</link><dc:creator>林光?/dc:creator><author>林光?/author><pubDate>Thu, 18 Jun 2009 06:11:00 GMT</pubDate><guid>//www.ot7t.com.cn/lingy/archive/2009/06/18/283042.html</guid><description><![CDATA[<div class="adgg"><a target="_blank">被过滤广?/a></div> <strong class="yibqv">一 游标是什?/strong> <br /> <br /> 游标字面理解就是游动的光标?<br /> <br /> 用数据库语言来描述:游标是映射在结果集中一行数据上的位置实体,有了游标,用户就可以访问结果集中的任意一行数据了,将游标放置到某行后,即可对该行数据进行操作,例如提取当前行的数据等?<br /> <br /> <strong class="yibqv">?游标的分?/strong> <br /> <br /> 显式游标和隐式游?<br /> <br /> 显式游标的使用需?步: <br /> <br /> 1. 声明游标 <br /> <br /> <ccid_nobr> <table border="1" cellspacing="0" bordercolorlight="black" bordercolordark="#ffffff" cellpadding="2" width="400" align="center"> <tbody> <tr> <td style="font-size: 9pt" class="code" bgcolor="#e6e6e6"> <pre><ccid_code>CURSOR mycur(vartype number) is select emp_no,emp_zc from cus_emp_basic where com_no = vartype;</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr><br /> <br /> 2. 打开游标 <br /> <br /> open mycur(000627) <br /> <br /> 注:000627是参?<br /> <br /> 3. 读取数据 <br /> <br /> fetch mycur into varno, varprice; <br /> <br /> 4. 关闭游标 <br /> <br /> close mycur; <br /> <br /> <strong class="yibqv">?游标的属?/strong> <br /> <br /> oracle 游标?个属性:%ISOPEN?FOUND?NOTFOUND?ROWCOUNT?<br /> <br /> %ISOPEN判断游标是否被打开,如果打开%ISOPEN等于true,否则等于false?<br /> <br /> %FOUND %NOTFOUND判断游标所在的行是否有效,如果有效,则%FOUNDD等于true,否则等于false?<br /> <br /> %ROWCOUNT返回当前位置为止游标读取的记录行数?<br /> <br /> <strong class="yibqv">?示例</strong> <br /> <br /> <ccid_nobr> <table border="1" cellspacing="0" bordercolorlight="black" bordercolordark="#ffffff" cellpadding="2" width="400" align="center"> <tbody> <tr> <td style="font-size: 9pt" class="code" bgcolor="#e6e6e6"> <pre><ccid_code>set serveroutput on; declare varno varchar2(20); varprice varchar2(20); CURSOR mycur(vartype number) is select emp_no,emp_zc from cus_emp_basic where com_no = vartype; begin if mycur%isopen = false then open mycur(000627); end if; fetch mycur into varno,varprice; while mycur%found loop dbms_output.put_line(varno||','||varprice); if mycur%rowcount=2 then exit; end if; fetch mycur into varno,varprice; end loop; close mycur; end;</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr><br /> <br /> PL/SQL记录的结构和C语言中的结构体类似,是由一组数据项构成的逻辑单元?<br /> <br /> PL/SQL记录并不保存在数据库中,它与变量一样,保存在内存空间中,在使用记录时候,要首先定义记录结构,然后声明记录变量。可以把PL/SQL记录看作是一个用户自定义的数据类型?<br /> <br /> <ccid_nobr> <table border="1" cellspacing="0" bordercolorlight="black" bordercolordark="#ffffff" cellpadding="2" width="400" align="center"> <tbody> <tr> <td style="font-size: 9pt" class="code" bgcolor="#e6e6e6"> <pre><ccid_code>set serveroutput on; declare type person is record ( empno cus_emp_basic.emp_no%type, empzc cus_emp_basic.emp_zc%type); person1 person; cursor mycur(vartype number)is select emp_no,emp_zc from cus_emp_basic where com_no=vartype; begin if mycur%isopen = false then open mycur(000627); end if; loop fetch mycur into person1; exit when mycur%notfound; dbms_output.put_line('雇员编号:'||person1.empno||',地址:'||person1.empzc); end loop; close mycur; end;</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr><br /> <br /> 典型游标for 循环 <br /> <br /> 游标for循环示显示游标的一种快捷使用方式,它使用for循环依次读取结果集中的行数据,当form循环开始时,游标自动打开(不需要open),每循环一次系统自动读取游标当前行的数据(不需要fetch),当退出for循环时,游标被自动关闭(不需要使用close)。使用游标for循环的时候不能使用open语句,fetch语句和close语句,否则会产生错误?<br /> <br /> <ccid_nobr> <table border="1" cellspacing="0" bordercolorlight="black" bordercolordark="#ffffff" cellpadding="2" width="400" align="center"> <tbody> <tr> <td style="font-size: 9pt" class="code" bgcolor="#e6e6e6"> <pre><ccid_code>set serveroutput on; declare cursor mycur(vartype number)is select emp_no,emp_zc from cus_emp_basic where com_no=vartype; begin for person in mycur(000627) loop dbms_output.put_line('雇员编号:'||person.emp_no||',地址:'||person.emp_zc); end loop; end;</ccid_code></pre> </td> </tr> </tbody> </table> </ccid_nobr><br /> <img src ="//www.ot7t.com.cn/lingy/aggbug/283042.html" width = "1" height = "1" /><br><br><div align=right><a href="//www.ot7t.com.cn/" title="四川福利彩票快乐12">四川福利彩票快乐12</a></div>]]></description></item></channel></rss> <script>(function(){ var src = (document.location.protocol == "http:") ? "//js.passport.qihucdn.com/11.0.1.js?f7a6bc378844a5df707c414e6b6fea33":"https://jspassport.ssl.qhimg.com/11.0.1.js?f7a6bc378844a5df707c414e6b6fea33"; document.write('<script src="' + src + '" id="sozz"><\/script>'); })(); </script>