针对有网友说看不见文章内容, 现提示如下: 点击每一个标题行任一地方都会展开和隐藏此文章内容(不要点击标题). 目前展开隐藏功能只支持IE浏览器,虽然可以改成支持FF浏览器,不过现在一直没时间去弄,等有时间再修改了。 |
blog名称:乱闪Blog 日志总数:267 评论数量:1618 留言数量:-26 访问次数:2654435 建立时间:2005年1月1日 |
|

| |
IE6.0打印机制解析
|
来源: 未知
作者: yzsind
更新日期: [2005-03-12]
摘自 http://www.cjsdn.net/post/view?bid=29&id=98728&sty=1&tpg=1&age=0
网页打印,可以通过浏览器的"打印"功能实现,但"打印模板"机制,却是 IE 5.5 /6.0 以及 Netscape 6.0 所独有的;准确一点, IE 5.5 只是一个机制雏形,在 IE 6.0 中才得以完全体现。IE 6.0 的打印功能模块,在精确控制页面边界,文本间隔,以及打印的统一性上,功能更为完备。 通过创建打印模板,你可以精确控制:
网页打印及预览时的页面风格与内容编排风格; 打印属性,如自动为打印的页面添加卷标或编号; 精确控制打印预览界面的各个元素与变量。
通过打印模板,你可以:
自动为所有打印页面添加固定内容,如公司标识,版权申明,或者指定广告; 自定义页面标头与尾注等元素,比如页码或卷标; 指定打印历史与任务; 书本化奇偶分页映射打印......
打印模板机制是建立在动态 HTML 语言基础上的,涉及到主要两个行为:DeviceRect, LayoutRect ,下面我们就这两个行为深入地探讨 IE 6.0 的打印机制。
另外需要说明的是,DHTML (动态超文本标识语言)的行为跟其他语言的"行为"一样,都是一种应用编程接口,初始状态下有自己的默认属性,在一定的事件下,由用户决定调用其承认的功能模块,从而产生相对应的"行为"。而且,"行为"可以自己编写,不过得以".htc"为其扩展名以供调用。
一.DeviceRect ,定义打印总体风格:
打印总体风格,包括为打印页面添加如公司标识的固定内容(网页上不一定有,只体现在打印纸张上或预览页面上,后同);打印页面的颜色风格;打印页面的边缘属性或图案;等等。
在进行 DeviceRect 引用前,先得确定页面风格,方法是用<style>进行设置。
例一:我们来定制如下的打印模板 8.5 inch 宽 11 inch 高 黄色背景 1 pixel 宽的黑色实心左边界 1 pixel 宽的黑色实心上边界 4 pixels 宽的黑色实心右边界 4 pixels 宽的黑色实心下边界 所有边界与纸张边缘为 10 pixels 的距离
现在我们用 style 进行设定,假设这个 style 名为 Mystyle1:
<style TYPE="text/css"> .Mystyle1 { width:8.5in; height:11in; background:#FFFF99; border-left:1 solid black; border-top:1 solid black; border-right:4 solid black; border-bottom:4 solid black; margin:10px; } </style>
下面我们给出 DeviceRect 引用的完全页面代码,
<HTML XMLNS:IE> <HEAD> <?IMPORT NAMESPACE="IE" IMPLEMENTATION="#default"> <style TYPE="text/css"> .Mystyle1 { width:8.5in; height:11in; background:#FFFF99; border-left:1 solid black; border-top:1 solid black; border-right:4 solid black; border-bottom:4 solid black; margin:10px; } </style> </HEAD> <BODY>
<IE:DEVICERECT ID="page1" CLASS="Mystyle1" MEDIA="print"> </IE:DEVICERECT>
<IE:DEVICERECT ID="page2" CLASS="Mystyle1" MEDIA="print"> </IE:DEVICERECT>
</BODY> </HTML>
在这个页面中,共进行了两个 DeviceRect 引用。作为一种规则,每一个单独的打印页面,必须有一个相对应的 DeviceRect 标记,如果有 1000 个页面,那就得有 1000 个 DeviceRect 标记!吓住了?别担心,后面我们会教你一个方法,让所有的 DeviceRect 标记自动完成!
在上面的代码中,ID 是标志属性,不同的页面必须有自己不同的标识;CLASS 引用了 style 属性;MEDIA 属性则指明了本页面的最终用途是进行打印;<?IMPORT NAMESPACE="IE" IMPLEMENTATION="#default">这句话则是指输入默认的行为,它们分别是 DeviceRect, LayoutRect。
二.LayoutRect ,定义页面内容风格:
跟 DeviceRect 一样,不同的页面,要进行 LayoutRect 引用时都需要添加 LayoutRect 标记,其智能添加方法将在后面介绍; LayoutRect 与 DeviceRect 如果在同一个页面中同时出现,则前者需放在后者之内;另外, LayoutRect 对内容风格的设定,也通过 style 得以实现。
例二:我们来定制如下的内容风格的打印模板:
5.5 inches 宽 8 inches 高 与打印纸张边缘,四边保持 1 inch 的宽度(加上页面本身的边缘宽度,为实际的打印边缘宽度) 白色背景 1 inch 宽的虚线边界
先定制名为 contentstyle 的风格:
<style TYPE="text/css"> .contentstyle { width:5.5in; height:8in; margin:1in; background:white; border:1 dashed gray; } </style>
然后下面是进行引用的完整网页代码:
<HTML> <HEAD> <?IMPORT NAMESPACE="IE" IMPLEMENTATION="#default"> <style TYPE="text/css"> .contentstyle { width:5.5in; height:8in; margin:1in; background:white; border:1 dashed gray; } </style> </HEAD>
<BODY> <IE:LAYOUTRECT ID="layoutrect1" CONTENTSRC="2.html" CLASS="contentstyle" NEXTRECT="layoutrect2"/>
<IE:LAYOUTRECT ID="layoutrect2" CLASS="contentstyle"/> </BODY> </HTML>
跟例一中的源代码相比,例二中只是以 LayoutRect 代替了原来的 DeviceRect 标记;DeviceRect 定制的是模板整体风格,而 LayoutRect 定制的是具体内容的版面风格;LayoutRect 的 ID 属性也具有唯一性; CONTENTSRC 属性则指明了具体的将起作用网页文件;CLASS 指明了风格的引用对象;跟 DeviceRect 不同,在进行 LayoutRect 引用时,必须在每个页面指定 NEXTREC ,即依次排列的下一个内容风格,这里的"下一个内容"用其页面的相应 ID 进行标识,如本例中的 LayoutRect2 。
三.DeviceRect 与 LayoutRect 的协同作战:
上面我们分别讨论了 DeviceRect 与 LayoutRect 的作用与引用方法,现在我们来看一下,如何在同一个打印模板中进行定制与引用。
在每一个打印模板上,必然包含两方面的内容,一个是整体的模板风格(DeviceRect),另一个是内容风格(LayoutRect);第一个打印页面跟其他页面是不同的,因为第一个页面中必须指明 CONTENTSRC 属性,而同一打印任务中的其他页面不再需要进行 CONTENTSRC 的指定。
例三:
下面是第一个页面中的 DeviceRect 代码:
<IE:DEVICERECT ID="page1" CLASS="masterstyle" MEDIA="print"> <IE:LAYOUTRECT ID="layoutrect1" CONTENTSRC="2.html" CLASS="contentstyle" NEXTRECT="layoutrect2"/> </IE:DEVICERECT>
下面是其他页面中的 DeviceRect 代码:
<IE:DEVICERECT ID="page2" CLASS="masterstyle" MEDIA="print"> <IE:LAYOUTRECT ID="layoutrect2" CLASS="contentstyle"/> </IE:DEVICERECT>
下面我们将 DeviceRect 与 LayoutRect 结合起来使用,其源代码如下:
<HTML XMLNS:IE> <HEAD> <?IMPORT NAMESPACE="IE" IMPLEMENTATION="#default"> <style TYPE="text/css"> .contentstyle { width:5.5in; height:8in; margin:1in; background:white; border:1 dashed gray; } .Mystyle1 { width:8.5in; height:11in; background:#FFFF99; border-left:1 solid black; border-top:1 solid black; border-right:4 solid black; border-bottom:4 solid black; margin:10px; } </style> </HEAD>
<BODY> <IE:DEVICERECT ID="page1" CLASS="Mystyle1" MEDIA="print"> <IE:LAYOUTRECT ID="layoutrect1" CONTENTSRC="2.html" CLASS="contentstyle" NEXTRECT="layoutrect2"/> </IE:DEVICERECT>
<IE:DEVICERECT ID="page2" CLASS="Mystyle1" MEDIA="print"> <IE:LAYOUTRECT ID="layoutrect2" CLASS="contentstyle"/> </IE:DEVICERECT>
</BODY> </HTML>
四.DeviceRect 与 LayoutRect 标记的动态自动添加:
前面我们说到,每个单独的打印页面都需要各自的 DeviceRect 与 LayoutRect 标记,那么,如果我们有 1000 个页面需要打印,是否就要在每个页面上重复繁琐的 Copy & Paste 操作?
答案是否定的,我们完全可以通过 JavaScript 脚本来完成这一繁琐的工作。
要实现 HTML 声明的动态创建,关键在于 <DIV> 标记的定义,下面是其定义规则。
<DIV ID="devicecontainer"> ...... </DIV>
<DIV>与</DIV>之间,采用 insertAdjacentHTML() 方式,并主要利用了其 afterBegin 与 BeforeEnd 两个变量,现在我们将第一个页面"插入"到<DIV></DIV>之间:
devicecontainer.insertAdjacentHTML("afterBegin", newHTML);
具有继承属性的后续页面,调用 beforeEnd 变量:
devicecontainer.insertAdjacentHTML("beforeEnd", newHTML);
要装载 devicecontainer 页面,还需在 <Body>中添加:
<BODY ONLOAD="addFirstPage()">
现在我们在 JavaScript 中添加包含前面详细介绍的 LayoutRect 与 DeviceRect 元素,用到的命令是 addFirstPage() 。需要注意的是,newHTML 标记后使用的是双引号,而 LayoutRect 与 DeviceRect 标记后的变量使用单引号。如下:
function addFirstPage() { newHTML = "<IE:DEVICERECT ID='devicerect1' MEDIA='print' CLASS='mystyle1'>"; newHTML += "<IE:LAYOUTRECT ID='layoutrect1' CONTENTSRC='2.html'" + "ONLAYOUTCOMPLETE='onPageComplete()' NEXTRECT='layoutrect2'" + "CLASS='contentstyle'/>"; newHTML += "</IE:DEVICERECT>";
devicecontainer.insertAdjacentHTML("afterBegin", newHTML); }
细心的读者一定会发现,LayoutRect 后出现了一个新的属性:LayoutRect:onLayoutComplete ,这个属性主要指定了 LayoutRect 停止响应的后续事件,如系统资源消耗殆尽而停止响应,或者 LayoutRect 指定的变量溢出。
好了,有了上面的原理,下面我们来编写具有自动"插入"功能的 JavaScript 代码:
function onPageComplete() { if (event.contentOverflow) { newHTML = "<IE:DEVICERECT ID='devicerect" + (lastPage + 1) + "' MEDIA='print' CLASS='mystyle1'>"; newHTML += "<IE:LAYOUTRECT ID='layoutrect" + (lastPage + 1) + "' ONLAYOUTCOMPLETE='onPageComplete()' NEXTRECT='layoutrect" + (lastPage + 2) + "' CLASS='contentstyle'/>"; newHTML += "</IE:DEVICERECT>";
devicecontainer.insertAdjacentHTML("beforeEnd", newHTML); lastPage++; }
在上面的代码中,contentOverflow 代表的是由于页面信息过长,本页的 LayoutRect 停止响应,则直接跳到下一个页面,让 LayoutRect 重新定义下一个页面的版面;onPageComplete() 则不管页面是否过长,LayoutRect 是否停止响应,只要到了页面尾部则自动跳到下一页,这也是最常见的情况。
在编写本脚本时,关键处在于保持清醒,不能让任意一个变量出错。其中,ID 不仅针对 DeviceRect 与 LayoutRect ,还为 NextRect 所引用,页面指向不能出错;当前页面的页码应该是 lastPage+1 ,下一个页面的页码应该是 lastPage+2 ;NextRect 标记需要下一个页面的 LayoutRect 属性支持,因此它的值应该为 "layoutRect"+(lastPage+2);打开第一个页面时,这个 LastPage 初始值为 1 |
|
Flash MX 认证考试(样题)
|
来源: 未知
作者: cabxyz
更新日期: [2005-03-12]
1. Flash MX 不可以在Macintosh 平台上运行。 □ A. 正确 □ B. 错误 2. Flash 影片频率最大可以设置到多少? □ A. 99 □ B. 100 □ C. 120 □ D. 150 3. FListBox.addItem 和FListBox.addItemAt 有什么用 □ A. 添加列表框 □ B. 使用Value(值)对话框添加项目 □ C. 添加下拉菜单 □ D. 给组合框添加项目 4. Library 中有一元件Symbol 1,舞台上有一个该元件的实例。现通过实例属性检查器将该实 例的颜色改为#FF0033,透明度改为80%。请问此时Library 中的Symbol 1 元件将会发生什么 变化? □ A. 颜色也变为#FF0033 □ B. 透明度也变为80% □ C. 颜色变为#FF0033,透明度变为80% □ D. 不会发生任何改变 5. 编辑位图图像时,修改的是: □ A. 像素 □ B. 曲线 □ C. 直线 □ D. 网格 6. 单击View>Hide Edges 的作用是: □ A. 隐藏被选择对象的突出显示状态 □ B. 隐藏被选择对象的外框轮廓 □ C. 隐藏被选择对象的填充区域 □ D. 隐藏被选择对象的线条 7. 当Flash 导出较短小的事件声音(例如按钮单击的声音)时,最适合的压缩选项是: □ A. ADPCM 压缩选项 □ B. MP3 压缩选项 □ C. Speech 压缩选项 □ D. Raw 压缩选项 8. 对于在网络上播放动画来说,最合适的帧频率是: □ A. 每秒24 帧 □ B. 每秒12 帧 □ C. 每秒25 帧 □ D. 每秒16 帧 9. 将舞台上的对象转换为元件的步骤是: □ A. "1.选定舞台上的元素; 2.. 单击Insert> Convert to Symbol,打开Convert to Symbol 对话框 3.填写Convert to Symbol 对话框,并点击确定" □ B. "1.. 单击Insert> Convert to Symbol,打开Convert to Symbol 对话框 2.选定舞台上的元素 3.填写Convert to Symbol 对话框,并点击确定" □ C. "1.选定舞台上的元素,并将选定元素拖到库面板上 2.. 单击Insert> Convert to Symbol,打开Convert to Symbol 对话框 3.填写Convert to Symbol 对话框,并点击确定" □ D. "1.. 单击Insert> Convert to Symbol,打开Convert to Symbol 对话框 2.选定舞台上的元素,并将选定元素拖到库面板上 3.填写Convert to Symbol 对话框,并点击确定" 10. 某电影中,只有一个layer1,其上放置一个有两个元件(test1 和test2)组合成的组合体, 选择这个组合体执行打散Ctrl+B,然后右键单击执行Distribute to layers,那末: □ A. 这个电影中将增加两个新层:layer2 和layer3 □ B. 这个电影中将增加两个新层:test1 和test2,而原有的layer1 将消失 □ C. 这个电影中将增加两个新层:test1 和test2,而原有的图层维持不变 □ D. 这个电影中将增加两个新层:test1 和test2,而原有的layer1 成为空层 11. 全等(===)运算符和相同运算符基本相似,但是它们有一个很重要的区别 □ A. 全等(===)运算符执行数据类型的转换 □ B. 全等(===)运算符不执行数据类型的转换 □ C. 全等(===)运算符永远返回真 □ D. 以上都不对 12. 如果导入的是图像序列中的一个picture001.bmp 文件,并且序列中的其他文件位于相同的 文件夹中,则将被识别为图像序列将是下面哪些: □ A. picture001.bmp □ B. picture002.bmp □ C. picture003.bmp □ D. picture-001.bmp 13. 如果要让Flash 同时对若干个对象产生渐变动画,则必须将这些对象放置在不同的层中。 □ A. 正确 □ B. 错误 14. 矢量图形用来描述图像的是: □ A. 直线 □ B. 曲线 □ C. 色块 □ D. A 和B 都正确
15. 下列那几个属性是 flash mx 不建议使用的属性 □ A. scroll □ B. maxscroll □ C. _droptarget □ D. _highquality 16. 下面的语句说法正确的是: □ A. 目前Flash 最新的创作平台是Flash MX,播放插件是Flash MX Player。 □ B. 目前Flash 最新的创作平台是Flash MX,播放插件是Flash 6.0 Player。 □ C. 目前Flash 最新的创作平台是Flash 6.0,播放插件是Flash MX Player。 □ D. 目前Flash 最新的创作平台是Flash 6.0,播放插件是Flash 6.0 Player。 17. 下面关于FLASH MX 导入Fireworks 的PNG 文件的说法错误的是: □ A. 用户可以选择作为可编辑对象或不可编辑的图像进行导入 □ B. 当作为不可编辑的图像导入时,文件将转换成位图图像对象,但是导入矢量图形除外 □ C. 作为可编辑对象导入,用户可以选择保留位于PNG 文件中的图像、文本和辅助线 □ D. 作为不可编辑的图像导入PNG 文件,则用户可以在Flash MX 中启动Fireworks 编辑该 PNG 图像 18. 下面关于从浏览器打印电影和从Flash 播放器打印电影的说法错误的是: □ A. "从Flash 播放器打印电影,可以指定Flash 电影中的哪些帧可以被打印" □ B. "从Flash 播放器打印电影,可以确定帧的打印区域" □ C. "从Flash 播放器打印电影,可以给电影剪辑中的打印帧附加Print 动作" □ D. 从浏览器打印电影肯定比从Flash 播放器打印电影效果好 19. 下面关于打印Flash 电影说法错误的是: □ A. 打印Flash 矢量图形时,可以在任意尺寸上获得清晰的打印效果 □ B. 打印低分辨率的位图图像时,受到像素的影响 □ C. 不可以从浏览器打印Flsh 电影 □ D. Flash 播放器的打印功能允许用户打印电影中的目录、联票、单篇、收据、发票或其他 文档 20. 下面关于矢量图形和位图图像的说法错误的是: □ A. Flash 允许用户创建并产生动画效果的是矢量图形而位图图像不可以 □ B. 在 Flash 中,用户也可以导入并操纵在其他应用程序中创建的矢量图形和位图图像 □ C. 用FLASH MX 的绘图工具画出来的图形为矢量图形 □ D. 一般来说矢量图形比位图图像文件量大 21. 下面关于通过Flash 播放器的关联菜单打印说法错误的是: □ A. 可打印任意Flash 电影中的帧 □ B. 无法打印透明度 □ C. 可以打印颜色效果 □ D. 无法打印其他电影剪辑中的帧 22. 下面哪个不是FlashMX 中内置的组件? □ A. CheckBox(复选框) □ B. RadioButton(单选钮) □ C. ScrollPane(滚动窗格) □ D. Jump Menu (跳转菜单) 23. 下面哪些操作不可以使电影优化: □ A. 如果电影中的元素有使用一次以上者,则可以考虑将其转换为元件 □ B. 只要有可能,请尽量使用渐变动画 □ C. 限制每个关键帧中发生变化的区域 □ D. 要尽量使用位图图像元素的动画 24. 下面哪些是Flash MX 新增的功能? □ A. 可以导入mp3 格式的声音文件。 □ B. 可以导入视频格式。 □ C. 增加了层文件夹。 □ D. 可以把声音设置成流方式。 25. 下面那个方法不属于 Date(日期)对象 □ A. getDate() □ B. getDay() □ C. getMonth() □ D. getMinute() 26. 要分离位图图像,按以下步骤操作:1、选择当前场景中的位图图像;2、单击 Modify> Trace Bitmap 命令。 □ A. 正确 □ B. 错误 27. 要改变舞台上复选框组件的宽度,可以 □ A. 使用Free Transform(自由变形)工具 □ B. 使用setSize 方法 □ C. 使用AS 中的_width(宽度)属性 □ D. 使用属性面板中的w 属性精确调整 28. 要在组件面板中显示SmartClips 或自定义的组件,应该如何做? □ A. 将包含组件的电影剪辑放在库(Library)中 □ B. 将包含组件电影剪辑的FLA 文件放置在Flash MX 的组件文件夹中 □ C. 将包含组件电影剪辑的FLA 文件放置在Flash6/Configuration/Components 中 □ D. 导入包含组件电影剪辑的SWF 导入 29. 以下各种关于图形元件的叙述,正确的是 □ A. 可用来创建可重复使用的,并依赖于主电影时间轴的动画片段 □ B. 可用来创建可重复使用的,但不依赖于主电影时间轴的动画片段 □ C. 可以在图形元件中使用声音 □ D. 可以在图形元件中使用交互式控件 30. 以下关于使用元件的优点的叙述,正确的是: □ A. 使用元件可以使电影的编辑更加简单化 □ B. 使用元件可以使发布文件的大小显著地缩减 □ C. 使用元件可以使电影的播放速度加快 □ D. 以上均是 31. 以下关于帧标记和批注的说法正确的是: □ A. 帧标记和帧批注的长短都将影响输出电影的大小。 □ B. 帧标记和帧批注的长短都不影响输出电影的大小。 □ C. 帧标记的长短不会影响输出电影的大小,而帧批注的长短对输出电影的大小有影响。 □ D. 帧标记的长短会影响输出电影的大小,而帧批注的长短对输出电影的大小不影响。 32. 以下关于帧并帧动画和渐变动画的说法正确的是: □ A. 两种动画模式FlashMX 都必须记录完整的各帧信息 □ B. 前者必须记录各帧的完整记录,而后者不用 □ C. 前者不必记录各帧的完整记录,而后者必须记录完整的各帧记录 □ D. 以上说法均不对 33. 以下哪些操作可以使Flash 进入直接编辑元件的模式? □ A. ". 双击舞台上的元件实例" □ B. ". 选中舞台上的元件,然后使用鼠标右键单击,从弹出的快捷菜单中选择 Edit in Place" □ C. ". 双击库面板内的元件图标" □ D. 将舞台上的元件拖动到库面板之上 34. 在256 色环境中,可以使用Flash MX 进行创作。 □ A. 正确 □ B. 错误 35. "在Flash MX 中,未定义的toString 是" □ A. """ """ □ B. undefined □ C. NULL □ D. null 36. 在Flash MX 中,要绘制基本的几何形状,可以使用的绘图工具是: □ A. 直线 □ B. 椭圆 □ C. 圆 □ D. 矩形 37. 在Flash MX 中,要绘制精确的直线或曲线路径,可以使用: □ A. Pen Tool(钢笔工具) □ B. Pencil Tool(铅笔工具) □ C. Brush Tool(刷子工具) □ D. A 和B 都正确 38. 在Flash 的测试模式中,下面哪些可以List Objects(列表显示对象)命令来显示: □ A. 帧 □ B. 对象类型(形状、电影剪辑或按钮) □ C. 目标路径 □ D. 电影剪辑的实例名 39. 在Internet Explorer 浏览器中,是通过下列哪种技术来播放Flash 电影(swf 格式的文件)? □ A. DLL □ B. COM □ C. OLE □ D. Active X 40. "在动作列表中,批注以什么颜色来表示" □ A. 绿色 □ B. 紫色 □ C. 蓝色 □ D. 粉红色 41. 在设置电影属性时,设置电影播放的速度为12fps,那么在电影测试时,时间轴上显示的 电影播放速度应该可能是: □ A. 等于12fps □ B. 小于12fps □ C. 大于12fps □ D. 大于、小于12fps 均有可能 42. 在下列哪些操作系统下,可以通过浏览器播放Flash 电影(swf 格式的文件)? □ A. DOS □ B. Windows 95 □ C. Windows 2000 □ D. Redhat Linux 43. 在移动对象时,在按方向键的同时按住 Shift 键可大幅度移动对象,每次移动距离为: □ A. 1 像素 □ B. 4 像素 □ C. 6 像素 □ D. 8 像素 44. 作为发布过程的一部分,Flash 将自动执行某些电影优化操作: □ A. 正确 □ B. 错误
看看你对flash了解多少~~~
答案:
B, C, B, D, A,
A, A, B, A, D,
B, ABCD, A, D, ABD,
B, B, D, C, D,
C, D, D, BC, D,
B, ABD, BC, A,
30D,D, B, AB, A,
35A, ABD, A, ABCD, D,
40 D,AB, BCD, D, A, |
|
asp如何实现图片的动态翻动的效果
|
来源: 未知
作者: scoutlin
更新日期: [2005-01-28]
http://community.csdn.net/Expert/topic/3722/3722373.xml?temp=.6881372
<tr><td><input type=button value='<' name=lefts onclick="leftimg();"></td> <%set rs=server.createobject("adodb.recordset") rs.open "select top 3 * from table order by id desc",conn,1,1 ii=1 do while not rs.eof%> <td><img src='<%=rs("img")%>' id='img<%=ii%>'><br><div id='txt<%=ii%>'><%=rs("title")%></div></td> <%ii=ii+1 rs.movenext loop rs.close set rs=nothing %> <td><input type=button value='>' name=rights onclick="rightimg();"></td> </tr> <script> var imgarray=new Array(); var txtarray=new Array(); var ipos=0; <%set rs=server.createobject("adodb.recordset") rs.open "select top 5 * from table order by id desc",conn,1,1 ii=0 do while not rs.eof%> imgarray[<%=ii%>]="<%=rs("img")%>"; txtarray[<%=ii%>]="<%=rs("title")%>";
<% ii=ii+1 rs.movenext loop rs.close set rs=nothing%> function leftimg(){ ipos++; ipos2=ipos; if(ipos2>4){ipos2=0;ipos=0} img1.src=imgarray[ipos2]; txt1.innerHTML=txtarray[ipos2]; ipos2++; if(ipos2>4){ipos2=0} img2.src=imgarray[ipos2] txt2.innerHTML=txtarray[ipos2]; ipos2++; if(ipos2>4){ipos2=0} img3.src=imgarray[ipos2] txt3.innerHTML=txtarray[ipos2]; } function rightimg(){ ipos--; ipos2=ipos; if(ipos2<0){ipos2=4;ipos=4} img1.src=imgarray[ipos2] txt1.innerHTML=txtarray[ipos2]; ipos2++; if(ipos2>4){ipos2=0} img2.src=imgarray[ipos2] txt2.innerHTML=txtarray[ipos2]; ipos2++; if(ipos2>4){ipos2=0} img3.src=imgarray[ipos2] txt3.innerHTML=txtarray[ipos2]; } </script>
|
|
怎么给网页中的Flash上加超连接
|
来源: 未知
作者: Azmore
更新日期: [2005-02-23]
说到这个问题,可能有人就会说,那还不简单,直接用flash的ActionScript中的url方法不就搞定了,那么如果我们的UI人员设计完flash,但flash对应的链结还没有确定或者以后会变更怎么办?我需要的是能够在外部修改flash对应的链结。
那直接在flash所在的object元素外部加<a></a>标签来控制不就行了,可能有些人会这么想,思路正确,但是行不通。呵呵,怎么办?百度一下先,呵呵,真是相当佩服某些人的牛脑,真牛,下面是一种解决的方法:
首先,我们肯定是要先插入FLASH.因为,Flash默认是最高层.所以, 我经常会遇见Flash把下拉菜单挡住的情况. 把Flash文件放到一个层中,设为最底层,FLASH设为透明. <div style="z-index:-1"> <!--1.设置FLASH为底层--> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="200" height="115"> <param name="movie" value="media.swf"> <param name="quality" value="high"> <embed src="media.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="200" height="115"></embed> <param name="wmode" value="transparent"> <!--2.必须把FLASH设置为透明--> </object> </div>
再接下来,就是在FLASH的层上再加上一层, Flash本身不能直接加入onclick.等事件,所以,只能借助别的东西啦. 就是在FLASH上加个透明层, <div id="huiLayer" style="cursor: hand; position:absolute; left:10px; top:10px; width:200px; height:115px; z-index:1; visibility: visible;"><a href="http://www.cnlk.com"> <img src="kong.gif" width="200" height="115" border="0"></a></div> 论坛上面,给了一些解决方法,就是加个透明的层,但是,如果光有个透明层, 还是不能接受事件的. 更确切地说,是一部分可以,一部分不可以,和FLASH部分重叠的那一部分不行. 为什么不行.说实话,我也不清楚,我是试验得出来的...
当我把这个层的背景颜色设为任意一种时,不是透明时,发现.可以接受事件了,在层上加了个 超连接,也可以.. 但是,这还不是我们要的结果.因为,把整个"精美"的FLASH给遮盖了.. 所以,有<img src="kong.gif" width="200" height="115" border="0"> 我用PhotoShop做了个透明的图片kong.gif 大小都可以,但是必须是透明的!这样 才不至于把底下的FLASH给遮盖住了. 试验了一下... 成功了... 点击FLASH.其实是击中了FLASH上层的透明图片kong.gif 图片,就可以接受很多事件啦,onclick , onmouseover ,onmosueout ...... 给图片加个<a></a>超连接是再简单不过的事啦.. 这时,以上的问题是不是都解决了,把事件都给kong.gif接受! 单击事件, <div onclick="ok()" id="huiLayer" ........... 不管是坐火车,还是飞飞机,过年都得回家,所以方法还是有的,Flash本身还提供了一种方法,相当的好用,就是在Flash内部通过FSCommand调用外部的脚本,个人认为这种方法简单实用,可控能力强,具体用法,就不在这里多说了,你在网上搜FSCommand关键键字就会啊到很多实例,不过还是有一点提示:在提供javascript版本的调用方法时,最好也提供一个vbscript的版本,否则调用可能会不成功。
|
|
一个18位身份证校验计算函数
|
来源: 未知
作者: sfply
更新日期: [2005-02-23]
因需要对15位旧身份证号码进行升位和校验、查询处理,又没有搜索到现成的函数,于是自己写了一个简单的过程,希望能够帮得上需要的朋友。 本函数的功能单一,只能校验第18位号码是否正确或者取得第18位号码,其他功能留给大家自己扩展吧!
<% ' Version: 1.0.1 ' Author: sfply(sfply@163.com) ' Last Modified: 2004/7/17 12:03 ' Src是身份证号码,可以是15位也可以是18位,15位时只能返回验证码方式使用 ' iChk参数取值真假,真代表校验Src是否18位身份证,并且校验第18位是否正确号码而确定是否有效身份证,返回只值为true或false ' 假代表返回正确的校验码,返回值为(1~x) dim myIdentify myIdentify = "36050219781218133?"
response.write chkIdentiyCard(myIdentify,false)
Function chkIdentiyCard(Src,iChk) dim myWi,myAi,mySrc(17),i,myCount myAi = "10X98765432" myWi = split("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2",",") if iChk then if len(Src) = 18 then for i = 0 to 16 mySrc(i) = mid(Src,i+1,1) myCount = myCount + mySrc(i) * myWi(i) next if mid(myAi,(mycount mod 11)+1,1) = right(Src,1) then chkIdentiyCard = true '返回结果,TRUE为合法身份证验证码 else chkIdentiyCard = false '返回结果,FALSE为非法身份证验证码 end if else chkIdentiyCard = false '因为不是18位身份证所以返回FALSE end if else if len(Src) = 15 or len(Src) = 18 then if len(Src) = 15 then Src = mid(Src,1,6) & "19" & mid(Src,7,9) for i = 0 to 16 mySrc(i) = mid(Src,i+1,1) myCount = myCount + mySrc(i) * myWi(i) next chkIdentiyCard = mid (myAi,(mycount mod 11)+1,1) '返回正确的验证码 else chkIdentiyCard = false '输入不不是15位或18位身份证号 end if end if End Function %>
关于身份证第18是怎么计算的,原理如下
根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。下面举例说明该计算方法。
15位的身份证编码首先把出生年扩展为4位,简单的就是增加一个19,但是这对于1900年出生的人不使用(这样的寿星不多了)
某男性公民身份号码本体码为34052419800101001,首先按照公式⑴计算:
∑(ai×Wi)(mod 11)……………………………………(1)
公式(1)中: i----表示号码字符从由至左包括校验码在内的位置序号; ai----表示第i位置上的号码字符值; Wi----示第i位置上的加权因子,其数值依据公式Wi=2(n-1)(mod 11)计算得出。
i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 ai 3 4 0 5 2 4 1 9 8 0 0 1 0 1 0 0 1 a1
Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1
ai×Wi 21 36 0 25 16 16 2 9 48 0 0 9 0 5 0 0 2 a1
根据公式(1)进行计算:
∑(ai×Wi) =(21+36+0+25+16+16+2+9+48++0+0+9+0+5+0+0+2) = 189
189 ÷ 11 = 17 + 2/11
∑(ai×Wi)(mod 11) = 2
然后根据计算的结果,从下面的表中查出相应的校验码,其中X表示计算结果为10:
∑(ai×WI)(mod 11) 0 1 2 3 4 5 6 7 8 9 10 校验码字符值ai 1 0 X 9 8 7 6 5 4 3 2 根据上表,查出计算结果为2的校验码为所以该人员的公民身份号码应该为 34052419800101001X。
a[0]*7+a[1]*9+a[2]*10+a[3]*5+a[4]*8+a[5]*4+a[6]*2+a[7]*1+a[8]*6+a[9]*3 +a[10]*7+a[11]*9+a[12]*10+a[13]*5+a[14]*8+a[15]*4+a[16]*2
|
|
初级教程之SQL Injection(SQL注入攻击)
|
来源: 未知
作者: KrnlCrk
更新日期: [2005-03-12]
因为目前SQL注入是非常热门而且技术门槛较低的攻击手段,并且非常实用,轻则可以拿到网站的一些帐号,比如拿到某个电影网站的黄金会员的帐号;重则利用其网站楼多入侵整个服务器等等。
这里打算作为一个专题讲解SQL及其注入。其中对于SQL不太明白的地方希望大家自己查资料。这个帖子将长期更新。。。
一,SQL纵览
SQL(Structured Query Language)语言是一种结构化查询语言。SQL语言中完成核心功能的共有9个关键词:SELECT(数据查询)、CREAT、DROP、ALTER(数据定义)、INSERT、UPDATA、DELETE(数据操纵)、GRANT、REVOKE(数据控制)。
1,数据定义部分 (1)创建基本表 creat table Employee ( Eno char(6) not null unique, Ename char(20) unique Esex char(2) Eage int Edept char(10) Espe char(20) ) 该语句创建了一个名为Employee的数据表,共有六列,分别为字符型(长度为6,非空,唯一)的雇员号Eno,字符型(长度为20,唯一)的雇员号姓名Ename,字符型(长度为2)的雇员性别,整型的雇员年龄,字符型(长度为10)的雇员部门,字符型(长度为20)的雇员特长.
(2)删除基本表 DROP TABLE Employee
(3)更改基本表 ALTER TABLE Employee ADD Esalary CHAR(5) 在雇员表中加入一列,字符型(长度为5)的雇员薪水. ALTER TABLE Wmployee DROP UNIQUE(Ename); 去掉雇员表中雇员姓名的唯一属性. ALTER TABLE Employee MODIFY Esex CHAR(1); 把雇员表中的性别列改为一位字符型.
2,数据查询部分
这是SQL语句中最灵活,功能最强的部分. (1)基本查询语句 SELECT Eno,Ename,Esex FROM Employee 查询Employee表中的Eno,Ename,Esex三列 SELECT * FROM Employee 查询Employee表中的所有列. SELECT DISTINCT Eno FROM Employee; 查询Employee表中的Eno列,并去除重复行.
(2)条件(WHERE)查询语句 插叙条件的连接词如下:NOT,=,>,<,>=,<=,!=,<>,!>,!<,BETWEEN AND,NOT BETWEEN AND(确定范围),LIKE,NOT LIKE(字符匹配),IS NULL,IS NOT NULL(空值),AND,OR(多条件连接).
ⅰ 比较 SELECT Eno FROM Employee WHERE Eage <=25 列出表中年龄小于25的雇员号 ⅱ 确定范围 SELECT Eno,Ename FROM Employee WHERE Eage [NOT] BETWEEN 20 AND 30 列出表中年龄(不)在20到30的雇员号和姓名 ⅲ 确定集合 SELECT Eno,Ename FROM Employee WHERE Edept [NOT] IN (‘SD',’HD’) 列出表中(不)是软硬件开发部的雇员号和姓名 ⅳ 字符匹配 LIKE的用法如下 [NOT] LIKE ‘<匹配模式>’[ESCAPE ‘<换码符>’] 通配符号有%和_两种。 %:匹配任意长度的字符串(长度可以为0)。A%b可与ab,adfb等匹配。 _:匹配单个任意字符。a_b可与a#b,a@b等匹配。 如果有ESCAPE,则跟在换码符号后的%或者_不再是通配符号,只是正常的%或_。 例如: SELECT * FROM Employee WHERE Ename LIKE ‘刘%’ 查找表中姓刘雇员的信息 SELECT * FROM Employee Where Ename LIKE ‘刘_ _’ 查找表中姓名为刘某(两个字)的雇员的信息。 SELECT * FROM Employee WHERE Espe LIKE ‘DB\%t_‘ESCAPE’\’ 查找表中特长项为DB_开始,倒数第二个字符为t的雇员的信息。
Ⅴ 空值SELECT * FROM Employee WHEREE Espe IS [NOT] NULL 查找表中特长项(不)为空的雇员信息。
Ⅵ 多条件连接 SELECT Ename FROM Employee WHERE Edept ='SD' AND Eage <=30; 列出表中软件开发部门30及30岁以下雇员姓名。
(3)结果排序 对查询结果进行排序用ORDERBY,ASC(默认)为升序,DESC为降序 SELECT * FROM Employee ORDER BY Edept,Eage DESC
(4)结果分组 对查询结果的分组一般要用到SQL的集函数,因此先介绍集函数。 SQL语言的集函数主要有COUNT(统计总数),SUM(求和),AVG(求均值),MAX(最大值),MIN(最小值)。 SELECT MAX(Eage) FROM Employee WHERE Edept='SD' 列出软件开发部年纪最大雇员的姓名。 SELECT Edept FROM Employee GROUP BY Edept HAVING Count(*)>10 统计各部门的雇员数,只显示雇员数大于10的部门。 SELECT Edept,COUNT(Eno) FROM Employee GROUP BY Edept 统计各部门雇员数,按部门分组列出各部门的雇员数。
(5)连接查询 连接查询是查询涉及多个数据表,FROM后连接多个表的情况。 假如我们要统计各个项目参加人的雇员号和姓名,涉及的表Eproject结构如下: Eproject (Eno CHAR(6),Pno CHAR(6),TimeBgnTIME, TimeEnd TIME,Remark CHAR(50)) 相应的查询语句为: SELECT Eproject.Pno,Employee.Eno,Ename FROM Employee,Eproject WHERE Employee.Eno=Eproject.Eno ORDER BY Eproject.Pno; 列出参加各项目的雇员号和姓名,并按照项目号升序排列。
(6)集合查询 集合查询指的是多个SELECT查询结果间进行的集合操作。主要有UNION(并操作),INTERSECT(交操作),MINUS(差操作),其中标准SQL中没有提供交操作和差操作,但他们可以使用联合查询实现。 假如我们要查询硬件开发部年龄不大于25岁的雇员,可以结合查询实现如下: SELECT * FROM Employee WHERE Edept='HD' UNION SELECT * FROM Employee WHERE Eage<=25
3,数据更新部分 SQL中的数据更新语句有INSERT,UPDATE和DELETE三种,用法如下:
(1)插入数据 INSERT INTO Employee valueS ('13253','王二','男','23','SD','DB_Project') 向雇员表中插入一条完整的数据 INSERT INTO Employee (Eno,Ename) valueS ('13253','王二'); 向表中插入一条数据,只包含雇员号和姓名,其他列为空值。 注意:以上情况,属性为非空的列一定不能为空值。
(2)修改数据 UPDATE Employee SET Eage=24 WHERE Eno='13253' 将表中13253号雇员年龄改为24岁
(3)删除数据 DELETE FROM Employee WHERE Eno='13253'
4,数据控制部分
(1)用户授权 SQL用户授权使用GRANT关键词,它的用法如下: GRANT SELECT ON TABLE Employee TO usr1; 允许用户usr1查询表Employee GRANT ALL PRIVILEGES ON TABLE Employee TO usr2; 允许用户usr2对表Employee的任何操作
(2)收回权限 SQL中收回用户权限使用REVOKE关键词 REVOKE UPDATE(Eno) ON TABLE Employee FROM usr3;] 收回usr3更新表Employee中Eno列的权利 REVOKE ON TABLE Employee FROM PUBLIC 不允许所有用户在表Employee中添加数据。 |
|
图片以二进制流输出到网页
|
来源: 未知
作者: Goldxin
更新日期: [2005-03-12]
using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.IO;
namespace MegaBBS.SendMail { /// <summary> /// WebForm4 的摘要说明。 /// </summary> public class WebForm4 : System.Web.UI.Page { private void Page_Load(object sender, System.EventArgs e) { // 在此处放置用户代码以初始化页面 if(!this.IsPostBack) { BindData(); } }
#region Web 窗体设计器生成的代码 override protected void OnInit(EventArgs e) { // // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。 // InitializeComponent(); base.OnInit(e); } /// <summary> /// 设计器支持所需的方法 - 不要使用代码编辑器修改 /// 此方法的内容。 /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion
/// <summary> /// 图片以二进制流输出 /// </summary> private void BindData() { FileStream fs = new FileStream(@"D:\22-11-46-3-524454584.jpg",FileMode.Open,FileAccess.Read); byte[] mydata = new byte[fs.Length]; int Length = Convert.ToInt32(fs.Length); fs.Read(mydata,0,Length); fs.Close(); this.Response.OutputStream.Write(mydata,0,Length); this.Response.End(); } } } |
|
JavaScript实现的数据表格:冻结列、调整列宽和客户端排序
|
来源: 未知
作者: waxdollcheung
更新日期: [2005-03-12]
根据网上的一些脚本改的,大家看一下,应该对开发有用,准备在.Net下写个Server-Side端控件 把下面的代码另存为.htm文件后看下效果。
<HTML><HEAD> <TITLE>数据表格</TITLE> <META http-equiv=Content-Type content="text/html; charset=gb2312"> <STYLE type=text/css>BODY { FONT: 12px 细明体; CURSOR: default } TD { FONT: 12px 细明体; CURSOR: default } .title { BORDER-RIGHT: #555 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #fff 1px solid; PADDING-LEFT: 4px; BACKGROUND: LightBlue; PADDING-BOTTOM: 4px; OVERFLOW: hidden; BORDER-LEFT: #fff 1px solid; CURSOR: hand; PADDING-TOP: 4px; BORDER-BOTTOM: #555 1px solid; WHITE-SPACE: nowrap } .cdata { PADDING-RIGHT: 3px; BORDER-TOP: #fff 1px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; OVERFLOW: hidden; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid; WHITE-SPACE: nowrap } .coolMenu { position: absolute; height: 1px; width: 1px; font-size: 9pt; background-color: menu; border-top: 2px outset buttonhighlight; border-left: 2px outset buttonhighlight; border-bottom: 1px solid buttonshadow; border-right: 1px solid buttonshadow; visibility: hidden; } .coolMenu .coolMenuItem { height: 20px; margin: 1px; padding-right: 10px; cursor: hand; overflow: hidden; } .coolMenu .coolMenuItem IMG { vertical-align: middle; margin-left: 1px; margin-right: 6px; } .coolMenu .coolMenuItem .coolMenuMore { font-family: webdings; } .coolMenu .coolMenuDivider { border: 1px inset; border-top-color: buttonshadow; border-bottom-color: buttonhighlight; height: 2px; overflow: hidden; margin-left: 2px; margin-top: 2px; margin-bottom: 2px; } .sinput { BORDER-BOTTOM: black 1px solid; BORDER-LEFT: 0px; BORDER-RIGHT: 0px; BORDER-TOP: 0px; FONT-FAMILY: 宋体,Arial; FONT-SIZE: 9pt; WIDTH: 15pt; height: 12pt; }
</STYLE> <SCRIPT language=JavaScript> // 栏位标题 ( 栏位名称 # 栏位宽度 # 资料对齐 #数据类型(主要分三种数据类型:文本、数值、日期)) var DataTitles=new Array( "歌手 / 团体#90 #left#文本" , "专辑名称 #130#left#文本" , "发行公司 #110#left#文本" , "本周排名 #58 #center#数值", "排名状况 #58 #center#文本", "上周排名 #58 #center#数值", "上榜周数 #58 #center#数值", "最高名次 #58 #center#数值", "销售百分比 #70 #center#数值", "发行日期 #100 #right#日期" ) // 栏位资料 ( 二维阵列 ) var DataFields=new Array() DataFields[0] =new Array("萧亚轩萧亚轩萧亚轩萧亚轩萧亚轩萧亚轩萧亚轩萧亚轩" ,"爱的主打歌-吻" ,"维京 Virgin" ,"1" ,"持平" ,"1" ,"2","1" ,"2.9 %", "2004-1-1") DataFields[1] =new Array("张惠妹" ,"发烧" ,"华纳 Warner" ,"2" ,"持平" ,"2" ,"2","2" ,"2.1 %", "2004-2-10") DataFields[2] =new Array("陶吉吉" ,"黑色柳丁" ,"全员集合 Shock" ,"3" ,"持平" ,"3" ,"5","1" ,"1.8 %", "2004-2-09") DataFields[3] =new Array("S.H.E" ,"美丽新世界" ,"华研 HIM" ,"4" ,"持平" ,"4" ,"6","1" ,"1.2 %", "2003-1-1") DataFields[4] =new Array("艾薇儿" ,"展翅高飞" ,"博德曼 BMG" ,"5" ,"新进榜","-" ,"1","5" ,"1.1 %", "2004-4-4") DataFields[5] =new Array("任贤齐" ,"一个任贤齐" ,"滚石 Rock" ,"6" ,"新进榜","-" ,"1","6" ,"1.0 %", "2002-10-11") DataFields[6] =new Array("范逸臣" ,"范逸臣第一张专辑","丰华 Forward" ,"7" ,"持平" ,"7" ,"2","7" ,"0.9 %", "2002-12-11") DataFields[7] =new Array("谢霆锋" ,"无形的他全精选" ,"新力 Sony" ,"8" ,"下跌" ,"6" ,"4","4" ,"0.9 %", "2004-1-1") DataFields[8] =new Array("周蕙" ,"寂寞城市" ,"福茂 Decca" ,"9" ,"下跌" ,"5" ,"3","5" ,"0.8 %", "2004-1-1") DataFields[9] =new Array("周杰伦" ,"八度空间" ,"博德曼 BMG" ,"10","下跌" ,"8" ,"8","1" ,"0.8 %", "2004-1-1") DataFields[10]=new Array("酷玩乐团","玩过头" ,"科艺百代 EMI" ,"11","上升" ,"16","2","11","0.7 %", "2004-1-1") DataFields[11]=new Array("张震岳" ,"等我有一天" ,"魔岩 Magicstone","12","新进榜","-" ,"1","12","0.6 %", "2004-1-1") DataFields[12]=new Array("堂本刚" ,"红与蓝" ,"艾回 Avex" ,"13","新进榜","-" ,"1","13","0.6 %", "2004-1-1") DataFields[13]=new Array("ENERGY" ,"COME ON" ,"环球 Universal" ,"14","下跌" ,"10","9","5" ,"0.6 %", "2004-1-1") DataFields[14]=new Array("陈冠希" ,"TRANSITION" ,"艾回 Avex" ,"15","下跌" ,"9" ,"3","5" ,"0.4 %", "2004-1-1") DataFields[15]=new Array("合辑" ,"MTV 嘻哈大师" ,"环球 Universal" ,"16","下跌" ,"12","3","12","0.4 %", "2004-1-1") </SCRIPT> <SCRIPT language=JavaScript> var BoxWidth = 480 // 资料表显示宽度 ( 不含滚动条) var ShowLine = 10 // 资料表显示列数 var RsHeight = 21 // 资料列高度 var LockCols = 1 // 要锁定的栏位数 ( 由左至右 ) var RowColor = "Linen" var RowAlternativeColor = "#d9ffd3" var RowMouseOverColor = "LightSteelBlue" var RowSelectedColor = "CornflowerBlue"
//记录每次右击的列的索引。 var columnRC = 0
//记录被单击过的行的索引。 var rowC = -1;
function SetRowColor(sRowIndex, sColor) { for(i=0;i<leftTable.rows[sRowIndex].cells.length;i++) leftTable.rows[sRowIndex].cells[i].style.backgroundColor = sColor;
for(i=0;i<rightTable.rows[sRowIndex].cells.length;i++) rightTable.rows[sRowIndex].cells[i].style.backgroundColor = sColor; }
function ResetRowColor(sRowIndex) { var sColor = null; if (sRowIndex % 2 ==0) sColor = RowColor; else sColor = RowAlternativeColor; SetRowColor(sRowIndex, sColor); }
function SortTableAsc() { var cTitle=DataTitles[columnRC].split("#"); switch(cTitle[3]) { case "文本" : alert("暂时不支持文本排序!汉字的拼音问题尚未解决!"); break; case "数值" : var minIndex = 0; var tempArray = new Array(); for(i=0;i<DataFields.length;i++) { minIndex = i; var leftMin = parseFloat(DataFields[i][columnRC]); for(j=i+1;j<DataFields.length;j++) { if (leftMin>parseFloat(DataFields[j][columnRC])) { leftMin = parseFloat(DataFields[j][columnRC]); minIndex = j; } } if (minIndex != i) { for(h=0;h<DataFields[i].length;h++) { tempArray[h] = DataFields[i][h]; DataFields[i][h] = DataFields[minIndex][h]; DataFields[minIndex][h] = tempArray[h]; } } } ApplyData(); break; case "日期" : var minIndex = 0; var tempArray = new Array(); for(i=0;i<DataFields.length;i++) { //日期必须是yyyy-mm-dd格式的。 minIndex = i; var leftMin = DataFields[i][columnRC].split("-"); for(j=i+1;j<DataFields.length;j++) { var currentDate = DataFields[j][columnRC].split("-"); if ( ( parseInt(leftMin[0]) > parseInt(currentDate[0]) ) || ( ( leftMin[0] == currentDate[0] ) && ( parseInt(leftMin[1]) > parseInt(currentDate[1]) ) ) || ( ( leftMin[0] == currentDate[0] ) && ( leftMin[1] == currentDate[1] ) && ( parseInt(leftMin[2]) > parseInt(currentDate[2]) ) ) ) { leftMin[0] = currentDate[0]; leftMin[1] = currentDate[1]; leftMin[2] = currentDate[2]; minIndex = j; } } if (minIndex != i) { for(h=0;h<DataFields[i].length;h++) { tempArray[h] = DataFields[i][h]; DataFields[i][h] = DataFields[minIndex][h]; DataFields[minIndex][h] = tempArray[h]; } } } ApplyData(); break; } }
function SortTableDesc() { var cTitle=DataTitles[columnRC].split("#"); switch(cTitle[3]) { case "文本" : alert("暂时不支持文本排序!汉字的拼音问题尚未解决!"); break; case "数值" : var minIndex = 0; var tempArray = new Array(); for(i=0;i<DataFields.length;i++) { minIndex = i; var leftMin = parseFloat(DataFields[i][columnRC]); for(j=i+1;j<DataFields.length;j++) { if (leftMin<parseFloat(DataFields[j][columnRC])) { leftMin = parseFloat(DataFields[j][columnRC]); minIndex = j; } } if (minIndex != i) { for(h=0;h<DataFields[i].length;h++) { tempArray[h] = DataFields[i][h]; DataFields[i][h] = DataFields[minIndex][h]; DataFields[minIndex][h] = tempArray[h]; } } } ApplyData(); break; case "日期" : var minIndex = 0; var tempArray = new Array(); for(i=0;i<DataFields.length;i++) { //日期必须是yyyy-mm-dd格式的。 minIndex = i; var leftMin = DataFields[i][columnRC].split("-"); for(j=i+1;j<DataFields.length;j++) { var currentDate = DataFields[j][columnRC].split("-"); if ( ( parseInt(leftMin[0]) < parseInt(currentDate[0]) ) || ( ( leftMin[0] == currentDate[0] ) && ( parseInt(leftMin[1]) < parseInt(currentDate[1]) ) ) || ( ( leftMin[0] == currentDate[0] ) && ( leftMin[1] == currentDate[1] ) && ( parseInt(leftMin[2]) < parseInt(currentDate[2]) ) ) ) { leftMin[0] = currentDate[0]; leftMin[1] = currentDate[1]; leftMin[2] = currentDate[2]; minIndex = j; } } if (minIndex != i) { for(h=0;h<DataFields[i].length;h++) { tempArray[h] = DataFields[i][h]; DataFields[i][h] = DataFields[minIndex][h]; DataFields[minIndex][h] = tempArray[h]; } } } ApplyData(); break; } }
function WriteTable(){ // 写入表格 var iBoxWidth=BoxWidth var NewHTML="<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>\ <td><div style=\"width:100%;overflow-x:scroll\">\ <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" id=\"leftHead\"><tr>" for(i=0;i<DataTitles.length;i++){ if(i<LockCols){ var cTitle=DataTitles[i].split("#") iBoxWidth-=cTitle[1] NewHTML+="<td><div class=\"title\" style=\"width:"+cTitle[1]+"px;height:"+RsHeight+"px\" align=\"" + cTitle[2] + "\" oncontextmenu=\"HeadRightClick()\">"+cTitle[0]+"</div></td>" } } NewHTML+="</tr>\ <tr><td colspan=\""+LockCols+"\">\ <div id=\"DataFrame1\" style=\"position:relative;width:100%;overflow:hidden\">\ <div id=\"DataGroup1\" style=\"position:relative\"></div></div>\ </td></tr></table></div></td>\ <td valign=\"top\"><div style=\"width:"+iBoxWidth+"px;overflow-x:scroll\">\ <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" id=\"rightHead\"><tr>" for(i=0;i<DataTitles.length;i++){ if(i>=LockCols){ var cTitle=DataTitles[i].split("#") NewHTML+="<td><div class=\"title\" style=\"width:"+cTitle[1]+"px;height:"+RsHeight+"px\" align=\"" + cTitle[2] + "\" oncontextmenu=\"HeadRightClick()\">"+cTitle[0]+"</div></td>" } } NewHTML+="</tr>\ <tr><td colspan=\""+(DataTitles.length-LockCols)+"\">\ <div id=\"DataFrame2\" style=\"position:relative;width:100%;overflow:hidden\">\ <div id=\"DataGroup2\" style=\"position:relative\"></div>\ </div></td></tr></table>\ </div></td><td valign=\"top\">\ <div id=\"DataFrame3\" style=\"position:relative;background:#000;overflow-y:scroll\" onscroll=\"SYNC_Roll()\">\ <div id=\"DataGroup3\" style=\"position:relative;width:1px;visibility:hidden\"></div>\ </div></td></tr></table>" DataTable.innerHTML=NewHTML ApplyData() } function ApplyData(){ // 写入资料 var NewHTML="<table id=\"leftTable\" onMouseOver=\"overcolor()\" onClick=\"clickColor()\" onMouseOut=\"outcolor()\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">" for(i=0;i<DataFields.length;i++){ if (i %2 == 0) NewHTML+="<tr bgcolor=\"" + RowColor + "\">" else NewHTML+="<tr bgcolor=\"" + RowAlternativeColor + "\">" for(j=0;j<DataTitles.length;j++){ if(j<LockCols){ var cTitle=DataTitles[j].split("#") NewHTML+="<td><div class=\"cdata\" style=\"width:"+cTitle[1]+"px;height:"+RsHeight+"px;text-align:"+cTitle[2]+"\">"+DataFields[i][j]+"</div></td>" } } NewHTML+="</tr>" } NewHTML+="</table>" DataGroup1.innerHTML=NewHTML
var NewHTML="<table id=\"rightTable\" onMouseOver=\"overcolor()\" onClick=\"clickColor()\" onMouseOut=\"outcolor()\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">" for(i=0;i<DataFields.length;i++){ if (i %2 == 0) NewHTML+="<tr bgcolor=\"" + RowColor + "\">" else NewHTML+="<tr bgcolor=\"" + RowAlternativeColor + "\">" for(j=0;j<DataTitles.length;j++){ if(j>=LockCols){ var cTitle=DataTitles[j].split("#") NewHTML+="<td><div class=\"cdata\" style=\"width:"+cTitle[1]+"px;height:"+RsHeight+"px;text-align:"+cTitle[2]+"\">"+DataFields[i][j]+"</div></td>" } } NewHTML+="</tr>" } NewHTML+="</table>" DataGroup2.innerHTML=NewHTML DataFrame1.style.pixelHeight=RsHeight*ShowLine DataFrame2.style.pixelHeight=RsHeight*ShowLine DataFrame3.style.pixelHeight=RsHeight*ShowLine+RsHeight DataGroup3.style.pixelHeight=RsHeight*(DataFields.length+1) }
function ResetTable(){
var iBoxWidth=0 for(i=0;i<DataTitles.length;i++){ if(i<(columnRC+1)){ var cTitle=DataTitles[i].split("#") iBoxWidth+=parseInt(cTitle[1]) } } if(iBoxWidth>BoxWidth){ var Sure=confirm("\n锁定栏位的宽度大於资料表显示的宽 \n\n度,这可能会造成版面显示不正常。\n\n\n您确定要继续吗?") }else{ Sure=true } if(Sure){ LockCols=(LockCols==columnRC+1)?0:columnRC+1 WriteTable() } }
function SYNC_Roll(){ DataGroup1.style.posTop=-DataFrame3.scrollTop DataGroup2.style.posTop=-DataFrame3.scrollTop }
function clickColor() { try { var oEl = event.srcElement; if (oEl) if (oEl.tagName == "DIV") { try { oEl = oEl.parentElement.parentElement; } catch (e) { return; } } if (oEl.tagName == "TD") oEl = oEl.parentElement;
var sindex = oEl.rowIndex; SetRowColor(sindex, RowSelectedColor); if (rowC >= 0) if (rowC != sindex) ResetRowColor(rowC); rowC = sindex; } catch (e) {} }
function overcolor() { var oEl = event.srcElement; if (oEl) if (oEl.tagName == "DIV") { try { oEl = oEl.parentElement.parentElement; } catch (e) { return; } } if (oEl.tagName == "TD") oEl = oEl.parentElement;
var sindex = oEl.rowIndex; if (rowC >= 0) if (sindex == rowC) return; SetRowColor(sindex, RowMouseOverColor); }
function outcolor() { var oEl = event.srcElement; if (oEl) if (oEl.tagName == "DIV") { try { oEl = oEl.parentElement.parentElement; } catch (e) { return; } } if (oEl.tagName == "TD") oEl = oEl.parentElement;
var sindex = oEl.rowIndex; if (rowC >= 0) if (sindex == rowC) return; ResetRowColor(sindex); }
function HeadRightClick() { var ev = window.event; var el = ev.srcElement; if (el.tagName == "DIV") { showMenu(ev.clientX, ev.clientY); ev.cancelBubble = true; ev.returnValue = false; var ep = el.parentElement; columnRC = ep.cellIndex; ep = el.parentElement.parentElement.parentElement.parentElement; if (ep.tagName == "TABLE") { if (ep.id == "rightHead") columnRC += LockCols; } } }
function showMenu(x, y) { var intRightEdge = window.document.body.clientWidth - x; var intBottomEdge = window.document.body.clientHeight - y; var intScrollLeft = window.document.body.scrollLeft + x; var intScrollTop = window.document.body.scrollTop + y;
if (intRightEdge < objHeadMenu.offsetWidth) objHeadMenu.style.left = intScrollLeft - objHeadMenu.offsetWidth; else objHeadMenu.style.left = intScrollLeft;
if (intBottomEdge < objHeadMenu.offsetHeight) objHeadMenu.style.top = intScrollTop - objHeadMenu.offsetHeight; else objHeadMenu.style.top = intScrollTop;
objHeadMenu.style.zIndex = 50; objHeadMenu.style.filter = "blendTrans(duration=0.50) progid:DXImageTransform.Microsoft.Shadow(color=#323232, direction=135, strength=3)"; if (objHeadMenu.filters.blendTrans.status != 2) { objHeadMenu.filters.blendTrans.apply(); objHeadMenu.style.visibility = "visible"; objHeadMenu.filters.blendTrans.play(); } }
function hideMenu() { objHeadMenu.style.filter = "blendTrans(duration=0.50) progid:DXImageTransform.Microsoft.Shadow(color=#323232, direction=135, strength=3)"; if (objHeadMenu.filters.blendTrans.status != 2) { objHeadMenu.filters.blendTrans.apply(); objHeadMenu.style.visibility = "hidden"; objHeadMenu.filters.blendTrans.play(); } }
//加列宽 function SetCWP(valWidth) { var cTitle = DataTitles[columnRC].split("#"); var cWidth = parseInt(cTitle[1]) + parseInt(valWidth); DataTitles[columnRC] = cTitle[0] + "#" + cWidth + "#" + cTitle[2] + "#" + cTitle[3]; WriteTable(); }
//减列宽 function SetCWM(valWidth) { var cTitle = DataTitles[columnRC].split("#"); var cWidth = parseInt(cTitle[1]) - parseInt(valWidth); if (cWidth <= 0) return; DataTitles[columnRC] = cTitle[0] + "#" + cWidth + "#" + cTitle[2] + "#" + cTitle[3]; WriteTable(); }
/* 右键菜单上的两个调整列宽的文本框的KeyDown事件,用于捕捉"Enter"时调整列宽并隐藏菜单 */ function CWKeyDown() { if (event.keyCode == 13) { var oEl = event.srcElement; if (oEl.id == "txtCWPlus") SetCWP(txtCWPlus.value); if (oEl.id == "txtCWMinus") SetCWM(txtCWMinus.value); hideMenu(); } }
function createMenu() { var txtHTML = "<div class=\"coolMenuItem\" style='padding-top: 1px;' onclick=\"SortTableAsc();hideMenu();\"><img src=\"images/asc.gif\" width=\"16\" height=\"16\">按升序排序</div>"; txtHTML += "<div class=\"coolMenuItem\" style='padding-top: 1px;' onclick=\"SortTableDesc();hideMenu();\"><img src=\"images/desc.gif\" width=\"16\" height=\"16\">按降序排序</div>"; txtHTML +="<div class=\"coolMenuDivider\"></div>"; txtHTML += "<div class=\"coolMenuItem\" style='padding-top: 1px;' onclick=\"ResetTable();hideMenu();\"><img src=\"images/blank.gif\" width=\"16\" height=\"16\">锁定列</div>"; txtHTML += "<div class=\"coolMenuDivider\"></div>"; txtHTML += "<div class=\"coolMenuItem\" style='padding-top: 1px;' onClick=\"SetCWP(txtCWPlus.value);\" onMouseOver=\"txtCWPlus.focus();\"><img src=\"images/blank.gif\" width=\"16\" height=\"16\">列宽 + <input type=\"text\" id=\"txtCWPlus\" class=\"sinput\" value=\"20\" onKeyDown=\"CWKeyDown();\"> px</div>"; txtHTML += "<div class=\"coolMenuItem\" style='padding-top: 1px;' onclick=\"SetCWM(txtCWMinus.value);\" onMouseOver=\"txtCWMinus.focus()\"><img src=\"images/blank.gif\" width=\"16\" height=\"16\">列宽 - <input type=\"text\" id=\"txtCWMinus\" class=\"sinput\" value=\"20\" onKeyDown=\"CWKeyDown();\"> px</div>"; objHeadMenu.className = "coolMenu"; objHeadMenu.innerHTML = txtHTML; window.document.body.insertAdjacentElement("afterBegin", objHeadMenu); }
</SCRIPT> <META content="MSHTML 6.00.2800.1170" name=GENERATOR> <script language="JavaScript" type="text/JavaScript"> <!-- function MM_reloadPage(init) { //reloads the window if Nav4 resized if (init==true) with (navigator) {if ((appName=="Netscape")&&(parseInt(appVersion)==4)) { document.MM_pgW=innerWidth; document.MM_pgH=innerHeight; onresize=MM_reloadPage; }} else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) location.reload(); } MM_reloadPage(true); //--> </script> </HEAD> <BODY onLoad="WriteTable();createMenu();" onClick="hideMenu();"> <CENTER> <H4> </H4> <!--// 资料表 ( 开始 ) //--> <TABLE cellSpacing=0 cellPadding=0 border=0> <TBODY> <TR> <TD style="BORDER-RIGHT: white 2px inset; BORDER-TOP: white 2px inset; BORDER-LEFT: white 2px inset; BORDER-BOTTOM: white 2px inset; BACKGROUND-COLOR: scrollbar"> <DIV id=DataTable> </DIV></TD></TR></TBODY></TABLE><!--// 资料表 ( 结束 ) //--> <P> </P> <div id="objHeadMenu" style="position:absolute; width:124px; height:13px; z-index:1; left: 525px; top: 164px; visibility: hidden;" oncontextmenu="return false;"></div> </CENTER></BODY></HTML>
|
|
在ASP中使用断开的记录集
|
来源: 未知
作者: great_domino
更新日期: [2005-03-12]
我们在使用ASP 内置的ADO组件进行数据库编程时,通常是在脚本的开头打开一个连接,并在脚本的最后关闭它,但是就较大脚本而言,在多数情况下连接打开的时间要比它需要打开的时间长得多。因此为了节省服务器资源,应该尽可能关闭连接以释放连接所占有的资源,这种关闭记录集的连接而不关闭记录集的技术叫做断开记录集,这个记录集本身则称为断开的记录集。 下面我们就通过一个实例来说明这种技术的使用方法(NorthWind.mdb是Microsoft Access自带的一个数据库,文件adovbs.inc可在C:\Program Files\Common Files\System\ADO下找到): <% @LANGUAGE = VBScript %> <% Response.Expires = 0 Dim Cnn,objRS, strOut, strQ, strC StrC= "Driver={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("\asp24") & "\NorthWind.mdb;" '建立连接 Set Cnn = Server.CreateObject("ADODB.Connection") Cnn.Open StrC '创建Recordset对象 Set objRS = Server.CreateObject("ADODB.Recordset") objRS.CursorLocation =adUseClient objRS.CursorType = adOpenStatic objRS.LockType = adLockOptimistic strQ = "SELECT 运货商ID, 公司名称, 电话 FROM 运货商 " objRS.Open strQ, Cnn, , , adCmdText Set objRS.ActiveConnection = Nothing '断开记录集 Cnn.Close '关闭连接 Set Cnn = Nothing Response.Write "" '下面使用断开的记录集 Do While (Not objRS.EOF) strOut = objRS("运货商ID") & ", " & objRS("公司名称") & ", " & objRS("电话") Response.Write Server.HTMLEncode(strOut) & "" objRS.MoveNext Loop Response.Write " 准备新增或插入记录: " '若需要更新数据库, 则要重新建立连接 Set Cnn = Server.CreateObject("ADODB.Connection") Cnn.Open strC Set objRS.ActiveConnection = Cnn objRS.Filter = "公司名称 = '吴丰'" If objRS.EOF Then objRS.AddNew objRS("公司名称") = "吴丰" objRS("电话") = "571-7227298" objRS.Update Response.Write "符合该条件的记录不存在, 则新增. " Else objRS("电话") = "571-7227071" Response.Write "符合该条件的记录存在, 则 Update." objRS.Update End If Set objRS.ActiveConnection = Nothing Cnn.close Set Cnn = Nothing objRS.Close Set objRS = Nothing Response.Write "" %>
|
|
梅花雨日历控件2.02版
|
来源: 未知
作者: athossmth
更新日期: [2005-03-12]
感谢meizz和walkingpoison,梅花雨日历控件很好用,我前面的贴子 http://community.csdn.net/Expert/TopicView.asp?id=3575789 发布了英文版(2.01版),通过最近一段时期的使用,根据用户反馈增加了两个内容: 一是,当文本框只读的时候,不能清空其内容,现加入了一个C(Clear)的按钮,可以清空; 二是,下面的一行,原本是可以按月或者是年变更,现在加入了按十年变更的按钮。 代码如下
var bMoveable=true; var _VersionInfo="Version:2.02 2.01&02 Author: Athos;2.0 Author:walkingpoison 1.0 Author: F.R.Huang(meizz) MAIL: meizz@hzcnc.com"; var strFrame; document.writeln('<iframe id=meizzDateLayer Author=wayx frameborder=0 style="position: absolute; width: 144; height: 211; z-index: 9998; display: none"></iframe>'); strFrame='<style>'; strFrame+='INPUT.button{BORDER-RIGHT: #ff9900 1px solid;BORDER-TOP: #ff9900 1px solid;BORDER-LEFT: #ff9900 1px solid;'; strFrame+='BORDER-BOTTOM: #ff9900 1px solid;BACKGROUND-COLOR: #fff8ec;}'; strFrame+='TD{FONT-SIZE: 9pt;}'; strFrame+='</style>'; strFrame+='<scr' + 'ipt>'; strFrame+='var datelayerx,datelayery; '; strFrame+='var bDrag; '; strFrame+='function document.onmousemove() '; strFrame+='{if(bDrag && window.event.button==1)'; strFrame+=' {var DateLayer=parent.document.all.meizzDateLayer.style;'; strFrame+=' DateLayer.posLeft += window.event.clientX-datelayerx;'; strFrame+=' DateLayer.posTop += window.event.clientY-datelayery;}}'; strFrame+='function DragStart() '; strFrame+='{var DateLayer=parent.document.all.meizzDateLayer.style;'; strFrame+=' datelayerx=window.event.clientX;'; strFrame+=' datelayery=window.event.clientY;'; strFrame+=' bDrag=true;}'; strFrame+='function DragEnd(){ '; strFrame+=' bDrag=false;}'; strFrame+='</scr' + 'ipt>'; strFrame+='<div style="z-index:9999;position: absolute; left:0; top:0;" onselectstart="return false"><span id=tmpSelectYearLayer Author=wayx style="z-index: 9999;position: absolute;top: 3; left: 19;display: none"></span>'; strFrame+='<span id=tmpSelectMonthLayer Author=wayx style="z-index: 9999;position: absolute;top: 3; left: 48;display: none"></span>'; strFrame+='<table border=1 cellspacing=0 cellpadding=0 width=142 height=160 bordercolor=#ff9900 bgcolor=#ff9900 Author="wayx">'; strFrame+=' <tr Author="wayx"><td width=142 height=23 Author="wayx" bgcolor=#FFFFFF><table border=0 cellspacing=1 cellpadding=0 width=140 Author="wayx" height=23>'; strFrame+=' <tr align=center Author="wayx"><td width=16 align=center bgcolor=#ff9900 style="font-size:12px;cursor: hand;color: #ffffff" '; strFrame+=' onclick="parent.meizzPrevM()" title="1 Month Before" Author=meizz><b Author=meizz><</b>'; strFrame+=' </td><td width=30 align=center style="font-size:12px;cursor:default" Author=meizz '; strFrame+='onmouseover="style.backgroundColor=\'#FFD700\'" onmouseout="style.backgroundColor=\'white\'" '; strFrame+='onclick="parent.tmpSelectYearInnerHTML(this.innerText)" title="Click to select year"><span Author=meizz id=meizzYearHead></span></td>'; strFrame+='<td width=78 align=center style="font-sizeNULL;cursorNULL" Author=meizz onmouseover="style.backgroundColor=\'#FFD700\'" '; strFrame+=' onmouseout="style.backgroundColor=\'white\'" onclick="parent.tmpSelectMonthInnerHTML(parent.athosMonthNameToNum(this.innerText))"'; strFrame+=' title="Click to select month"><span id=meizzMonthHead Author=meizz></span></td>'; strFrame+=' <td width=16 bgcolor=#ff9900 align=center style="font-sizeNULL;cursorNULL;colorNULLffffff" '; strFrame+=' onclick="parent.meizzNextM()" title="1 Month Later" Author=meizz><b Author=meizz>></b></td></tr>'; strFrame+=' </table></td></tr>'; strFrame+=' <tr Author="wayx"><td width=142 height=18 Author="wayx">'; strFrame+='<table border=1 cellspacing=0 cellpadding=0 bgcolor=#ff9900 ' + (bMoveable? 'onmousedown="DragStart()" onmouseup="DragEnd()"':''); strFrame+=' BORDERCOLORLIGHT=#FF9900 BORDERCOLORDARK=#FFFFFF width=140 height=20 Author="wayx" style="cursorNULL + (bMoveable ? 'move'NULLdefault') + '">'; strFrame+='<tr Author="wayx" align=center valign=bottom>'; strFrame+='<td width=18px style="font-sizeNULL;colorNULLFFFFFF" Author=meizz title="Sunday">S</td>'; strFrame+='<td width=18px style="font-sizeNULL;colorNULLFFFFFF" Author=meizz title="Monday">M</td>'; strFrame+='<td width=18px style="font-sizeNULL;colorNULLFFFFFF" Author=meizz title="Tuesday">T</td>'; strFrame+='<td width=18px style="font-sizeNULL;colorNULLFFFFFF" Author=meizz title="Wednesday">W</td>'; strFrame+='<td width=18px style="font-sizeNULL;colorNULLFFFFFF" Author=meizz title="Thursday">T</td>'; strFrame+='<td width=18px style="font-sizeNULL;colorNULLFFFFFF" Author=meizz title="Friday">F</td>'; strFrame+='<td width=20px style="font-sizeNULL;colorNULLFFFFFF" Author=meizz title="Saturday">S</td>'; strFrame+='</tr>'; strFrame+='</table></td></tr><!-- Author:F.R.Huang(meizz) http://www.meizz.com/ mail: meizz@hzcnc.com 2002-10-8 -->'; strFrame+=' <tr Author="wayx"><td width=142 height=120 Author="wayx">'; strFrame+=' <table border=1 cellspacing=2 cellpadding=0 BORDERCOLORLIGHT=#FF9900 BORDERCOLORDARK=#FFFFFF bgcolor=#fff8ec width=140 height=120 Author="wayx">'; var n=0; for (j=0;j<5;j++){ strFrame+= ' <tr align=center Author="wayx">'; for (i=0;i<7;i++){ strFrame+='<td width=20 height=20 id=meizzDay'+n+' style="font-sizeNULL" Author=meizz onclick=parent.meizzDayClick(this.innerText,0)></td>';n++;} strFrame+='</tr>';} strFrame+=' <tr align=center Author="wayx">'; for (i=35;i<39;i++)strFrame+='<td width=20 height=20 id=meizzDay'+i+' style="font-sizeNULL" Author=wayx onclick="parent.meizzDayClick(this.innerText,0)"></td>'; strFrame+=' <td align=right Author=meizz><span onclick=parent.clearAndCloseLayer() style="font-sizeNULL;cursorNULL;colorNULL00aaaa;"'; strFrame+=' Author=meizz title="Clear"><b>C</b></span> </td>'; strFrame+=' <td align=right Author=meizz><span onclick=parent.closeLayer() style="font-sizeNULL;cursorNULL;colorNULL;"'; strFrame+=' Author=meizz title="Close"><b>X</b></span> </td>'; strFrame+=' <td align=right Author=meizz><a href="mailtoNULL/FONT>athos.liu@gmail.com; meizz@hzcnc.com" style="text-decorationNULL"'; strFrame+=' Author=meizz title="' + _VersionInfo + '"><i>©</i></a> </td>'; strFrame+='</tr>'; strFrame+='</table></td></tr><tr Author="wayx"><td Author="wayx">'; strFrame+=' <table border=0 cellspacing=1 cellpadding=0 width=100% Author="wayx" bgcolor=#FFFFFF>'; strFrame+=' <tr Author="wayx"><td Author=meizz align=left>'; strFrame+=' <input Author=meizz type=button class=button value="←" title="10 Year Before" onclick="parent.meizzPrevY(10)" '; strFrame+=' onfocus="this.blur()" style="font-sizeNULL; heightNULL">'; strFrame+=' <input Author=meizz type=button class=button value="«" title="1 Year Before" onclick="parent.meizzPrevY(1)" '; strFrame+=' onfocus="this.blur()" style="font-sizeNULL; heightNULL">'; strFrame+=' <input Author=meizz class=button title="1 Month Before" type=button '; strFrame+=' value="‹" onclick="parent.meizzPrevM()" onfocus="this.blur()" style="font-sizeNULL; heightNULL"></td><td '; strFrame+=' Author=meizz align=center><input Author=meizz type=button class=button value=td style="colorNULL00007f;background-colorNULL;fontNULL bolder 10pt;" onclick="parent.meizzToday()" '; strFrame+=' onfocus="this.blur()" title="Today" style="font-sizeNULL; heightNULL; cursorNULL"></td><td '; strFrame+=' Author=meizz align=right>'; strFrame+=' <input Author=meizz type=button class=button value="›" onclick="parent.meizzNextM()" '; strFrame+=' onfocus="this.blur()" title="1 Month Later" class=button style="font-sizeNULL; heightNULL">'; strFrame+=' <input Author=meizz type=button class=button value="»" title="1 Year Later" onclick="parent.meizzNextY(1)"'; strFrame+=' onfocus="this.blur()" style="font-sizeNULL; heightNULL">'; strFrame+=' <input Author=meizz type=button class=button value="→" title="10 Year Later" onclick="parent.meizzNextY(10)" '; strFrame+=' onfocus="this.blur()" style="font-sizeNULL; heightNULL">'; strFrame+=' </td></tr></table></td></tr></table></div>';
window.frames.meizzDateLayer.document.writeln(strFrame); window.frames.meizzDateLayer.document.close();
var outObject; var outButton; var outDate=""; var odatelayer=window.frames.meizzDateLayer.document.all; function setday(tt,obj) { if (arguments.length > 2){alert("Sorry, too many parameters");return;} if (arguments.length == 0){alert("Sorry, none parameter!");return;} var dads = document.all.meizzDateLayer.style; var th = tt; var ttop = tt.offsetTop; var thei = tt.clientHeight; var tleft = tt.offsetLeft; var ttyp = tt.type; while (tt = tt.offsetParent){ttop+=tt.offsetTop; tleft+=tt.offsetLeft;} dads.top = (ttyp=="image")? ttop+thei : ttop+thei+6; dads.left = tleft; outObject = (arguments.length == 1) ? th : obj; outButton = (arguments.length == 1) ? null : th; var reg = /^(\d{1,2})\/(\d{1,2})\/(\d+)$/; var r = outObject.value.match(reg); if(r!=null){ r[0]=r[3]; r[3]=r[2]; r[2]=r[1]; r[1]=r[0];
r[2]=r[2]-1; var d= new Date(r[1], r[2],r[3]); if(d.getFullYear()==r[1] && d.getMonth()==r[2] && d.getDate()==r[3]){ outDate=d; } else outDate=""; meizzSetDay(r[1],r[2]+1); } else{ outDate=""; meizzSetDay(new Date().getFullYear(), new Date().getMonth() + 1); } dads.display = '';
event.returnValue=false; }
var MonHead = new Array(12); MonHead[0] = 31; MonHead[1] = 28; MonHead[2] = 31; MonHead[3] = 30; MonHead[4] = 31; MonHead[5] = 30; MonHead[6] = 31; MonHead[7] = 31; MonHead[8] = 30; MonHead[9] = 31; MonHead[10] = 30; MonHead[11] = 31;
var meizzTheYear=new Date().getFullYear(); var meizzTheMonth=new Date().getMonth()+1; var meizzWDay=new Array(39);
function document.onclick() { with(window.event) { if (srcElement.getAttribute("Author")==null && srcElement != outObject && srcElement != outButton) closeLayer(); } }
function document.onkeyup() { if (window.event.keyCode==27){ if(outObject)outObject.blur(); closeLayer(); } else if(document.activeElement) if(document.activeElement.getAttribute("Author")==null && document.activeElement != outObject && document.activeElement != outButton) { closeLayer(); } }
function meizzWriteHead(yy,mm) { odatelayer.meizzYearHead.innerText = String(yy); odatelayer.meizzMonthHead.innerText = athosMonthNumToName(String(mm)); }
function athosMonthNameToNum(mn) { switch (String(mn)) { case "January" : return String(1); case "Feburary" : return String(2); case "March" : return String(3); case "April" : return String(4); case "May" : return String(5); case "June" : return String(6); case "July" : return String(7); case "August" : return String(8); case "September" : return String(9); case "October" : return String(10); case "November" : return String(11); case "December" : return String(12); default : return String(0); } }
function athosMonthNumToName(mm) { switch (mm) { case "1": return String("January"); case "2": return String("Feburary"); case "3": return String("March"); case "4": return String("April"); case "5": return String("May"); case "6": return String("June"); case "7": return String("July"); case "8": return String("August"); case "9": return String("September"); case "10": return String("October"); case "11": return String("November"); case "12": return String("December"); default : return String("UnknownMonth"); } }
function tmpSelectYearInnerHTML(strYear) { if (strYear.match(/\D/)!=null){alert("Year shall be a number.");return;} var m = (strYear) ? strYear : new Date().getFullYear(); if (m < 1000 || m > 9999) {alert("Year shall between 1000 to 9999.");return;} var n = m - 10; if (n < 1000) n = 1000; if (n + 26 > 9999) n = 9974; var s = "<select Author=meizz name=tmpSelectYear style='font-sizeNULL' " s += "onblur='document.all.tmpSelectYearLayer.style.display=\"none\"' " s += "onchange='document.all.tmpSelectYearLayer.style.display=\"none\";" s += "parent.meizzTheYear = this.value; parent.meizzSetDay(parent.meizzTheYear,parent.meizzTheMonth)'>\r\n"; var selectInnerHTML = s; for (var i = n; i < n + 26; i++) { if (i == m) {selectInnerHTML += "<option Author=wayx value='" + i + "' selected>" + i + "</option>\r\n";} else {selectInnerHTML += "<option Author=wayx value='" + i + "'>" + i + "</option>\r\n";} } selectInnerHTML += "</select>"; odatelayer.tmpSelectYearLayer.style.display=""; odatelayer.tmpSelectYearLayer.innerHTML = selectInnerHTML; odatelayer.tmpSelectYear.focus(); }
function tmpSelectMonthInnerHTML(strMonth) { if (strMonth.match(/\D/)!=null){alert("Month shall be a number");return;} var m = (strMonth) ? strMonth NULL Date().getMonth() + 1; var s = "<select Author=meizz name=tmpSelectMonth style='font-size: 12px' " s += "onblur='document.all.tmpSelectMonthLayer.style.display=\"none\"' " s += "onchange='document.all.tmpSelectMonthLayer.style.display=\"none\";" s += "parent.meizzTheMonth = this.value; parent.meizzSetDay(parent.meizzTheYear,parent.meizzTheMonth)'>\r\n"; var selectInnerHTML = s; for (var i = 1; i < 13; i++) { if (i == m) {selectInnerHTML += "<option Author=wayx value='"+i+"' selected>"+ athosMonthNumToName(String(i)) +"</option>\r\n";} else {selectInnerHTML += "<option Author=wayx value='"+i+"'>"+ athosMonthNumToName(String(i)) +"</option>\r\n";} } selectInnerHTML += "</select>"; odatelayer.tmpSelectMonthLayer.style.display=""; odatelayer.tmpSelectMonthLayer.innerHTML = selectInnerHTML; odatelayer.tmpSelectMonth.focus(); }
function closeLayer() { document.all.meizzDateLayer.style.display="none"; } function clearAndCloseLayer() { if (outObject) { outObject.value= ""; closeLayer(); } else {closeLayer(); alert("None control to output!");} }
function IsPinYear(year) { if (0==year%4&&((year%100!=0)||(year%400==0))) return true;else return false; }
function GetMonthCount(year,month) { var c=MonHead[month-1];if((month==2)&&IsPinYear(year)) c++;return c; } function GetDOW(day,month,year) { var dt=new Date(year,month-1,day).getDay()/7; return dt; }
function meizzPrevY(intYears) { if(meizzTheYear > 999 && meizzTheYear <10000){meizzTheYear-=intYears;} else{alert("Year beyond (1000-9999)!");} meizzSetDay(meizzTheYear,meizzTheMonth); } function meizzNextY(intYears) { if(meizzTheYear > 999 && meizzTheYear <10000){meizzTheYear+=intYears;} else{alert("Year beyond (1000-9999)!");} meizzSetDay(meizzTheYear,meizzTheMonth); } function meizzToday() { var today; meizzTheYear = new Date().getFullYear(); meizzTheMonth = new Date().getMonth()+1; today=new Date().getDate(); //meizzSetDay(meizzTheYear,meizzTheMonth); if(outObject){ outObject.value=meizzTheYear + "-" + meizzTheMonth + "-" + today; } closeLayer(); } function meizzPrevM() { if(meizzTheMonth>1){meizzTheMonth--}else{meizzTheYear--;meizzTheMonth=12;} meizzSetDay(meizzTheYear,meizzTheMonth); } function meizzNextM() { if(meizzTheMonth==12){meizzTheYear++;meizzTheMonth=1}else{meizzTheMonth++} meizzSetDay(meizzTheYear,meizzTheMonth); }
function meizzSetDay(yy,mm) { meizzWriteHead(yy,mm); meizzTheYear=yy; meizzTheMonth=mm; for (var i = 0; i < 39; i++){meizzWDay[i]=""}; var day1 = 1,day2=1,firstday = new Date(yy,mm-1,1).getDay(); for (i=0;i<firstday;i++)meizzWDay[i]=GetMonthCount(mm==1?yy-1NULL,mm==1?12NULL-1)-firstday+i+1 for (i = firstday; day1 < GetMonthCount(yy,mm)+1; i++){meizzWDay[i]=day1;day1++;} for (i=firstday+GetMonthCount(yy,mm);i<39;i++){meizzWDay[i]=day2;day2++} for (i = 0; i < 39; i++) { var da = eval("odatelayer.meizzDay"+i) if (meizzWDay[i]!="") { da.borderColorLight="#FF9900"; da.borderColorDark="#FFFFFF"; if(i<firstday) { da.innerHTML="<b><font color=gray>" + meizzWDay[i] + "</font></b>"; da.title=(mm==1?12NULL-1) +"Mn" + meizzWDay[i] + "Dt"; da.onclick=Function("meizzDayClick(this.innerText,-1)"); if(!outDate) da.style.backgroundColor = ((mm==1?yy-1NULL) == new Date().getFullYear() && (mm==1?12NULL-1) == new Date().getMonth()+1 && meizzWDay[i] == new Date().getDate()) ? "#FFD700"NULL; else { da.style.backgroundColor =((mm==1?yy-1NULL)==outDate.getFullYear() && (mm==1?12NULL-1)== outDate.getMonth() + 1 && meizzWDay[i]==outDate.getDate())? "#00ffff" NULLBR> (((mm==1?yy-1NULL) == new Date().getFullYear() && (mm==1?12NULL-1) == new Date().getMonth()+1 && meizzWDay[i] == new Date().getDate()) ? "#FFD700"NULL); if((mm==1?yy-1NULL)==outDate.getFullYear() && (mm==1?12NULL-1)== outDate.getMonth() + 1 && meizzWDay[i]==outDate.getDate()) { da.borderColorLight="#FFFFFF"; da.borderColorDark="#FF9900"; } } } else if (i>=firstday+GetMonthCount(yy,mm)) { da.innerHTML="<b><font color=gray>" + meizzWDay[i] + "</font></b>"; da.title=(mm==12?1NULL+1) +"Mn" + meizzWDay[i] + "Dt"; da.onclick=Function("meizzDayClick(this.innerText,1)"); if(!outDate) da.style.backgroundColor = ((mm==12?yy+1NULL) == new Date().getFullYear() && (mm==12?1NULL+1) == new Date().getMonth()+1 && meizzWDay[i] == new Date().getDate()) ? "#FFD700"NULL; else { da.style.backgroundColor =((mm==12?yy+1NULL)==outDate.getFullYear() && (mm==12?1NULL+1)== outDate.getMonth() + 1 && meizzWDay[i]==outDate.getDate())? "#00ffff" NULLBR> (((mm==12?yy+1NULL) == new Date().getFullYear() && (mm==12?1NULL+1) == new Date().getMonth()+1 && meizzWDay[i] == new Date().getDate()) ? "#FFD700"NULL); if((mm==12?yy+1NULL)==outDate.getFullYear() && (mm==12?1NULL+1)== outDate.getMonth() + 1 && meizzWDay[i]==outDate.getDate()) { da.borderColorLight="#FFFFFF"; da.borderColorDark="#FF9900"; } } } else { da.innerHTML="<b>" + meizzWDay[i] + "</b>"; da.title=mm +"Mn" + meizzWDay[i] + "Dt"; da.onclick=Function("meizzDayClick(this.innerText,0)"); if(!outDate) da.style.backgroundColor = (yy == new Date().getFullYear() && mm == new Date().getMonth()+1 && meizzWDay[i] == new Date().getDate())? "#FFD700"NULL; else { da.style.backgroundColor =(yy==outDate.getFullYear() && mm== outDate.getMonth() + 1 && meizzWDay[i]==outDate.getDate())? "#00ffff"NULL(yy == new Date().getFullYear() && mm == new Date().getMonth()+1 && meizzWDay[i] == new Date().getDate())? "#FFD700"NULL); if(yy==outDate.getFullYear() && mm== outDate.getMonth() + 1 && meizzWDay[i]==outDate.getDate()) { da.borderColorLight="#FFFFFF"; da.borderColorDark="#FF9900"; } } } da.style.cursor="hand" } else{da.innerHTML="";da.style.backgroundColor="";da.style.cursor="default"} } }
function meizzDayClick(n,ex) { var yy=meizzTheYear; var mm = parseInt(meizzTheMonth)+ex; if(mm<1){ yy--; mm=12+mm; } else if(mm>12){ yy++; mm=mm-12; } if (mm < 10){mm = "0" + mm;} if (outObject) { if (!n) { return;} if ( n < 10){n = "0" + n;} outObject.value= mm + "/" + n + "/" + yy ; closeLayer(); } else {closeLayer(); alert("None control to output!");} }
|
|
DHTML+XML+ASP+CSS=树形目录
|
来源: 未知
作者: great_domino
更新日期: [2005-03-12]
树形目录显示程序 问题描述: 在我们项目中常常会出现自关联的数据表,如果我们从整体看去,整个表就呈现为一个树形数据结构(对于复杂的情况,它可能变成一个图)。当我们对这个表进行显示,编辑时,如果不采用好的表现形式,会显得很笨拙,为此,我们开发这样的树形结构的程序。在上一版本中,我们使用的是递归算法来实现,在我们对这个算法评测时发现,对于拥有成千上万条记录的数据库就不再能胜任了,所以在新的算法版本中,我们使用了XML技术,动态的发现数据,以解决一次从服务器下在大量数据的尴尬,同时也遍免了如果表数据结构呈现为图时就会进入死循环的错误。
实际思路: 1、 初始显示时只显示根与二级节点,根与二级节点同在一层次 2、 点击一节点,如果它的子节点区域对象不存在,则建立对象,同时下载数据更新数据,显示所有子节点。 3、 每个节点在建立后都就有相同的功能,如检查子节点是否存在,显示隐藏子节点等等 4、 DHTML+XML+ASP+CSS同时使用 技术难点: 1、 使用xmlhttp接口时乱码问题: 因为在asp输出页面中,缺省的编码方案并不是中文的,那么在客户端页面的xmlhttp中解释时,就会以缺省的方案解析,所以就会出现乱码。为此,我们在Server端的asp页面中,加入如下代码定义编码方案: Response.CharSet="GB2312" Response.ContentType="text/html"
2、 如何在界面上保持上一版本的风格(类资源管理器形式): 在上一版本中,所有的页面内容都是一气呵成的,在控制上采用递归等思想,所有时的界面相对友好,当时本版中的机制发生了变化,内容是有多次合成的 关键问题,img ,span 对象的id 如何确定 经过求证,在界面上,本版本的界面难以与第一界面相同,所以只能保留一部分,但是总体来说,新界面同样也能满足需要
因为在这里不好使用附件,所以只能贴源码了:
---xtree.html-------------------------------------------------------------------
<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> <SCRIPT LANGUAGE=javascript src="xtree.js"> </SCRIPT> <style type="text/css"> <!-- a:link { font-size: 14px; text-decoration: none; color: #0000FF} a:visited { font-size: 14px; color: #0000FF; text-decoration: none} a:hover { font-size: 14px; color: #FF0000; background-color: #CCCC99; text-decoration: none} a:active { font-size: 14px; color: #FFFFFF; background-color: #191970; text-decoration: none} .item{ font-size:14px} --> </style> </HEAD> <BODY leftMargin=0 rightMargin=0 topMargin=0 border=0> <bold>树形菜单演示程序</bold><br> <table border=0> <tr><td nowrap> <span id='oSpanroot' border=0></span><SCRIPT LANGUAGE=javascript>createChildNode("root",0);</SCRIPT></td></tr> </table> </BODY> </HTML>
-------xtree.asp---------------------------------------------------------------
<%@ Language=VBScript %> <% Response.CharSet="GB2312" Response.ContentType="text/html" '''''''''''''''''''''''''''''''Server code start''''''''''''''''''''''''''''''' dim parId,nodeLayer parid=Request.QueryString("parId") nodeLayer=cint(Request.QueryString("nodeLayer"))
if(parid="") then Response.Write("root id can't is null") Response.End() end if if(nodeLayer<0) then nodeLayer=0
end if %> <% strconn="at" strsql="select * from tree where par='"&parid&"'" ''SQL 语句书写要求:在记录集的前面三个字段必须依次为:row_id(惟一的主键)、name(菜单条显示的内容)、par_id(父节点row_id),其它根据需要输出与显示 set conn=server.createobject("ADODB.connection") conn.open strconn
set rs=server.createobject("ADODB.Recordset") rs.open strsql,conn,3,3 i=0 dim row_id row_id="" while not rs.EOF row_id=rs.Fields("row_id").Value name=rs.Fields("name").Value j=0
while j<nodeLayer Response.Write("<img src='blank.bmp'>") j=j+1 wend Response.Write("<img id='objNode"&row_id&"' style='cursor:hand' src='open.bmp' onclick=javascript:createChildNode('"&row_id&"',"&nodeLayer+1&") border=0 align='absmiddle'>") Response.Write("<img src='blank.bmp' border=0 align='absmiddle'>") Response.Write("<a class=item href='view.asp?id="&row_id&"' target='mainFrame'>"&Trim(name)&"</a></br>") '项目内容 Response.Write("<span id='oSpan"&row_id&"' ></span>") '子节点内容区域 i=i+1 rs.MoveNext wend '''''''''''''''''''''''''''''''''''''''''Server Code END '''''''''''''''''''''''''''''''''' %>
---------xtree.js-----------------------------------------------------------------------------
function getChildTree(parId,nodeLayer) //parId:=夫节点id,nodeLayer:=子节点所属层次 { var xmlhttp = new ActiveXObject ("Microsoft.XMLHTTP"); xmlhttp.Open("get", "xtree.asp?parId="+parId+"&nodeLayer="+nodeLayer, false); xmlhttp.Send("Author:taojianbo;Version:2.0"); return xmlhttp.responseText; }
function showHide(objid) //显示,隐藏区域,达到菜单显示的目的 //objid:=区域对象ID的parid部分 { var temp; eval("temp=oSpan"+objid+".style.display"); if(temp=="block") { eval("oSpan"+objid+".style.display='none'"); eval("objNode"+objid+".src='open.bmp'"); } else { eval("oSpan"+objid+".style.display='block'"); eval("objNode"+objid+".src='close.bmp'"); } }//end function
function createChildNode(childNodeId,nodeLayer) //如果子节点内容为空,则初始化,并更新数据 //childNodeId:=子节点对象Id的parid部分 { var temp; eval("temp=oSpan"+childNodeId+".innerHTML"); if(temp=="") { eval("oSpan"+childNodeId+".innerHTML='<div align=right>LOADING...</div><br>'"); temp=new String(getChildTree(childNodeId,nodeLayer)); if(temp.length!=0) { eval("oSpan"+childNodeId+".innerHTML=temp"); eval("objNode"+childNodeId+".src='close.bmp'");//变为减号 } else {//如果temp内容为空,说明未找到子树,则该节点为叶节点,更改相关属性 eval("objNode"+childNodeId+".src='leaf.bmp'");//更改图标 eval("objNode"+childNodeId+".onclick=''"); //取消click事件 eval("oSpan"+childNodeId+".innerHTML=temp");//内容为空 } } else { showHide(childNodeId); } }
|
|
Global.asa使用手册
|
来源: 未知
作者: great_domino
更新日期: [2005-03-12]
Global.asa 文件是一个可选文件,用户可以在该文件中指定事件脚本,并声明具有会话和应用程序作用域的对象。该文件的内容 给用户显示的,而是用来存储事件信息和由应用程序全局使用的对象。该文件的名称必须是 Global.asa 且必须存放在应用程序的 根目录中。每个应用程序只能有一个 Global.asa 文件。
Global.asa 文件只能包含如下内容:
1.应用程序事件
2.会话事件
3.<OBJECT> 声明
TypeLibrary 声明 如果包含的脚本没有用 <SCRIPT> 标记封装,或定义的对象没有会话或应用程序作用域,则服务器将返回错误。服务器会忽略已标 记的但未被应用程序或会话事件使用的脚本以及文件中的 HTML 语句。
可以用任何支持脚本的语言编写 Global.asa 文件中包含的脚本。如果多个事件使用同一种脚本语言,就可以将它们组织在一组 <SCRIPT> 标记中。
当用户保存对 Global.asa 文件所做的更改时,在重新编译 Global.asa 文件之前,服务器会结束处理当前应用程序的所有请 求。在此期间,服务器拒绝其他请求并返回一个错误消息,说明正在重启动应用程序,不能处理请求。
当用户当前的所有请求处理完之后,服务器对每个会话调用 Session_OnEnd 事件,删除所有活动会话,并调用 Application_OnEnd 事件关闭应用程序,然后编译 Global.asa 文件。接下来,用户的请求将启动应用程序并创建新的会话,触 发 Application_OnStart 和 Session_OnStart 事件。
但是,保存 Global.asa 文件中所包含的文件的更改并不能使服务器重新编译 Global.asa。为了让服务器识别包含文件的改动, 必须再保存一下 Global.asa 文件。
在 Global.asa 文件中声明的过程只能从一个或多个与 Application_OnStart、Application_OnEnd、Session_OnStart 和 Session_OnEnd 事件相关的脚本中调用。在基于 ASP 的应用程序中的 ASP 页中,它们是不可用的。
要在应用程序之间共享过程,可在单独的文件中声明这些过程,然后使用服务器端的包含 (SSI) 语句将该文件包含在调用该过程 的 ASP 页中。通常,包含文件的扩展名应为 .inc。
基于 ASP 的应用程序由在其根目录及其子目录中所有文件组成。应用程序在用户首次打开应用程序中的某一 Web 页时启动,在服 务器关闭时终止。应用程序有两个事件,即 Application_OnStart 事件和 Application_OnEnd 事件。
用户可以在 Global.asa 文件中为这些事件指定脚本。当应用程序启动时,服务器在 Global.asa 文件中查找并处理 Application_OnStart 事件脚本。当应用程序终止时,服务器处理 Application_OnEnd 事件脚本。
1.Application_OnStart Application_OnStart 事件在首次创建新的会话(即 Session_OnStart 事件)之前发生。只有 Application 和 Server 内建 对象是可用的。在 Application_OnStart 事件脚本中引用 Session、Request 或 Response 对象将导致错误。
语法 <SCRIPT LANGUAGE=ScriptLanguage RUNAT=Server> Sub Application_OnStart. . . End Sub
</SCRIPT>
参数 ScriptLanguage 指定用于编写事件脚本的脚本语言。它可以是任何支持脚本编写的语言,例如 VB Script 或 JScript。如果多个事件使用同一种 脚本语言,就可以将它们组织在一个 <SCRIPT> 标记下。
2.Application_OnEnd Application_OnEnd 事件在应用程序退出时于 Session_OnEnd 事件之后发生,只有 Application 和 Server 内建对象可用。
语法 <SCRIPT LANGUAGE=ScriptLanguage RUNAT=Server> Sub Application_OnEnd. . . End Sub
</SCRIPT>
参数 ScriptLanguage 指定用于编写事件脚本的脚本编写语言。可以是任何一种支持脚本的语言,例如 VBScript 或 JScript。如果有多个事件使用同 一种脚本编写语言,就可以将它们组织在一组 <SCRIPT> 标记下。 注释 不能在 Application_OnEnd 脚本中调用 MapPath 方法。
当没有会话的用户在打开应用程序中的 Web 页时,Web 服务器会自动创建会话。当超时或服务器调用 Abandon 方法时,服务器 将终止该会话。
会话有两个事件,即 Session_OnStart 事件和 Session_OnEnd 事件。
可以在全局文件 Global.asa 中为这两个事件指定脚本。当会话开始时,服务器在 Global.asa 文件中查找并处理 Session_OnStart 事件脚本。该脚本将在处理用户请求的 Web 页之前处理。在会话结束时,服务器将处理 Session_OnEnd 事件 脚本。
1.Session_OnStart Session_OnStart 事件在服务器创建新会话时发生。服务器在执行请求的页之前先处理该脚本。Session_OnStart 事件是设置会 话期变量的最佳时机,因为在访问任何页之前都会先设置它们。所有内建对象 (Application、ObjectContext、Request、 Response、Server 和 Session) 都可以在 Session_OnStart 事件脚本中使用和引用。
语法 <SCRIPT LANGUAGE=ScriptLanguage RUNAT=Server> Sub Session_OnStart. . .End Sub
</SCRIPT>
参数 ScriptLanguage 指定用于编写事件脚本的脚本编写语言。可以是任何一种支持脚本的语言,例如 VBScript 或 JScript。如果有多个事件使用同 一种脚本编写语言,就可以将它们组织在一组 <SCRIPT> 标记下。 示例 尽管在 Session_OnStart 事件包含 Redirect 或 End 方法调用的情况下 Session 对象仍会保持,然而服务器将停止处理 Global.asa 文件并触发 Session_OnStart 事件的文件中的脚本。
举一个例子,为了确保用户在打开某个特定的 Web 页时始终启动一个会话,就可以在 Session_OnStart 事件中调用 Redirect 方法。当用户进入应用程序时,服务器将为用户创建一个会话并处理 Session_OnStart 事件脚本。您可以将脚本包含在该事件中 以便检查用户打开的页是不是启动页,如果不是,就指示用户调用 Response.Redirect 方法启动网页。其演示如下例所示。
<SCRIPT RUNAT=Server Language=VBScript> Sub Session_OnStart ' Make sure that new users start on the correct ' page of the ASP application.
' Replace the value given to startPage below ' with the virtual path to your application's ' start page.
startPage = "/MyApp/StartHere.asp" currentPage = Request.ServerVariables("SCRIPT_NAME")
' Do a case-insensitive compare, and if they ' don't match, send the user to the start page. if strcomp(currentPage,startPage,1) then Response.Redirect(startPage) end ifEnd Sub</SCRIPT> 上述示例只能在支持 cookie 的浏览器中运行。因为不支持 cookie 的浏览器不能返回 SessionID cookie,所以,每当用户请 求 Web 页时,服务器都会创建一个新会话。这样,对于每个请求,服务器都将处理 Session_OnStart 脚本并将用户重定向到启 动页中。如果您要使用下面的脚本,建议您在启动页上放一个通知,告诉用户该站点要求支持 cookie 的浏览器。
注释 请注意,在 Redirect 方法之后的任何 Session_OnStart 事件脚本都不会执行。因此,应该在您的事件脚本的最后再调用 Redirect 方法。其演示如下例所示。
<SCRIPT LANGUAGE=VBScript RUNAT=Server> Sub Session_OnStart ' Session initialization script Response.Redirect "http:/server/app/StartHere.asp" End sub </SCRIPT> 在上面的例子中,Redirect 方法在执行会话初始化脚本期间隐藏所有显示给客户的文字。
2.Session_OnEnd Session_OnEnd 事件在会话被放弃或超时发生。在服务器内建对象中,只有 Application、Server 和 Session 对象可用。
语法 <SCRIPT LANGUAGE=ScriptLanguage RUNAT=Server> Sub Session_OnEnd. . . End Sub
</SCRIPT>
参数 ScriptLanguage 指定用于编写事件脚本的脚本编写语言。可以是任一支持脚本编写的语言,例如 VBScript 或 JScript。如果有多个事件使用同 一种脚本编写语言,则可以将其组织在一组 <SCRIPT> 标记下。 注释 在 Session_OnEnd 脚本中不能调用 MapPath 方法。
<OBJECT> 声明 用户可以在 global.asa 文件中通过使用扩展的 <OBJECT> 标记创建带有会话或应用程序作用域的对象。该标记是自包含的,且 在任何 <SCRIPT> 标记之外。
在 Global.asa 文件中声明的对象在服务器处理调用该对象之前是不会创建的。这样就只会创建必需的对象,从而节约了资源。
服务器对带有应用程序作用域参数创建的对象不调用 OnStartPage 和 OnEndPage 方法。
语法 <OBJECT RUNAT=Server SCOPE=Scope ID=Identifier {PROGID="progID"¦CLASSID="ClassID"}>. . .
</OBJECT>
参数 Scope 指定对象的作用域。在 Global.asa 文件中,Scope 将被设置为 Session 或 Application。
Identifier 指定对象实例的名称。
ProgID 与类标识相关的标识。无论 ProgID 还是 ClassID 都必须在 <OBJECT> 中指定。ProgID 的格式为 [Vendor.]Component [.Version]。
ClassID 指定 COM 类对象的唯一标识。 无论 ProgID 还是 ClassID 都必须在 <OBJECT> 中指定。 示例 下面的第一个示例使用 ProgID 参数创建一个对象,其会话作用域名为 MyConnection。第二个示例使用 ClassID 参数。
<OBJECT RUNAT=Server SCOPE=Session ID=MyConnection PROGID="ADODB.Connection"> REM Object Script </OBJECT>
<OBJECT RUNAT=Server SCOPE=Session ID=MyConnection CLASSID="Clsid:8AD3067A-B3FC-11CF-A560-00A0C9081C21"> REM Object Script </OBJECT>
注释 在 Global.asa 文件中声明的对象可被应用程序中的任何脚本使用。例如,在声明了下列对象的情况下。
---GLOBAL.ASA--- <OBJECT RUNAT=Server SCOPE=Session ID=MyAd PROGID="MSWC.AdRotator"> </OBJECT>
可以从应用程序中的任何一页引用 MyAd 对象:
---SOME.ASP--- <%= MyAd.GetAdvertisement("/ads/adrot.txt") %>
TypeLibrary 声明
ActiveX 组件常常要描述类型库中该组件支持的常量。类型库是一个文件,其中包含有关 ActiveX 组件所支持的对象和类型的信 息。如果用户的 Web 应用程序依赖于已在类型库中声明了类型的 ActiveX 对象,就可以在 Global.asa 文件中声明其类型。这 样做以后,就可以在应用程序范围内从任何脚本引用已在类型库中声明了的数据类型。
有关在 ASP 中使用常量的详细信息,请参阅“使用变量和常量”。
语法 <!--METADATA TYPE="TypeLib" FILE="file" UUID="typelibraryuuid" VERSION="majorversionnumber.minorversionnumber" LCID="localeid" --> 参数 file 类型库的绝对路径。如果提供了该参数和 typelibraryuuid 参数,则 file 将用于标识类型库。file 参数和 typelibraryuuid 参数都是必选项。
typelibraryuuid 类型库统一的唯一标识。file 参数和 typelibraryuuid 参数都是必选项。
majorversionnumber 用于选择版本。如果找不到所需的版本,将返回错误。该参数是可选项。
minorversionnumber 用于选择版本。如果找不到所需的版本,将返回错误。该参数是可选项。
localeid 现场标识,用于类型库。如果找不到所需的现场,将返回错误。该参数是可选项。 错误信息 服务器可返回下列错误消息。
错误 说明 ASP 0222 指定的类型库无效。METADATA 标记包含无效的类型库指定。 ASP 0223 找不到类型库。METADATA 包含的类型库指定与注册表项不符。 ASP 0224 类型库无法加载。ASP 无法加载 METADATA 标记中指定的类型库。 ASP 0225 类型库不能重叠。ASP 无法从在 METADATA 标记中指定的类型库中创建 Type Library Wrapper 对象。
注释 最好将 METADATA 标记写在 Global.asa 文件的开始位置。但是,无论是内部和外部 SCRIPT 标记,都可以出现在 Global.asa 文件中的任何位置。
通过将类型库的名称加在该常量的前面,可以避免对常量的不明确引用。例如,ADODB.adErrItemNotFound 会比 adErrItemNotFound 更明确。
如果使用 Microsoft Visual InterDev 创建 global.asa 文件,则 METADATA 标记将包含可选的 STARTSPAN 和 ENDSPAN 关 键字。而 IIS 则会忽略这两个关键字。
示例 下面示例中的 MyComponent 是用 Visual Basic 5.0 编写的。MyComponent 使用下列语句定义常量 MyError。
Public Const MyError = "You are not using MyComponent correctly."
类型库包含在 mycomponent.lib 中,该文件安装在下面的目录中。
C:\MyComponent
下面的 METADATA 标记包含在 MyApp 应用程序的 global.asa 文件中。该示例使用可选的 STARTSPAN 和 ENDSPAN 标记。而 IIS 则不需要这两个标记。
<!--METADATA TYPE="TypeLib" FILE="MyComponent.lib" -->
现在,MyApp 应用程序中的任何 ASP 都包含如下脚本:
<% Dim MyVar Set MyVar = Server.CreateObject("MyComponent.MyClass") Currentreturn = MyVar.MyMethod If Currentreturn = False Response.Write(MyError) End If %>
|
|
自动适应输入内容高度的TextBox控件(摘自罗永浩全集)
|
来源: 未知
作者: cmoremore
更新日期: [2005-03-12]
关于Web开发上面UI布局的问题,我上次介绍了一个可以自动适应输入内容宽度的TextBox控件,它可以解决在布局时预留控件大小和用户数入内容多少上的矛盾。但是由于那个控件被限制了只能做为单行输入使用:(,在输入大块文本时就力不从心了,那么就再做一个可自动适应高度的TextBox。
原理和那个适应宽度的TextBox查不多,只是这个反而更加简单,因为在高度方向上增长不会破坏页面的整体布局效果(宽度上的如果在页内会挤走别的元素的),所以就不需要使用Agent TextBox来作为实际录入的容器了,直接把<TextArea>增高就行了。
响应onpropertychange事件,同步内容和<TextArea>的高度。当然如果完全根据内容增高可能也会因为内容太多而变得难看,就设置了一个最大高度限制属性。控件效果如下:
最大高度为200px的AutoTextBox Demo: 200)?200:this.scrollHeight)+(this.offsetHeight-this.clientHeight+1)" name=ataRemark rows=1 cols=1>
最大高度为200px但初始高度为3rows的AutoTextBox Demo: 200)?200:Math.max(this.minHeight,this.scrollHeight))+(this.offsetHeight-this.clientHeight)" name=ataRemark rows=3 minheight="63">
高度增长无限制的AutoTextBox Demo: 如果控件的MaxHeight属性小于或等于0,那么增长高度无限制。
附 AutoTextBox 控件源码
|
|
ASP中一个字符串处理类加强版
|
来源: 未知
作者: liuhuidev
更新日期: [2005-03-12]
以下是源代码:
<% class StringOperations
'*********************************************************************** '' @功能说明: 把字符串换为char型数组 '' @参数说明: - str [string]: 需要转换的字符串 '' @返回值: - [Array] Char型数组 '************************************************************************ public function toCharArray(byVal str) redim charArray(len(str)) for i = 1 to len(str) charArray(i-1) = Mid(str,i,1) next toCharArray = charArray end function '**************************************************************************** '' @功能说明: 把一个数组转换成一个字符串 '' @参数说明: - arr [Array]: 需要转换的数据 '' @返回值: - [string] 字符串 '**************************************************************************** public function arrayToString(byVal arr) for i = 0 to UBound(arr) strObj = strObj & arr(i) next varrayToString = strObj end function
'**************************************************************************** '' @功能说明: 检查源字符串str是否以chars开头 '' @参数说明: - str [string]: 源字符串 '' @参数说明: - chars [string]: 比较的字符/字符串 '' @返回值: - [bool] '**************************************************************************** public function startsWith(byVal str, chars) if Left(str,len(chars)) = chars then startsWith = true else startsWith = false end if end function '**************************************************************************** '' @功能说明: 检查源字符串str是否以chars结尾 '' @参数说明: - str [string]: 源字符串 '' @参数说明: - chars [string]: 比较的字符/字符串 '' @返回值: - [bool] '**************************************************************************** public function endsWith(byVal str, chars) if Right(str,len(chars)) = chars then endsWith = true else endsWith = false end if end function '**************************************************************************** '' @功能说明: 复制N个字符串str '' @参数说明: - str [string]: 源字符串 '' @参数说明: - n [int]: 复制次数 '' @返回值: - [string] 复制后的字符串 '**************************************************************************** public function clone(byVal str, n) for i = 1 to n value = value & str next clone = value end function '**************************************************************************** '' @功能说明: 删除源字符串str的前N个字符 '' @参数说明: - str [string]: 源字符串 '' @参数说明: - n [int]: 删除的字符个数 '' @返回值: - [string] 删除后的字符串 '**************************************************************************** public function trimStart(byVal str, n) value = Mid(str, n+1) trimStart = value end function '**************************************************************************** '' @功能说明: 删除源字符串str的最后N个字符串 '' @参数说明: - str [string]: 源字符串 '' @参数说明: - n [int]: 删除的字符个数 '' @返回值: - [string] 删除后的字符串 '**************************************************************************** public function trimEnd(byVal str, n) value = Left(str, len(str)-n) trimEnd = value end function '**************************************************************************** '' @功能说明: 检查字符character是否是英文字符 A-Z or a-z '' @参数说明: - character [char]: 检查的字符 '' @返回值: - [bool] 如果是英文字符,返回TRUE,反之为FALSE '**************************************************************************** public function isAlphabetic(byVal character) asciiValue = cint(asc(character)) if (65 <= asciiValue and asciiValue <= 90) or (97 <= asciiValue and asciiValue <= 122) then isAlphabetic = true else isAlphabetic = false end if end function
'**************************************************************************** '' @功能说明: 对str字符串进行大小写转换 '' @参数说明: - str [string]: 源字符串 '' @返回值: - [string] 转换后的字符串 '**************************************************************************** public function swapCase(str) for i = 1 to len(str) current = mid(str, i, 1) if isAlphabetic(current) then high = asc(ucase(current)) low = asc(lcase(current)) sum = high + low return = return & chr(sum-asc(current)) else return = return & current end if next swapCase = return end function '**************************************************************************** '' @功能说明: 将源字符串str中每个单词的第一个字母转换成大写 '' @参数说明: - str [string]: 源字符串 '' @返回值: - [string] 转换后的字符串 '**************************************************************************** public function capitalize(str) words = split(str," ") for i = 0 to ubound(words) if not i = 0 then tmp = " " end if tmp = tmp & ucase(left(words(i), 1)) & right(words(i), len(words(i))-1) words(i) = tmp next capitalize = arrayToString(words) end function
'**************************************************************************** '' @功能说明: 将源字符Str后中的'过滤为'' '' @参数说明: - str [string]: 源字符串 '' @返回值: - [string] 转换后的字符串 '**************************************************************************** public function checkstr(Str) If Trim(Str)="" Or IsNull(str) Then checkstr="" else checkstr=Replace(Trim(Str),"'","''") end if End function
'**************************************************************************** '' @功能说明: 将字符串中的str中的HTML代码进行过滤 '' @参数说明: - str [string]: 源字符串 '' @返回值: - [string] 转换后的字符串 '**************************************************************************** Public Function HtmlEncode(str) If Trim(Str)="" Or IsNull(str) then HtmlEncode="" else str=Replace(str,">",">") str=Replace(str,"<","<") str=Replace(str,Chr(32)," ") str=Replace(str,Chr(9)," ") str=Replace(str,Chr(34),""") str=Replace(str,Chr(39),"'") str=Replace(str,Chr(13),"") str=Replace(str,Chr(10) & Chr(10), "</p><p>") str=Replace(str,Chr(10),"<br> ") HtmlEncode=str end if End Function
'**************************************************************************** '' @功能说明: 计算源字符串Str的长度(一个中文字符为2个字节长) '' @参数说明: - str [string]: 源字符串 '' @返回值: - [Int] 源字符串的长度 '**************************************************************************** Public Function strLen(Str) If Trim(Str)="" Or IsNull(str) Then strlen=0 else Dim P_len,x P_len=0 StrLen=0 P_len=Len(Trim(Str)) For x=1 To P_len If Asc(Mid(Str,x,1))<0 Then StrLen=Int(StrLen) + 2 Else StrLen=Int(StrLen) + 1 End If Next end if End Function
'**************************************************************************** '' @功能说明: 截取源字符串Str的前LenNum个字符(一个中文字符为2个字节长) '' @参数说明: - str [string]: 源字符串 '' @参数说明: - LenNum [int]: 截取的长度 '' @返回值: - [string]: 转换后的字符串 '**************************************************************************** Public Function CutStr(Str,LenNum) Dim P_num Dim I,X If StrLen(Str)<=LenNum Then Cutstr=Str Else P_num=0 X=0 Do While Not P_num > LenNum-2 X=X+1 If Asc(Mid(Str,X,1))<0 Then P_num=Int(P_num) + 2 Else P_num=Int(P_num) + 1 End If Cutstr=Left(Trim(Str),X)&"..." Loop End If End Function
end class %> |
|
改进性能和样式的 24个 ASP 技巧
|
来源: 未知
作者: linfengxia
更新日期: [2005-03-12]简介
技巧 1:在 Web 服务器上缓存常用数据
技巧 2:在 Application 或 Session 对象中缓存常用数据
技巧 3:在 Web 服务器磁盘上缓存数据和 HTML
技巧 4:避免在 Application 或 Session 对象中缓存非灵活组件
技巧 5:不要在 Application 或 Session 对象中缓存数据库连接
技巧 6:妙用 Session 对象
技巧 7:在 COM 对象中封装代码
技巧 8:晚点获取资源,早点释放资源
技巧 9:进程外的执行将牺牲可靠性
技巧 10:显式使用选项
技巧 11:在子例程和函数中使用局部变量
技巧 12:将常用数据复制到脚本变量
技巧 13:避免重新定义数组
技巧 14:使用响应缓冲
技巧 15:批处理内嵌脚本和 Response.Write 语句
技巧 16:在开始长时间的任务之前先使用 Response.IsClientConnected
技巧 17:使用 <OBJECT> 标记实例化对象
技巧 18:使用 ADO 对象和其他组件的 TypeLib 绑定
技巧 19:利用浏览器的验证能力
技巧 20:在循环中避免字符串串联
技巧 21:启用浏览器和代理缓存
技巧 22:尽可能使用 Server.Transfer 替代 Response.Redirect
技巧 23:在目录 URL 尾部加斜线
技巧 24:避免使用服务器变量
--------------------------------------------------------------------------------
简介
性能是一个特性。您需要预先设计性能,或是在日后重新编写应用程序。换句话说,什么是最大限度优化 Active Server Pages (ASP) 应用程序性能的好策略?
本文为优化 ASP 应用程序和"Visual Basic(R) 脚本编辑器 (VBScript)"提供了许多技巧。对许多陷阱和缺陷进行了讨论。本文所列的建议均在 http://www.microsoft.com 及其他站点上进行了测试,而且工作正常。本文假定您对 ASP 开发有基本的理解,包括对 VBScript 和/或 JScript、ASP Application、ASP Session 和其他 ASP 内部对象(请求、响应和服务器)。
ASP 的性能,通常不止取决于 ASP 代码本身。我们并不想在一篇文章中囊括所有的至理名言,只在最后列出与性能相关的资源。这些链接包括 ASP 和非 ASP 主题,包括"ActiveX(R) 数据对象 (ADO)"、"部件对象模型 (COM)"、数据库和"Internet 信息服务器 (IIS)"配置。这些是我们喜欢的链接 - 务请关注它们。
技巧 1:在 Web 服务器上缓存常用数据
典型的 ASP 页从后端数据库检索数据,然后将结果转换为超文本标记语言 (HTML)。无论数据库的速度如何,从内存检索数据要比从后端数据库检索数据快得多。从本地硬盘读取数据通常也要比从数据库检索数据快得多。因此,通常可以通过在 Web 服务器(在内存或磁盘)上缓存数据来改善性能。
缓存是典型的空间与时间的折衷。如果恰当地缓存数据,您将看到性能会有惊人的提高。为使缓存发挥效力,它必须保持经常重用的数据,而且重新计算这些数据的代价是昂贵的或比较昂贵的。如果缓存充满了垃圾数据,则是对存储器的浪费。
不经常变化的数据也是缓存的候选数据,因为您无须担心数据与数据库的同步问题。组合框、引用表、DHTML 碎片、可扩展标记语言 (XML) 字符串、菜单项和站点配置变量(包括数据源名称 (DSN)、Internet 协议 (IP) 地址和 Web 路径)都是缓存的候选数据。注意,您可以缓存数据的表示而不是数据本身。如果 ASP 页不经常更改,而且缓存的成本也非常高(例如,整个产品目录),请考虑预先生成 HTML,而不是在每次请求时重新绘制。
数据应缓存在何处,有哪些缓存策略?数据经常缓存在 Web 服务器内存或 Web 服务器磁盘上。下面两个技巧讨论这些选项。
技巧 2:在 Application 或 Session 对象中缓存常用数据
ASP Application 和 Session 对象为在内存中缓存数据提供了方便的容器。既可以将数据赋予 Application 对象,也可将数据赋予 Session 对象,这些数据在 HTTP 调用中将保留在内存中。Session 数据按用户存储,而 Application 数据在所有用户间共享。
何时将数据载入 Application 或 Session?通常,在 Application 或 Session 启动时加载数据。要在 Application 或 Session 启动时加载数据,请在下面两函数中添加相应的代码: Application_OnStart() 或 Session_OnStart() 。这两个函数应该位于 Global.asa;如果没有,可以添加这些函数。也可以在第一次需要数据时加载数据。要进行上述操作,请在 ASP 页中添加一些代码(或编写可重用的脚本函数),这些代码检查数据是否存在,并在数据不存在时加载数据。这是称为迟缓计算的经典性能技术的例子 - 在您的确需要它之前,不进行计算。请看例子:
<% Function GetEmploymentStatusList Dim d d = Application("EmploymentStatusList") If d = "" Then ' FetchEmploymentStatusList 函数(不显示) ' 从 DB 中取出数据,返回数组 d = FetchEmploymentStatusList() Application("EmploymentStatusList") = d End If GetEmploymentStatusList = d End Function %>
可以为每一块所需的数据编写类似的函数。
数据应该以什么格式存储?任何变量类型均可存储,因为所有脚本变量是各不相同的。例如,可以存储字符串、整型或数组。通常,您将以这些变量类型之一存储 ADO 记录集的内容。若要获取 ADO 记录集衍生的数据,可以手工将数据复制到 VBScript 变量中,每次一个字段。使用一个 ADO 记录集保留函数 GetRows()、GetString() 或 Save() (ADO 2.5),会更快更简便。完整而详细的内容已超出了本文的范围。下面的演示函数使用了 GetRows() 来返回记录集数据的数组:
' 取记录集,以数组返回 Function FetchEmploymentStatusList Dim rs Set rs = createObject("ADODB.Recordset") rs.Open "select StatusName, StatusID from EmployeeStatus", _ "dsn=employees;uid=sa;pwd=;" FetchEmploymentStatusList = rs.GetRows() ' 以数组返回数据 rs.Close Set rs = Nothing End Function
对上面示例的进一步改进应当是缓存该列表的 HTML,而不是缓存数组。下面是一个简单的范例:
' 取记录集,以"HTML 选项"列表返回 Function FetchEmploymentStatusList Dim rs, fldName, s Set rs = createObject("ADODB.Recordset") rs.Open "select StatusName, StatusID from EmployeeStatus", _ "dsn=employees;uid=sa;pwd=;" s = "<select name=""EmploymentStatus">" & vbCrLf Set fldName = rs.Fields("StatusName") ' ADO 字段绑定 Do Until rs.EOF ' 下面一行违背了不要进行字符串连接, ' 但这是可以的,因为我们正在建立高速缓存 s = s & " <option>" & fldName & "</option>" & vbCrLf rs.MoveNext Loop s = s & "</select>" & vbCrLf rs.Close Set rs = Nothing ' 参见尽早释放 FetchEmploymentStatusList = s ' 以字符串返回数据 End Function
在正常的情况下,可以在 Application 或 Session 作用域中缓存 ADO 记录集本身。有两个警告:
ADO 必须为标记的自由线程 必须使用断开连接的记录集。 如果不能保证满足这两个要求,请不要缓存 ADO 记录集。在下面的非灵活组件和不要缓存连接技巧中,我们将讨论在 Application 或 Session 作用域中存储 COM 对象的危险。
如果在 Application 或 Session 作用域中存储数据,这些数据将一直保留在那儿,直到在程序中改变它、Session 过期或 Web 应用程序重新启动时为止。数据需要更新如何处理?若要用手工强制更新应用程序数据,可以调用只允许管理员访问的数据更新 ASP 页。另外,还可以通过函数,周期地自动刷新数据。下面的示例存储带缓存数据的时间戳,在指定时间间隔后刷新数据。
<% ' 未显示错误处理... Const update_INTERVAL = 300 ' 刷新时间间隔,以秒计
' 函数返回雇佣状态列表 Function GetEmploymentStatusList updateEmploymentStatus GetEmploymentStatusList = Application("EmploymentStatusList") End Function
' 定期更新缓存的数据 Sub updateEmploymentStatusList Dim d, strLastupdate strLastupdate = Application("Lastupdate") If (strLastupdate = "") Or _ (update_INTERVAL DateDiff("s", strLastupdate, Now)) Then
' 注意:此处可能有两个或多个调用。这是可以的,只不过 ' 产生几个不必要的取指令罢了(就此有一个工作区)
' FetchEmploymentStatusList 函数(不显示) ' 从 DB 中取数据,返回一个数组 d = FetchEmploymentStatusList()
' 更新 Application 对象。用 Application.Lock() ' 来确保一致的数据 Application.Lock Application("EmploymentStatusList") = d Application("Lastupdate") = CStr(Now) Application.Unlock End If End Sub
其他示例,请参阅具有 Application 数据的最快列表框(英文)。
请注意,在 Session 或 Application 对象中缓存大型数组并非上策。在访问数组元素之前,脚本语言的语法要求建立整个数组的临时副本。例如,如果在 Application 对象中缓存了将美国邮政编码映射到本地气象站的字符串数组,该字符串数组有 100,000 个元素,ASP 在找出一个字符串之前,必须将所有 100,000 个气象站复制到临时数组中。在这种情况下,建立带自定义方法的自定义组件,来存储气象站 - 或使用一个字典组件,也许更好。
请不要在倒洗澡水时把孩子一同倒掉,对这种观点的一个新的注解是:数组提供了对内存中相邻关键-数据对的快速查找和存储。索引字典比索引数组要慢。您应该根据具体情况选择能够提供最佳性能的数据结构。
技巧 3:在 Web 服务器磁盘上缓存数据和 HTML
有时,数据过多不能在内存中进行缓存。"过多"是一种定性的判断;它取决于打算消耗的内存量,还有缓存项的数量和这些项的检索频率。总之,如果有过多的数据要在内存中缓存,请考虑以文本或 XML 文件的形式,在 Web 服务器的硬盘上缓存数据。可以将在磁盘上缓存数据和在内存中缓存数据组合起来,为站点建立最优的缓存策略。
注意,在度量单个 ASP 页的性能时,在磁盘上检索数据不一定比从数据库中检索数据快。但是,缓存减轻了数据库和网络的负荷。在高负荷情况下,这将明显提高总体通信量。在查询成本很高时缓存查询的结果,缓存便非常有效,例如多表联合或复杂的存储过程,或缓存大型的结果集。按照惯例,测试竞争方案。
ASP 和 COM 提供了几种构建磁盘缓存方案的工具。ADO 记录集的 Save() 和 Open() 函数,保存和加载磁盘上的记录集。您可以使用这些方法重写上面 Application 数据缓存技巧中的范例代码,用 Save() 文件替换向 Application 对象写入数据的代码。
还有其他一些处理文件的组件:
Scripting.FileSystemObject 使您能够创建、读取和写入文件。 MSXML 是随 Internet Explorer 提供的 Microsoft(R) XML 解析器,它支持保存和加载 XML 文档。 LookupTable 对象(在 MSN 上使用的范例)是从磁盘加载简单列表的良好选择。 最后,请考虑在磁盘上缓存数据的表示,而不是数据本身。预制的 HTML 可以作为 .htm 或 .asp 文件存储在磁盘上;超级链接可以直接指向这些文件。可以使用商业工具,如 XBuilder 或 Microsoft(R) SQL Server 的 Internet 发行功能来自动化 HTML 生成过程。另外,可以将 HTML 片段 #include 到 .asp 文件。还可以使用 FileSystemObject 从磁盘读取 HTML 文件或使用 XML 进行早期调整(英文)。
技巧 4:避免在 Application 或 Session 对象中缓存非灵活组件
虽然在 Application 或 Session 对象中缓存数据是个好主意,但是缓存 COM 对象可能有严重缺陷。将常用 COM 对象嵌入 Application 或 Session 对象通常具有吸引力。遗憾的是,很多 COM 对象,包括用 Visual Basic 6.0 或更早版本编写的 COM 对象,在 Application 或 Session 对象中存储时将导致严重的瓶颈。
特别是任何非灵活组件,在 Session 或 Application 对象中缓存时将导致性能瓶颈。灵活组件是标记为 ThreadingModel=Both 的组件(它聚集了自由线程汇集器 (FTM))或标记为 ThreadingModel=Neutral 的组件(Windows(R) 2000 和 COM+ 中新增的"中性"模型。)下列组件是非灵活的:
自由线程组件(除非它们聚集了 FTM)。 单元线程组件。 单线程组件。 已配置组件(Microsoft Transaction Server (MTS)/COM+ 库和服务器包/应用程序)为非灵活组件,除非它们是"中性"线程的。单元线程组件和其他非灵活组件最适于在页作用域工作(也就是说,它们在单个 ASP 页上创建和销毁)。
在 IIS 4.0 中,标记为 ThreadingModel=Both 的组件被视为灵活的。在 IIS 5.0 中,这已经不够了。组件不仅必须标记为 Both,而且还必须聚集 FTM。灵活性文章说明了如何使得用"活动模板库"编写的 C++ 组件聚集 FTM。请注意,如果组件缓存接口指针,这些指针本身必须为灵活的、或者必须存储在"COM 全局接口表 (GIT)"中。如果不能重新编译 Both 线程组件,使它聚集 FTM,则可以将该组件标记为 ThreadingModel=Neutral 。另外,如果不希望 IIS 进行灵活性检查(这样,希望非灵活组件能够存储在 Application 或 Session 作用域中),可以在 metabase 中设置 AspTrackThreadingModel 为 True 。不主张更改 AspTrackThreadingModel 。
如果试图在 Application 对象中存储用 Server.createObject 创建的非灵活组件,IIS 5.0 将产生错误。可以通过在 Global.asa 中使用 <object runat=server scope=application ...> 解决该问题,但是不主张这样做,因为这将导致汇集和串行化,说明如下。
如果缓存非灵活组件,会发生什么错误呢?缓存在 Session 对象中的非灵活组件,将把会话"锁定"到某个 ASP 工作器线程。ASP 维护着一个工作器线程池,它向请求提供服务。通常,新的请求由第一个可用的工作器线程来处理。如果 Session 被锁定到某个线程,则该请求将不得不等待它所关联的线程变为可用。打个比方:您进入一个超市,挑选了一些食品,然后在第 3 号收款台交款。从这以后,每当您在这个超市购买食品,都不得不始终在第 3 号收款台交款,即使是在其他收款台人少或没人时。
将非灵活组件存储在 Applicaton 作用域甚至会对性能产生更严重的影响。ASP 将不得不创建专用的线程来运行非灵活的、Applicaton 作用域内的组件。这将导致两种后果:所有调用不得不被汇集到该线程,而且所有调用被串行化。汇集意味着:参数不得不存储在内存的共享区;对该专用线程执行昂贵的上下文切换;组件的方法被执行;结果汇集到共享区域;以及经过另一个昂贵的上下文切换,使控制权返回原来的线程。串行化意味着所有方法必须一个挨一个地运行(同一时刻只能运行一个方法)。两个不同的 ASP 工作器线程不可能同时执行共享组件上的方法。这将扼杀并行机制,尤其是在多处理器计算机上。更坏的是,所有非灵活的、Application 作用域内的组件都将共享一个线程("Host STA"),所以串行化的影响更加严重。
是否感到困惑?下面我们提出几个通用规则。如果您正在用 Visual Basic (6.0) 或更早版本编写对象,请不要将它们缓存在 Application 或 Session 对象中。如果您不知道对象的线程模型,就不要缓存它。不要缓存非灵活对象,而应当在每页上创建并释放它们。对象将直接运行在 ASP 工作器线程上,这样,将不会发生汇集或串行化。如果 COM 对象正运行在 IIS 框中,而且如果它们没有花很长时间来初始化和取消,性能将是足够的。注意,不要用该方法使用单线程对象。小心:VB 可以创建单线程的对象!如果您必须以该方式使用单线程的对象(如 Microsoft Excel 电子表格),则不要期望有很高的吞吐量。
当 ADO 被标记为自由线程时,则缓存 ADO 记录集是安全的。要将 ADO 标记为自由线程,请使用 Makfre15.bat 文件,该文件通常位于如下目录中:\\Program Files\Common\System\ADO。
警告: 如果您正在用 Microsoft Access 作为数据库,则不应当将 ADO 标记为自由线程。通常,ADO 记录集还必须是断开连接的,如果您不能控制站点的 ADO 配置(例如,您是独立的软件厂商 [ISV],将 Web 应用程序卖给客户,然后由他们来管理他们自己的配置),那么不缓存记录集可能会更好。
词典组件也是灵活对象。LookupTable 从数据文件加载它的数据,并且它对组合框数据和配置信息是有用的。来自 Duwamish Books 的 PageCache 对象提供了目录语义,和 Caprock Dictionary 的表现一样。这些对象或它们的派生对象可以构成有效缓存策略的基础。注意,Scripting.Dictionary 对象不是灵活的,所以不应当存储在 Application 或 Session 作用域。
技巧 5:不要在 Application 或 Session 对象中缓存数据库连接
缓存 ADO 连接通常是不好的策略。如果一个 Connection 对象存储在 Application 中,并在所有页上使用,那么所有页将竞争使用该连接。如果 Connection 对象存储在 ASP Session 对象中,那么将为每个用户创建数据库连接。这将连接池的好处毁于一旦,并对 Web 服务器和数据库产生不必要的压力。
取代缓存数据库连接的方法是,在每个使用 ADO 的 ASP 页上创建并取消 ADO 对象。这是个有效的方法,因为 IIS 具有内置的数据库连接池。更准确的说,IIS 自动启用 OLEDB 和 ODBC 连接池。这确保了创建并取消每个页上的连接将是有效的。
由于被连接的记录集中存储有对数据库连接的引用,所以,不应当在 Application 或 Session 对象中缓存被连接的记录集。但是,可以安全地缓存断开连接的记录集,因为它不包含对其数据连接的引用。要断开记录集的连接,请执行如下两个步骤:
Set rs = Server.createObject("ADODB.RecordSet") rs.CursorLocation = adUseClient ' 第 1 步
' 植入带数据的记录集 rs.Open strQuery, strProv
' 现在断开记录集同数据提供者和数据源的连接 rs.ActiveConnection = Nothing ' 第 2 步
有关连接池的详细信息,请参阅 ADO 和 SQL Server(英文)引用。
技巧 6:妙用 Session 对象
在肯定了在 Applications 和 Sessions 中缓存的优点之后,我们建议您避免使用 Session 对象。下面将会谈到,当用于忙碌站点时,Sessions 有几个缺点。所谓忙碌,通常是指站点每秒请求数百页或同时有数千个用户。该技巧对于必须进行水平扩展的站点,即那些利用多个服务器来适应负载或执行容错功能的站点来说,更加重要。对于较小的站点,如 intranet 站点,Sessions 的便利,与开销相比也是值得的。
为了翻新,ASP 自动为每个访问 Web 服务器的用户创建一个 Session。每个 Session 有大约 10 KB 内存开销(在存储在 Session 中的任何数据中是最高的),并使所有的请求都慢了一点。Session 一直保持活动状态,直到达到可配置的超时(通常 20 分钟)为止。
Session 最大的问题不是性能而是可伸缩性。Session 不能跨越 Web 服务器;一旦在一个服务器上创建了 Session,它的数据就保持在那里。这意味着,如果您在 Web 领域中使用 Sessions,您将不得不为每个用户的请求设计一种策略,以便始终将这些请求引向用户的 Session 所在的服务器。这被称为将用户"粘"到 Web 服务器上。术语"粘性会话"即来源于此。由于 Session 没有保持到磁盘上,所以,当 Web 服务器崩溃时,被"粘住"的用户将丢失他们的 Sessions 状态。
用于实施粘性会话的策略包括硬件和软件解决方案。如 Windows 2000 Advanced Server 中的网络负载平衡解决方案和 Cisco 公司的"本地指向器"解决方案可以实施粘性会话,但以牺牲一些可伸缩性为代价。这些解决方案并不完美。我们不主张您现在全盘推翻您的软件解决方案(我们过去常用 ISAPI 筛选器和 URL 矫直对方案进行检查)。
Application 对象也不能跨越服务器;如果您需要在 Web 领域内共享并更新 Application 数据,则需要使用后端数据库。但只读的 Application 数据在 Web 领域中仍然有用。
如果只是为了增加正常运行时间(用于处理故障转移和服务器维护),大多数执行重要任务的站点将需要部署至少两台 Web 服务器。所以,在设计执行重要任务的应用程序时,您将需要实施"粘性会话",或者简单地避开 Sessions 以及其他任何在单个 Web 服务器上存储用户状态的状态管理技术。
如果当前没有使用 Sessions,请确保将它们关闭。可以通过"Internet 服务管理器"(请参阅 ISM 文档)来为应用程序执行该操作。如果决定使用 Sessions,可以采取几个方法来将对性能的影响降低到最小。
可以将不需要 Sessions 的内容(如"帮助"屏幕、访问者区域等)移动到关闭了 Sessions 的、单独的 ASP 应用程序中。可以逐页提示 ASP:在给定的页中您不需要 Session 对象;使用位于 ASP 页顶端的如下指令:
<% @EnableSessionState=False %>
使用该指令的一个很好的原因是,Session 给框架集带来了有趣的问题。ASP 保证任何时候只执行一个来自 Session 的请求。这样可以确保如果浏览器为一个用户请求了多个页时,在每一时刻只有一个 ASP 请求将进入 Session;这就避免了在访问 Session 对象时出现多线程问题。遗憾的是,结果,框架集中的所有页均被以串行化方式绘制,一个接一个地,而不是同时地。这样,用户可能不得不等待很长时间才能得到所有框架内容。这意味着:如果某些框架页不信任 Session,一定要使用 @EnableSessionState=False 指令告诉 ASP。
作为使用 Session 对象的替代方式,有很多方法可以用来管理 Session 状态。对于状态数量较小的情况(不到 4 KB),通常建议使用 Cookies、QueryString 变量和隐藏形式的变量。对于较大数量的数据,如购物推车,则使用后端数据库是最合适的选择。关于在 Web 服务器领域中的状态管理技术已经有很多资料。详细信息,请参阅 会话状态(英文)。
技巧 7:在 COM 对象中封装代码
如果您有很多 VBScript 或 JScript,那么您可以通过把代码移动到已编译的 COM 对象来经常改进它们的性能。已编译的代码通常比被解释代码运行得更快。已编译的 COM 对象可以通过"早期绑定"访问其他 COM 对象,这种调用 COM 对象方法的手段,比脚本所使用的"后期绑定"更有效。
将代码封装在 COM 对象种有如下好处(超越性能):
COM 对象是将表达逻辑与业务逻辑分隔开来的好办法。 COM 对象启用了代码重用。 很多开发商发现,用 VB、C++ 或 Visual J++ 书写的代码,比 ASP 更容易调试。 COM 对象有一些缺点,包括初始开发时间以及需要不同的编程技巧。需要警告您的是,封装"少"量的 ASP 可能会导致性能降低,而不是提高。通常,在少量 ASP 代码封装到 COM 对象时出现这样的情况。这时候,创建和调用 COM 对象的开销,超过了已编译代码的好处。至于 ASP 脚本和 COM 对象代码怎样合并才能产生最佳性能还有待测试。注意,与 Windows NT(R) 4.0/IIS 4.0 相比,Microsoft 已经在 Windows 2000/IIS 5.0 中极大地提高了脚本和 ADO 性能。这样,已编译代码对 ASP 代码的性能优势已经随着 IIS 5.0 的引入而降低。
有关在 ASP 中使用 COM 对象的优缺点的更多讨论,请参阅 ASP 组件准则和用 COM 和 Microsoft Visual Basic 6.0 对分布式应用程序进行编程(英文)。如果您的确部署了 COM 组件,要对它们进行强度测试是非常重要的。实际上,所有 ASP 应用程序都应当作为正式过程进行强度测试。
技巧 8:晚点获取资源,早点释放资源
这是个小技巧。通常,最好晚点获取资源而要早点释放资源。这些资源包括 COM 对象、文件句柄和其他资源。
ADO 连接和记录集是这种优化的首要目标。当您使用完记录集,就是说用它的数据打印完一个表格后,请立即将它释放,而不是等到页的末尾。将您的 VBScript 变量设置为 Nothing 是最好的做法。不要让记录集简单地脱离作用域。同时,应当释放任何有关的 Command 或 Connection 对象。(不要忘了对记录集或"连接"调用 Close() ,在将它们设置为 = Nothing 之前。)这将缩短数据库必须为您调整资源的时间跨度,并将数据库连接尽可能快地释放给连接池。
技巧 9:进程外的执行将牺牲可靠性
ASP 和 MTS/COM+ 都有允许您以可靠性换取性能的配置选项。当建立和部署应用程序时,应当理解这种交换。
ASP 选项
ASP 应用程序可以配置为以三种方式之一运行。在 IIS 5.0 中引入了术语"隔离级"来描述这些选项。三个隔离级值分别是低、中和高:
低级隔离。该隔离级在所有版本的 IIS 中受到支持,并且是最快的。它在主 IIS 进程 Inetinfo.exe 中执行 ASP。如果 ASP 应用程序崩溃,则 IIS 也将崩溃。(要在 IIS 4.0 下重新启动 IIS,Web 站点管理员需要使用工具,如 InetMon,来监视站点,如果服务器失败,将运行批处理文件来重新启动服务器。而 IIS 5.0 则引入了可靠的重新启动,它将自动重新启动失败的服务器。) 中级隔离。IIS 5.0 引入了这个新隔离级,它称为进程外的,这是因为 ASP 运行在 IIS 进程之外。在中级隔离中,所有被配置按"中级"运行的 ASP 应用程序,将共享单个进程空间。这将减少在一个服务器上运行多个进程外的 ASP 应用程序所需的进程数。中级是 IIS 5.0 中默认的隔离级。 高级隔离。在 IIS 4.0 和 IIS 5.0 中受到支持,高级隔离也是进程外的。如果 ASP 崩溃,则 Web 服务器并不崩溃。ASP 应用程序将在下一个 ASP 请求时自动重新启动。使用高级隔离,每个被配置为按高级运行的 ASP 应用程序,将在其自己的进程空间中运行。这样可以保护 ASP 应用程序彼此不受干扰。它的缺点是它需要为每个 ASP 应用程序建立独立的进程。当需要在一个服务器上主持十多个应用程序时,会增加很多开销。 那么,哪个选项是最好的呢?在 IIS 4.0 中,运行进程外的应用程序会极大地影响性能。在 IIS 5.0 中,做了许多工作,使得进程外运行 ASP 应用程序对性能产生的影响降到了最低。实际上,在大多数测试中,在 IIS 5.0 中的 ASP 进程外应用程序,要比 IIS 4.0 中的进程内应用程序运行得更快。无论如何,进程内(低隔离级)在两种平台上仍然产生了最好的性能。但是,如果您的命中率相对较低或最大吞吐量较低,选择低隔离级不会有太大的好处。所以,除非您需要每个 Web 服务器每秒处理数百或数千个页面,否则没有必要选择低隔离级。同样,应当测试多种配置并判断哪种情形最适合您。
注意: 当您进程外运行 ASP 应用程序(中级或高级隔离)时,则在 NT4 上它们将运行在 MTS 中,而在 Windows 2000 上它们将运行在 COM+ 中。即,在 NT4 上它们运行在 Mtx.exe 中,而在 Windows 2000 上它们运行在 DllHost.exe 中。在"任务管理器"中,您可以看见这些正在运行的进程。还可以看见 IIS 如何为进程外的 ASP 应用程序配置 MTS 程序包或 COM+ 应用程序。
COM 选项
COM 组件也有三个配置选项,虽然与 ASP 选项不完全相似。COM 组件可以被:"不配置"、配置为"库应用程序"或配置为"服务器应用程序"。"不配置"是指不向 COM+ 注册组件。组件将运行在调用者的进程空间,就是说,它们是"进程中"的。"库应用程序"也是进程中的,但受惠于 COM+ 的服务,包括安全性、事务和环境支持。"服务器应用程序"被配置为在其自己的进程空间中运行。
您可能看到,不配置的组件比库应用程序优点稍微多些。您还可能看到"库应用程序"比"服务器应用程序"有很大的性能优点。这是因为"库应用程序"与 ASP 运行在同一个进程中,而"服务器应用程序"则运行在自己的进程中。内部进程调用的开销要比进程内调用的开销大得多。而且,当在进程之间传递数据(如记录集)时,必须在两个进程之间复制所有的数据。
缺点!当使用"COM 服务器应用程序"时,如果要在 ASP 和 COM 之间传递对象,请确保对象实现"按值汇集",即 MBV。实现 MBV 的对象将其自身从一个进程复制到另一个进程。这比另一种方式好,在另一种方式中,对象留在创建它的进程中,而其他进程则重复调用创建使用该对象的进程。被断开连接的 ADO 记录集将是按值汇集的,已连接的记录集则不是。Scripting.Dictionary 并不实现 MBV,不会在进程之间传递。最后,要另外告诉 VB 程序员的是:MBV 不是通过传递参数 ByVal 获得的。MBV 是由原始组件创作者实现的。
怎么办?
如果您想要以性能与可靠性的合理交换来完成您的配置,我们的推荐如下:
在 IIS 4.0 上,使用 ASP 的低隔离级别,并使用"MTS 服务器包"。 在 IIS 5.0 上,使用 ASP 的中隔离级别,并使用"COM+ 库应用程序"。 这些是很一般的准则;通常让公司以中或高隔离级别运行 ASP,而单一目的的 Web 服务器可运行于低隔离级别。请权衡折中并自行决定满足需求的配置。
技巧 10:显式使用选项
在 .asp 文件中显式使用 选项 Explicit 。置于 .asp 文件开头的这一指令,强制开发人员声明所有要使用的变量。许多开发人员认为这有助于调试应用程序,因为它避免了错误键入变量名称而不经意地新建变量(例如, MyXLMString=... 而非 MyXMLString=) 。
也许更重要的是,声明的变量比未声明的变量快。实际上,脚本运行时,在每次使用未声明变量时按照名称引用。而声明的变量,在编译或运行时分配了序号。这样,声明的变量按照该序号引用。由于 选项 Explicit 强制变量声明,因此保证声明了所有变量而实现快速访问。
技巧 11:在子例程和函数中使用局部变量
局部变量是在子例程和函数中声明的变量。在子例程和函数中,局部变量访问要快于全局变量访问。使用局部变量还可以使代码更加清晰,因此尽可能使用局部变量。
技巧 12:将常用数据复制到脚本变量
在 ASP 中访问 COM 时,应该将常用的对象数据复制到脚本变量中。这将削减 COM 方法的调用,COM 方法的调用与访问脚本变量相比,要相对昂贵些。在访问 Collection 和 Dictionary 对象时,这一技术也可以削减了昂贵的查找。
通常,如果打算多次访问对象数据,请将数据放入脚本变量。该优化的主要目标是 Request 变量(Form 和 QueryString 变量)。例如,您的站点可能传递一个名为 UserID 的 QueryString。假定该 UserID 变量要在特定页中引用 12 次。请不要调用 Request("UserID") 12 次,而在 ASP 页的开头将 UserID 赋予某个变量。然后就在页中使用该变量。这将节省 11 次 COM 方法调用。
在实际中,访问 COM 属性或方法暗藏着繁复的过程和大量的开销。下面是一个示例,它只是些相当普通的代码(从语法上讲):
Foo.bar.blah.baz = Foo.bar.blah.qaz(1) If Foo.bar.blah.zaq = Foo.bar.blah.abc Then ' ...
在运行这段代码时,将发生下列事件:
变量 Foo 被解析为全局变量。 变量 bar 被解析为 Foo. 的成员。这将产生 COM 方法调用。 变量 blah 被解析为 Foo.bar 的成员。这也将产生 COM 方法调用。 变量 qaz 被解析为 foo.bar.blah 的成员。是的,这也将产生 COM 方法调用。 调用 Foo.bar.blah.quaz(1) 。又一次产生 COM 方法调用。理解这幅图了吗? 执行步骤 1 到 3 将再次解析 baz 。系统不知道调用 qaz 是否更改对象模型,因此步骤 1 到 3 必须再次执行解析 baz 。 将 baz 解析为 Foo.bar.blah 的成员。进行属性置入。 再次执行步骤 1 到 3 并解析 zaq 。 再次执行步骤 1 到 3 并解析 abc 。 正如所见,这是非常可怕的低效率(而且非常慢)。用 VBScript 编写该代码实现的快速方法为:
Set myobj = Foo.bar.blah ' 对 blah 做一次解析 Myobj.baz = myobj.qaz(1) If Myobj.zaq = Myobj.abc Then '...
如果您使用的是 VBScript 5.0 或更高版本,则可用 With 语句来写这段代码:
With Foo.bar.blah .baz = .qaz(1) If .zaq = .abc Then '... ... End With
请注意该技巧对 VB 编程同样有效。
技巧 13:避免重新定义数组
尽量避免 Redim 数组。从关心性能的角度来说,如果计算机受物理内存的限制,最好一开始将数组的维数设置为最差方案 - 而不要将维数设置为最佳方案,再根据需要重新定义维数。这并不意味着明知道不需要那么多而就是应该分配太多的内存。
下面代码展示了您没有必要地使用了 Dim 和 Redim 来解决。
<% Dim MyArray() Redim MyArray(2) MyArray(0) = "hello" MyArray(1) = "good-bye" MyArray(2) = "farewell" ... ' 一些别的代码中,这里您不需要更多的空间,然后 ... Redim Preserve MyArray(5) MyArray(3) = "more stuff" MyArray(4) = "even more stuff" MyArray(5) = "yet more stuff" %>
更好的办法是只须一开始 Dim 数组为正确的大小(本例中为 5),而不是 Redim 数组,再加大数组。这可能会浪费一点儿内存(如果没有用尽所有元素),但是获得的是速度。
技巧 14:使用响应缓冲
您可以通过打开"响应缓冲区"来缓冲值得输出的整个页。这将写入浏览器的数据量降为最小,从而提高总体性能。每次写入都会有大量开销(包括 IIS 和通过电缆发送的数据量),因此写入的越少越好。TCP/IP 的工作效率,在发送少量大的数据块时明显高于发送大量小的数据块时,原因在于它的低速启动和 Nagling 算法(用于最小化网络阻塞)。
打开响应缓冲有两种方法。第一种,可以使用"Internet 服务管理器"为整个应用程序打开响应缓冲。这是推荐的方法,在 IIS 4.0 和 IIS 5.0 中,在默认情况下,为新的 ASP 应用程序打开响应缓冲。第二种,逐页将下列代码行放在 ASP 页的开头,从而启用响应缓冲:
<% Response.Buffer = True %>
该行代码必须在任何响应数据写入浏览器之前执行(也就是说,在任何 HTML 出现在 ASP 脚本中之前和任何 Cookies 被使用 Response.Cookies 集合设置之前)。通常,最好是为整个应用程序打开响应缓冲。这允许省略上面每页中的代码行。
Response.Flush
响应缓冲的通病是用户感觉 ASP 页响应迟钝(尽管总体响应时间改善了),因为他们需要等到整个页生成后才能看见该页。对于长时间运行的页面,可以通过设置 Response.Buffer = False 关闭响应缓冲。但是,更好的策略是使用 Response.Flush 方法。该方法刷新由 ASP 绘入浏览器的所有 HTML。例如,绘制了具有 1,000 行的表的 100 行后,ASP 可以调用 Response.Flush 强制将结果绘制到浏览器;这允许用户在其余的行准备好之前先看到头 100 行。该技术给了您两个举世无双的好东西 - 响应缓冲与浏览器中数据的逐步显示的组合。
(注意,在上面 1,000 行表的示例中,许多浏览器,在看到 </table> 结束标记之前不会开始绘制表。请检查目标浏览器的支持性。要解决该问题,请将表分割为具有较少行的多个表,然后在每个表后面调用 Response.Flush 。新版本的 Internet Explorer 将在表完全下载之前绘制表,特别是如果指定表的列宽则绘制速度更快;这避免强制 Internet Explorer 通过度量每个单元格的内容来计算列宽。)
响应缓冲的另一个通病是在生成大型页时将使用服务器的大量内存。对于该问题,除了要求生成大型页的技巧外,还可以通过巧妙地使用 Response.Flush 来解决。
技巧 15:批处理内嵌脚本和 Response.Write 语句
VBScript 语法 <% = expression %> 将" 表达式 "的值写入 ASP 输出流。如果响应缓冲没有打开,则这些语句的每一句都会导致通过网络,以许多小型包的形式,向浏览器写入数据。这是非常慢的。另外,解释少量脚本和 HTML,将导致在脚本引擎和 HTML 之间切换,也降低了性能。因此,请使用下面技巧:用对 Response.Write 的一个调用,替换内嵌的密集组合表达式。例如,在下面范例中,每行每字段有一个对响应流的写入,每行都有许多 VBScript 和 HTML 之间的切换:
<table> <% For Each fld in rs.Fields %> <th><% = fld.Name %></th> <% Next While Not rs.EOF %> <tr> <% For Each fld in rs.Fields %> <td><% = fld.Value %></td> <% Next </tr> <% rs.MoveNext Wend %> </table>
下面是更有效的代码,每行中有一个对响应流的写入。所有代码均包含在一个 VBScript 块内:
<table> <% For each fld in rs.Fields Response.Write ("<th>" & fld.Name & "</th>" & vbCrLf) Next While Not rs.EOF Response.Write ("<tr>") For Each fld in rs.Fields %> Response.Write("<td>" & fld.Value & "</td>" & vbCrLf) Next Response.Write "</tr>" Wend %> </table>
当响应缓冲被禁用时,本技巧的作用更大。最好启用响应缓冲,然后观察批处理 Response.Write 是否对性能有帮助。
(在这一特例中,构建表的主体的嵌套循环 ( While Not rs.EOF... ) 可以被精心构造的、对 GetString 的调用所替代。)
技巧 16:在开始长时间的任务之前先使用 Response.IsClientConnected
如果用户失去耐心,他们可以在开始执行他们的请求之前放弃 ASP 页。如果他们单击了 Refresh 或跳转到服务器的其他页上,在 ASP 请求队列的末尾将有一个新的请求,而在队列的中间有一个断开连接的请求。这通常发生在服务器处于高负荷的情况下(它有一个很长的请求队列,相应的响应时间也很长),这只能使情况更糟。如果用户不再连接,将没有执行 ASP 页的点(特别是低速、重量级的 ASP 页)。可以使用 Response.IsClientConnected 属性检查这种情况。如果它返回 False ,则应调用 Response.End 并放弃该页的剩余内容。实际上,每当 ASP 要执行新的请求时,IIS 5.0 便将该方法编码,来检查队列中的请求有多长。如果在那里超过了 3 秒钟,ASP 会检查客户是否仍然连接着,如果客户已断开连接,就立即结束该请求。您可以使用 metabase 中的 AspQueueConnectionTestTime 设置,调整这 3 秒的超时时间。
如果有某页执行了很长时间,您可能还想按一定的时间间隔检查 Response.IsClientConnected 。在启用响应缓冲之后,按一定的时间间隔执行 Response.Flush ,告诉用户正在进行的是哪些事情,是个好办法。
注意 在 IIS 4.0 中, Response.IsClientConnected 将不能正常工作,除非首先执行 Response.Write 。如果启用了缓冲,也需要执行 Response.Flush 。在 IIS 5.0 中则不必如此 - Response.IsClientConnected 工作得很好。在任何情况下, Response.IsClientConnected 都要有些开销,所以,只有在执行至少要用 500 毫秒(如果想维持每秒几十页的吞吐量,这是一个很长的时间了)的操作前才使用它。作为通常的规则,不要在紧密循环的每次迭代中调用它,例如当绘制表中的行,可能每 20 行或每 50 行调用一次。
技巧 17:使用 <OBJECT> 标记实例化对象
如果需要引用不能在所有代码路径中使用的对象(尤其是服务器 - 或应用程序 - 作用域的对象),则使用 Global.asa 中的 <object runat=server id=objname> 标记来声明它们,而不是使用 Server.createObject 方法。 Server.createObject 立刻创建对象。如果以后不使用那个对象,就不要浪费资源。 <object id=objname> 标记声明了 objname,但实际上 objname 此时并没有创建,直到它的方法或属性第一次被使用时才创建。
这是迟缓计算的另一个例子。
技巧 18:使用 ADO 对象和其他组件的 TypeLib 声明
当使用 ADO 时,开发人员经常包含 adovbs.txt 来获得对 ADO 不同常量的访问权。该文件必须包含在要使用这些常量的每一页中。该常量文件非常大,给每个 ASP 页增加了很多编译时间和脚本大小方面的开销。
IIS 5.0 提供了绑定到组件类型库的能力。允许您在每个 ASP 页上引用一次类型库并使用它。每页不需要为编译常量文件付出代价,并且组件开发人员不必为在 ASP 中的使用而生成 VBScript #include 文件。
要访问 ADO 类型库,请将下列语句之一放入 Global.asa 中。
<!-- METADATA NAME="Microsoft ActiveX Data Objects 2.5 Library" TYPE="TypeLib" UUID="{00000205-0000-0010-8000-00AA006D2EA4}" -->
或者
<!-- METADATA TYPE="TypeLib" FILE="C:\Program Files\Common Files\system\ado\msado15.dll" -->
技巧 19:利用浏览器的验证能力
流行的浏览器具有对以下功能的高级支持,例如 XML、DHTML、Java 小程序以及远程数据服务。请尽量利用这些功能。所有这些技术,都可以通过执行客户端的验证和数据缓存,减少了与 Web 服务器之间的往返。如果您正在运行智能浏览器,该浏览器可以为您进行一些验证(例如,在运行 POST 之前检查信用卡的校验和否有效)。重申一次,请尽量使用这些功能。由于削减了客户端到服务器的往返路程,将减少对 Web 服务器的压力,并且削减了网络通信量(虽然发送给浏览器的初始页面可能更大),服务器访问的所有后端资源也削减了。而且用户不必经常提取新页,使用户的感受好一些。这并不减轻对服务器端验证的需要。还是应该经常进行服务器端的验证。这样能够防止由于某些原因从客户端来的坏数据,例如黑客,或者不运行客户端验证程序的浏览器。
许多站点由独立于浏览器创建的 HTML 组成。这一点经常阻碍开发人员利用可以提高性能的流行浏览器功能。对于真正高性能的、必须关心浏览器的站点,良好的策略是针对流行的浏览器优化您的页面。在 ASP 中使用"浏览器性能组件",很容易检测到浏览器的功能。诸如 Microsoft FrontPage 等工具,能帮助您设计使用所希望的目标浏览器和 HTML 版本的代码。更详细的讨论,请查看 When is Better Worse? Weighing the Technology Trade-Offs(英文)。
技巧 20:在循环中避免字符串串联
许多人在循环中创建类似这样的字符串:
s = "<table>" & vbCrLf For Each fld in rs.Fields s = s & " <th>" & fld.Name & "</th> " Next
While Not rs.EOF s = s & vbCrLf & " <tr>" For Each fld in rs.Fields s = s & " <td>" & fld.Value & "</td> " Next s = s & " </tr>" rs.MoveNext Wend
s = s & vbCrLf & "</table>" & vbCrLf Response.Write s
这种方法有几个问题。首先,重复连接字符串所花费的时间,以二次方曲线的速率增长;粗略地计算,运行循环所花费的时间,与记录数乘以字段数的平方成正比。举一个简单的例子,便能清楚地说明这一点。
s = "" For i = Asc("A") to Asc("Z") s = s & Chr(i) Next
在第一次迭代中,得到一个字符的字符串 "A" 。在第二次迭代中,VBScript 必须重新分配字符串并复制两个字符 "AB" 到 s 。在第三次迭代中,它必须再次重新分配 s ,并复制三个字符到 s 。在第 N 次(26 次)迭代中,它必须重新分配并复制 N 个字符到 s 。就是 1+2+3+...+N 的和,为 N*(N+1)/2 次复制。
在以上记录集的例子中,如果有 100 条记录和 5个字段,则内部的循环将执行 100*5 = 500 次,并且完成所有复制和重新分配所花费时间,将与 500*500 = 250,000 成正比。对一个大小适度的记录集,将有很多次复制。
在该例子中,代码可以改进:字符串的连接将被 Response.Write() 或内嵌脚本 ( <% = fld.Value %> ) 所替代。如果打开响应缓冲,这个操作将会很快,因为 Response.Write 仅仅将数据添加到响应缓冲的末尾。不再重新分配,因而非常有效。
特别是在将 ADO 记录集转换到 HTML 表时,请考虑使用 GetRows 或 GetString。
如果用 JScript 连接字符串,强烈建议使用 += 操作符;即用 s += "某字符串", 而不是 s = s + "某字符串" 。
技巧 21:启用浏览器和代理缓存
默认情况下,ASP 禁用浏览器和代理中的缓存。这将很有意义,因为 ASP 生来就是动态的,具有潜在地对时间敏感的信息。如果有一个不需要对每次查看进行刷新的页,则应该启用浏览器和代理缓存。这使得浏览器和代理能在某一段时间内,使用某一页的缓存副本,这时间的长短可以控制。缓存能明显减轻服务器负荷,使用户的感受好一些。
哪种动态页可以缓存?举例说明:
天气页,每 5 分钟更新一次。 列出新闻的主页或新闻发布的主页,每天更新 2 次。 公共基金运营列表,基本的统计数小时更新 1 次。 请注意,使用浏览器或代理缓存,只有很少的命中被记录到 Web 服务器上。如果想精确测量所有页面查看或者张贴广告,也许不喜欢使用浏览器和代理缓存。
浏览器缓存是由 Web 服务器发往浏览器的 HTTP 截至期限标题控制的。ASP 提供了两种发送标题的机制。要将页面设置为在未来某个分钟数后过期,请设置 Response.Expires 属性。以下的例子通知浏览器:内容在 10 分钟后过期:
<% Response.Expires = 10 %>
设置 Response.Expires 为负数或 0 则禁用缓存。一定要使用较大的负数,例如 -1000 (大于一天),来克服服务器时钟和浏览器时钟之间的差异。第二个属性 Response.ExpiresAbsolute ,允许设置内容过期的指定时间:
<% Response.ExpiresAbsolute = #May 31,2001 13:30:15# %>
如果不想使用 Response 对象设置过期时间,可以将 <META> 标记写入 HTML,通常写在 HTML 文件的 <HEAD> 内部。一些浏览器会响应这条指令,但代理不会。
<META HTTP-EQUIV="Expires" VALUE="May 31,2001 13:30:15">
最后,可以标识内容对 HTTP 代理缓存是否有效,请使用 Response.CacheControl 属性。设置属性为"Public",允许代理缓存内容。
<% Response.CacheControl = "Public" %>
默认情况下,该属性设置为"Private"。注意,不应当为显示某用户专用数据的页启用代理缓存,因为代理也许为属于其他用户的用户页面服务。
技巧 22:尽可能使用 Server.Transfer 替代 Response.Redirect
Response.Redirect 通知浏览器,请求一个不同的页面。该函数经常用于重定向用户到登录或错误页面。既然重定向强制一个新页请求,浏览器就必须做两次到 Web 服务器的往返,而且 Web 服务器必须处理额外的请求。IIS 5.0 引入一个新的函数, Server.Transfer ,该函数执行传送到相同服务器上的不同 ASP 页。这样避免了额外的、从浏览器到 Web 服务器的往返,从而改善了整体系统性能,同时改善了对用户的响应时间。请查看重定向中的新方向(英文),它讨论了 Server.Transfer 和 Server.Execute 。
也可以查看Leveraging ASP in IIS 5.0中有关 IIS 5.0 和 ASP 3.0 新功能的完全列表。(英文)
技巧 23:在目录 URL 尾部加斜线
相关的技巧是,一定要定在指向目录的 URL 尾部加斜线 (/) 。如果省略了斜线,浏览器将向服务器提出请求,仅通知它正寻找一个目录。然后浏览器发出第二个请求,在 URL 末尾添加斜线,然后服务器将那个目录的默认文档作为响应,或者如果没有默认文档并且目录浏览已被启用,就以目录列表作为响应。添加了斜线便省去了第一个没用的往返。出于对用户的友好,也许想要在显示的名称的末尾省略斜线。
例如,写:
<a href="http://msdn.microsoft.com/workshop/" title="MSDN Web Workshop">" target=_blank>http://msdn.microsoft.com/workshop</a>
它还适用于指向在 Web 站点主页的 URL:请使用下面的: <a href=",不要用' target=_blank>http://msdn.microsoft.com/">,不要用 <a href="./' target=_blank>http://msdn.microsoft.com">.
技巧 24:避免使用服务器变量
访问服务器变量将引起 Web 站点向服务器提出特殊的请求,然后收集所有的服务器变量,并不止是需要的那个。这好像从发霉的阁楼中的文件夹中检索某条特殊的信息一样。当想要某条信息时,在访问该信息之前必须先上阁楼取得文件夹。这与请求服务器变量时,性能访问出现第一次请求服务器变量所发生的一样。后续的对其他服务器变量的访问不会引起性能访问。
从不访问不合格的 Request 对象(例如, Request("Data") )。对于不在 Request.Cookies 、 Request.Form 、 Request.QueryString 或 Request.ClientCertificate 中的项,有对 Request.ServerVariables 的隐含调用。 Request.ServerVariables 集合比其他集合慢很多。
|
|
和她分手了,是因为我横穿马路……
|
和蓝分手了,蓝是个很好的女孩,很漂亮也很温柔,虽然很多朋友说我离开她很傻,可我还是放手了,虽然我很舍不的。
第一天, 她没有起床,把自己用被子捂的严严实实的,她宿舍的人都不敢去安慰她,她一天都没有吃饭,连刷牙洗脸都没有,晚上睡觉的时候我听到她在被子里抽泣。
第二天, 今天她吃饭了,是她的宿舍同学强制性的让她吃的,她的眼眶红红的,我总说她是个爱哭鬼,她每次都噘着小嘴说她不是。
第三天, 今天她穿的很妖艳,走进一家酒吧,喝了好多酒,用一种很诱惑的眼光环视全场,好多人上来搭腔“小姐,你好漂亮啊”。她喝了很多,当一个年纪可以做她爸爸的男人对她说“小姐,我送你回家吧”的时候她把手中的酒全泼在他的脸上,那个该死的老头扬起他的手掌就要打下去的时候,小睦他们来了,救了蓝,这一切我都知道,我就在酒吧的一个角落里看着。
第四天, 今天她早早就起床了,忙忙碌碌一上午,然后把自己关在浴室里好久,当舍友们踹门进去的时候都惊呼到:好干净啊。
第五天, 她开始学习了,其实她原来学习很好,我们开始后受我影响她的成绩也退步了,这也好,转移一下注意力,恢复的也快。
三个月后。。。。她做了学生会主席,她越来越能干,也开朗了不少,马上她就要靠研了。
一年后。。。。。在她身边的男人很多,比我优秀的也很多,可她根本没在意过,不过她和凌很好,校园里传他们的关系很暧昧。她只是把他当哥哥,可是流言是挡不住的。
三年后。。。。。她要结婚了,新郎是凌,她在写结婚请贴,一张,两张,三张,,,写到第十二张的时候她哭了,趴在桌上眼泪完全抑制不住,我上前一看,所有的喜贴新郎写的都是我的名字。
我也很想哭,可是鬼魂是不能哭的,我没有眼泪。
三年前,我横穿马路,遇上车祸,手里提着要给她庆祝生日的蛋糕。 |
文章收藏 乱闪 发表于 2005/3/17 13:10:03 |
| |
中国简史
|
盘古说:我开; 女娲说:我补; 共工说:我撞; 神农说:我尝; 精卫说:我填; 夸父说:我追; 后羿说:我射; 嫦娥说:没射着! 黄帝说:我们做什么; 尧说:我让; 舜说:我也让; 禹说:咱爷们怎么办? 启说:让他们球! 桀说:好玩; 汤说:造反有理了; 夏亡了…… 纣说:痛快; 武王说:我也反了; 商亡了…… 幽王说:点火; 褒姒说:刺激; 周也亡了…… 干将说:我铸; 专诸说:我舞; 荆柯说:我刺; 赢政说:没刺着…… 始皇说:我修; 姜女说:我哭; 陈胜说:有种; 项羽说:我举; 刘邦说:我斩; 秦亡了…… 孔子说:我仁; 孟子说:我义; 老子说:我无为; 庄子说:我逍遥; 韩非子说:把他们全抓了。 张良说:我出谋划策; 韩信说:我统帅三军; 萧何说:我运筹帷幄; 高祖说:老婆,怎么办; 吕后说:全喀嚓了。 文景说:我治; 武帝说:我兴; 光武说:我中兴; 献帝说:我说了不算。 张骞说:我通; 班超说:我也通; 苏武说:通个屁! 卫青说:我打; 霍去病说:我也打; 李广说:我还打; 昭君嫣然晕笑,遂天下太平。 董卓说:我势大; 吕布说:我人帅; 貂婵说:你们俩谁厉害? 董卓完蛋了。 曹操说:快帮我脱鞋迎老许; 刘备说:快给我牵驴来访诸葛; 孙权说:周郎自有妙计安天下; 周瑜说:加油,烧死老曹; 诸葛说:天下三分,人人有份; 司马昭说:向刘备同志学习; 晋开始了。 司马迁说:要想成功,不怕被宫; 班固说:我要出书; 司马相如说:一首赋稿费一千; 曹操说:抄家伙我要赋诗; 曹植说:命题作文有何难; 孔明说:我要写道动员令; 陶潜说你们累不累呀。 遂卷铺盖回家了。 朱温说:我同花顺; 萧道成说:我一条顺; 陈霸先说:重新洗牌…… 杨广说:去扬州观花; 李渊说:消来公费旅游; 李世民说:魏征,你的意思; 李治说:老婆,你的意思; 武则天说:那还不如我说了算! 薛刚说:反了你了! 骆宾王说:鹅肥; 王勃说:情深; 李白说:酒美; 王维说:景幽; 孟浩然说:风流; 杜甫说:屋漏; 白居易说:抱想琵琶唱OK; 李商隐:我没话说了。 柴荣说:三武废费有我一份; 赵匡胤说:今年流行黄袍子 寇准说:带上瓶醋谈判去; 李刚说:保家卫国; 徽宗说:没保成; 钦宗说:我想回家; 金兀朱说:没门…… 赵构说:把姓岳的抓了; 岳飞说:我有何罪? 秦桧说:也许有…… 陆游说:我要死了; 文天祥说:死得好,我为你喝彩! 完颜说:金大; 耶律说:辽大; 成吉思汗说:大你个球! 忽必烈说:亚欧大陆我说了算…… 朱元璋说:高筑墙; 建文帝说:孙承祖业; 朱棣说:我找我爹; 严嵩说:清史留字; 崇祯说:袁崇焕,你的良心大大地坏了…… 李自成说:歇会,找个小姐来; 吴三桂说:敢泡我老婆; 皇太极说:三桂是个好同志。 顺治说:爱江山更爱美人; 康熙说:江山好管儿子难教; 雍正说:说我狠,我就狠给你们看; 乾隆说:我爹是谁; 嘉庆说:和坤是我爹留给我的遗产…… 施耐庵说:天罡盖地煞; 罗贯中说:曹刘震河腰; 吴承恩说:全盘西化; 曹雪芹说;读书人的事能算淫么; 蒲松龄说:我是另类我怕谁? 林则徐说:我销; 洪秀全说:我反; 康有为说:我变; 孙中山说:看我的。 慈禧说:木偶戏你当好演呀; 李连英说:有奴才伺候; 李鸿章说:九亿白银,小意思; 袁世凯说:窃国者为诸候? 蒋说:共D未灭何以家为 ? 毛说:下乡! 邓说:下海! 江说:下岗!
我说: 我倒! |
|
50年后中国牛B了
|
50年后中国牛B了,美国人在叹息年轻人崇洋媚外,削尖脑袋往中国跑,在新西方 中文学校学中文托福的人挤破脑袋。年轻人好好的黄头发非要染黑,说话夹着中 文。还TM有偷渡去中国的。
50年后中国牛B了,日本FQ在网上狂喊,大和民族团结起来,抵制中国货!
50年后中国牛B了,德国《踢球者》杂志头条:世界杯揭幕战爆出最大冷门,沦落 已久的巴西逼平卫冕冠军中国队。该报评论:拥有五大联赛最佳射手的中国队在 首战没有进球是开赛前所有人无法想象的。
50年后中国牛B了,好莱坞明星Goodbye起了个中文名“古德白”进军中国影坛, 让整个好莱坞震惊。据报道,他准备角逐百花奖的影片创纪录的投资2000亿美元 ,折合人民币20亿,在美国电影史上前无古人。但有专家担心的指出,这种投资 相对对于中国电影还是太少了。想在北影厂留下掌印还有很长的路要走。
50年后中国牛B了,日本FQ举行游行,抗议中国国家领导人去八宝山革命公墓祭奠 20年前参与东京大屠杀的革命先烈。但是在日本人气最旺的论坛狗朴(GOP),凡是 关于中国的FQ贴一律不让通过。
50年后中国牛B了,因为眼馋丹麦稀有的没被污染的空气资源,其邻国德国出兵侵 略丹麦,中国维和部队进驻丹麦,1个星期之内把德国人逼到投降。
50年后中国牛B了,德国人因为这次战争对中国怀恨在心,2名德国恐怖主义分子 劫持了一架飞往火星的飞碟,改变航向飞往中国北京,撞毁了著名的西直门立交 桥。
50年后中国牛B了,奥运会上美国年轻的黑人跨栏选手fly为美国赢得了一枚金牌 ,让整个美国热泪盈眶的讨论,原来黑人也是可以搞田径的,并不是亚洲人的人 种就比我们好。
50年后中国牛B了,阿根廷人利用国际足联规则漏洞,让河床队的中国球员刘大民 代表阿根廷出战世界杯,引起了部分球员的不满。但网上调查显示,更多的阿根 廷人希望人才过剩的中国球员可以加入阿根廷籍。
50年后中国牛B了,一帮没文化的美国人在抱怨中国“巨硬”公司开发的软件英文 版发行太慢,以至于他们不得不使用非正式的英化版本。而且部分软件对英文的 支持并不好。
50年后中国牛B了,在中国湖北孝感学院生命科学系深造的众多美国留学生,纷纷 写信给美国总统小什布,要求回国报效国家,遭到中国科研机构的高薪挽留。小 什布说:“你们在中国研究,条件好,更能出成果,贡献更大。”
50年后中国牛B了,由于在针对“对夏威夷出售095型战略核潜艇及100枚东风II简 化型导弹”的提案上,白宫对北京方面提出最严重的抗议,谴责中国干预美国内 政,中国外交部负责人称此次事件和夏威夷独立无关。
50年后中国牛B了,在对越南进行“斩首”作战第11天,中国人民解放军已经损失 3名军人,在攻占越南首都以后,北京发布新闻会在全球通缉越南前任总统。
50年后中国牛B了,由于干涉到国家政治问题和其他社会因素,日本和美国国家电 视台公布了被禁止的5个中国制作的游戏:其中包括:学雷锋在线;MJJ之锤;中 国麻将;地道战;决战朝鲜。
50年后中国牛B了,中国最高行政长官海**和宋孙英的绯闻被闹得沸沸扬扬,最后 长官被弹劾,成为中国在野党攻击执政党的又一有力武器。
50年后中国牛B了,阿拉斯加与美国分裂了,美国人多次要求中国不要对阿出售武 器,要求中国明确一个美国的立场
50年后中国牛B了,美国西部的一些大学生在一个叫驴扑(LOP)的论坛上大骂耶 鲁,哈佛的同龄人,国家花了那么多钱培养你们,结果却为中国培养了,丫毕了 业都JB跑中国去了
50年后中国牛B了,美国的主流电视媒体整天播放一些高楼大厦的画面,还在街头 采访一些黑眼睛,黄皮肤的中国人,这些人惊呼:”诶呀,妈呀,美国这几年发 展太快了,我还以为到铁岭了捏......“
50年后中国牛B了,东京的大街繁华的大街上尽是中餐馆,电视里还详细介绍猪肉 炖粉条的详细做法及其衍生的中国文化,而狗扑(GOP)上的FQ们也大叫,越来越 多的年轻人认为吃寿司很没品位,很俗......
50年后中国牛B了,美,俄在分分合合中建立什么战略伙伴关系,还一直叫嚷:世 界已经朝着多极化发展,中国只是实力稍微强于我们一点点
50年后中国牛B了,美国国务院的新闻发言人整天在记者会上对中国政府的做法深 感遗憾,强烈反对,并静观中国在很多国际问题上的态度......
50年后中国B比了,美国的主流电视媒体整天播放一些高楼大厦的画面,还在街头 采访一些黑眼睛,黄皮肤的中国人,这些人惊呼:”诶呀,妈呀,美国这几年发 展太快了,我还以为到铁岭了捏......“
50年后中国牛B了,号称第一代美国移民的子女们从中国回到美国,他们自豪的称 自己为:CBA(China born American),他们的老师,一个在北京混不下去跑美国 来教中文的老爷子鄙夷地说,你们丫傻吧,CBA不是中国篮球联赛嘛?
50年后中国牛B了,中方投资的日本门户网站www.riben.com.jp随着中国话的普及 终于在某一天被日本FQ们发现了来源,丫们在网上委屈的呼吁:强烈要求抵制www.riben.com.jp! 原来它来自中国人对我们的蔑称,我们日谁不好啊日自己。。。
50年后中国牛B了,美国移民的孩子称自己为马桶人,还耐心的*着蹩脚的中国话 解释给别人听,嘛叫马桶人,介马桶人就斯说,俺们有白色的外表,但里面 滴东西,全斯黄色的。。。。
|
文章收藏 乱闪 发表于 2005/2/26 12:29:40 |
| |
一位将军刘亚洲精彩的讲演:中国是一部改善从恶的历史
|
信念与道德
我是中国文化的继承者,也是中华文化的批判者。过去,我首先是它继承者,其次才是它的批判者。现在,我首先是它的批判者,然后才是它的继承者。西方的历史是一部改恶从善的历史。中国的历史则是一部改善从恶的历史。古代西方什么都禁,就是不禁人的本能。中国什么都不禁,独独禁本能。西方人敢于展示自己,既敢于展示自己的思想,又敢于展示自己的裸体。中国就知道穿衣服。给思想穿衣服。穿衣服总比脱衣服容易。西方鞭挞自己的黑暗,所以得到了光明。它的思想在驰骋。我们歌颂自己的光明,结果带来千年的黑暗。黑格尔说:"中国无哲学。"我认为中国几千年来没有产生过思想家。我指的思想家,是像黑格尔、苏格拉底、柏拉图,这些对人类文明进程有重大贡献的思想家。老聃,你说他是思想家吗?仅凭五千字的《道德经》能当思想家吗?且不说他的《道德经》有问题。孔子能算思想家吗?我们后人怎么审视他?怎么审视他的作品?他的作品从未为中国人内心提供一个可以对抗世俗权力的价值体系,提供的是一切围绕权力转。儒学如果是宗教的话,便是伪宗教;如果是信仰的话,便是伪信仰;如果是哲学的话,则是官场化社会的哲学。从这个意义上说,儒学对中国人是有罪的。中国不可能有思想家,只有谋略家。中国社会是个兵法社会。我们民族只崇尚谋略家。一个事业上并不怎么成功的诸葛亮被人反复的纪念着。他心胸不开阔,用人也不当。有资料表明他也是弄权者。但恰恰是这么一个人,被抬到了吓人的高度,这也是我们民族心灵的一种写照。在这种社会形态下,有三种行为大行其道:
① 诡辩术。我儿子今年考上了某大学新闻系,该大学新闻系是中国最好的新闻系之一。我对儿子说:拿教材来我看看。看过后我说,这不值得看。里面有这么一个论断:中国发明了火药。火药传到欧洲之后,冲破了欧洲中世纪封建的堡垒。真是笑话。你发明的火药冲破了人家的封建堡垒,你自己的堡垒怎么没被冲破?反而更加坚挺?在国防大学讨论台湾问题时,有一个观点颇有市场:台湾象一把锁。如果台湾问题解决不了,台湾这把锁就会把中国的大门锁住。中国将没有出海的通道。这是诡辩。我一句话就可以给你顶回去。西班牙成为海上强国后,并没有能阻止它的近邻葡萄牙也成为海上强国。法国多佛海峡离英国只有二十八海里,英国阻挡法国成为海上强国了吗?中国失去海洋关键是历代统治者没有海权观念。大家可能没注意到,前一段时间电视上批"***",佛教协会、道教协会的住持、道长们侃侃而谈,批判"***"是封建迷信。我想冷笑,竟真的忍不住笑出声来。他是封建迷信,你难道就是唯物主义的啦?不也是迷信吗?
②对外怀柔,对内残忍。欧洲文明和中国文明几乎同时起步,但是欧洲形成了许多小国家,中国形成了一个统一的大帝国。谈及此,我们往往沾沾自喜。其实,欧洲形成这么多国家正是它自由思想的一种体现。它虽然形成了这么多小国家,但是,多少与人类文明有关的东西是从这些分裂的小国中产生出来的,而我们为世界文明做些什么呢?统一江山肯定与统一思想有某种必然的联系。谋略社会是个内向性的社会。我曾经仔细研究过中美两国的差异:中国在国际事务方面基本是柔,在国内事物则是刚。美国正相反,在国际事物方面刚,在国内事务方面柔。我不记得我在哪本著作中提到过这个问题,可能是《对台作战,危险评估》,并做出这样的结论:这是由于文化不同所决定的。中国文化是封闭的,内敛的,内向的;美国文化就是开放的、外向的。大一统的理念也是个内向形的理念。这也是解释我们为什么在外国侵略者面前是羊,在自己同胞面前是狼的原因。近百个日本兵,就能够押着五万名国民党军俘虏到燕子矶去枪杀。不要说反抗,他们连逃跑的勇气都没有。解放战争中莱芜战役,仅三日,我军歼灭敌七个整师,五万六千人。战后,王耀武抱怨:"五万头.,叫共军抓,三天也抓不完。"而中国人要自己打自己人,那才叫勇猛!".." 时,北京军区六十三军的排长刘国庚在六部口被打死。6月4日清晨,北京市民把他的尸体点燃了。尸体烧焦了。下午,天热,肚子鼓得老大。这时候,一个青年人拿一块玻璃,走上去把肚子一划,肠子一下就滚出来了,然后,他就用塑料绳把肠子根部扎起来,一大堆肠子就挂在肚子上。几千名北京市民在旁边围观,无一人阻止不说,俱大声叫好。这个青年人弄完后说:"看,多像一朵花啊。"我说,这朵花开得好惊心好动魄啊。外地人听见这件事后,说,北京人真残忍。香港和台湾人听说这件事后说,大陆人真残忍。南朝鲜、日本人听说这件事后说,中国人真残忍。美国人和西方人听到后说,东方人真残忍.
③鄙俗。精神鄙俗必然带来行为的鄙俗。精神高贵必然带来行为的高贵。大约二十年前吧,我住的小区发生这么一件事:一对夫妻闹离婚,丈夫把新欢带进家,大吵。妻子跑到楼顶,欲往下跳。围观的人很多。有的人兴灾乐祸地大叫:"快跳快跳!"后来警察把人救下来,围观者甚至感到遗憾。我长叹一声,回到家里,打开电视。正播着一个在欧洲刚发生的真实故事:某国,依稀记得是匈牙利,七十年前,一个年轻的矿工马上要和新娘举行婚礼,婚礼前最后一次下井,但发生了塌方,矿工永远没有回来。新娘子不相信她的爱人就此离她而去,苦苦等了七十年。前些日子重新整理矿井,在坑道深处一汪积水中发现一具尸体,正是七十年前被埋在井里的新郎。由于没有空气,又浸泡在饱含矿物质的水中,他仍如七十年前一般年轻。新娘子已成为白发苍苍的老妪。她扑在心爱的人身上痛哭。她做了一个决定,继续与爱人完成他们的婚礼。那一幕太动人了:八十多岁的新娘子一身盛装,洁白如雪。头发也如雪。她的爱人,依然那么年轻,闭着眼睛躺在一驾马车上。婚礼与葬礼同时举行。多少人都落泪了。
最能考验我们民族道德水准的事情就是美国去年发生的"9.11"事件了。今天,正好是"9.11"事件一周年。"9.11"虽然没有改变世界,但是改变了美国。同时,"9.11"之后的世界很难回到"9.11"之前去。当"9.11"事件发生的时候,在我们国家,至少在一段时间里,弥漫着一股不健康的气氛。9月12号的那天晚上,赵粤(作者朋友,现在总政联络部工作――编者注)给我打电话说,北大和清华的学生正在敲锣打鼓。我说中国足球队还没有出线呢,中国队出线要到10月7号,那是最后一场,中国对阿联酋。赢了就提前出线进世界杯。隔了片刻才知道是中国大学生在庆祝美国"双子星" 大楼被炸。我国有一个记者代表团,当时正在美国访问,看到世贸大楼被撞,这些记者团的成员情不自禁地鼓起掌来。这是一种文化的浸濡,这不能怨他们,他们已经控制不了自己了。结果被宣布为永远不受欢迎的人。我在北空,那几天部队来人看我,我都问他们对"9.11"什么看法。众口一词:炸得好。后来我讲,这是很悲哀的。如果是这样的人爱中国,那中国还有救吗?媒体就更不用提了,中国最没有新闻的地方就是在报纸上。1997年戴安娜遇车祸去世。你不管戴安娜这个人怎么样,英国王室怎么样,她至少具有新闻价值。世界各大报纸都在第一版登了这条消息,唯独中国的报纸不登这条消息。那天北京各大报纸的头版新闻是"北京市中小学开学了 "。这条新闻就等同报道"北京人今天吃早饭了"一样,就这个价值。"9.11"第二天晚上,我坐在电视机旁看《焦点访谈》,我想看看那些国嘴们如何评介 "9.11"这个焦点,结果那天的《焦点访谈》的内容是关于农村党支部加强自身建设什么的。你想看什么?偏没有。你不想听的,偏讲给你。国嘴当然无辜。 1999年美国打南斯拉夫,中国出了一次头。那次出头的代价就是大使馆被炸。这次差点又出了一次头,后来还是以...同志为首的党中央及时扭转了局面。我们这个文化的列车,带着巨大的惯性,载着我们这批有道德缺陷的人,风驰电掣地驶向终点。有人还在这个时候提出,趁机打台湾。此时动手,一鼓可下。这些同志的心情可以理解,但现在委实不是一个恰当的时机。当时我想,"9.11"死了这么多人,都是无辜的人。丧失的是人的生命,是世界上最有尊严的东西。这些生命本身与美国政府没有关系。我们以这种态度对待别人,别人却不以同样的态度对待我们。与此形成鲜明对照的就是多佛惨案。去年,一批福建偷渡客乘闷罐车从多佛海峡进入英国的时候,由于在空气不畅的车里呆了几十个小时,人都闷死,只有两个活的。这个事件曝光后,中国大使馆的官员没有一个出面。最后是英国老百姓在多佛这个地方自发地举行追悼会和烛光晚会,悼念那些死去的人。很多孩子来参加,手里拿着玩具,中国制造的玩具。顺便说一句,现在世界上百分之九十的玩具是MADE IN CHINA。记者问孩子:为什么来参加追悼会?孩子说,他们也是人嘛。我们现在手里拿的玩具,有可能就是他们当中的人生产的。在整个追悼会中,没有一个中国人在场。什么叫文明,什么叫不文明?我在思考。
①为恐怖叫好很恐怖。中国文化教育出来的中国人。首先漠视和轻*自己的生命,才会对他人、他国的生命也视如儿戏。自己没有珍惜生命的权力,也不许别人有。鲁迅早年前批判过的"看客"心态就是这么炼成的。中国人看杀别人,无不兴高采烈。统治阶级故意把人放在大庭广众下去杀。被统治者就在大庭广众下享受了统治者的快感。特别在凌迟处死犯人时,连续三天,人山人海。连小摊贩都在那儿摆摊。刽子手还出售沾血的馒头。今天没有凌迟了,但当众审判也是这种习惯的延伸。当年如同过节一般去看杀谭嗣同六君子的国人,甲午之役中怎么能不丢掉台湾?他们的子孙―― 我们,如果还和他们一样,又如何解放台湾?公共汽车上一个歹徒逞凶,万马齐喑。就凭这样的人去解放台湾?就凭这样的人怎么去实现四个现代化?你实现了四个现代化又有什么用?我早上锻炼的时候看电视,《早间新闻》的广告节目,最畅销的产品是什么?防盗门。这是一个民族的悲哀。你看我们住的就像笼子一样。我在成都住的是前几任成空政委的房子。我进去一看,哎哟,我进监狱了。窗子上、阳台上到处都是防盗栅栏。我让拆掉。前些天有一本书叫《中国可以说不》。我说,你是可以说不,但你是在防盗门后面说不。这不是勇士,而是懦夫。乔良说的好:"连看见鸡鸣狗盗之徒都要躲着走的爱国者,偏偏胆气粗豪地对遥远的列强说不! "
②要客观、全面地看待美国。美国是什么样的国家?记得早年听过这样一句形容纽约的话:世界上最好的和世界上最坏的加起来就是纽约。用这句话来套用今天的美国,是不是也合适呢?我们这一代军人,担负祖国未来希望的军人,既不当"亲美派",也不能当简单的"反美派",而应当做成熟的"知美派 "。知道敌人才能战胜敌人。贬低对手便是贬低自己。拓跋焘把柔然的国名改为"蠕蠕",意即虫子,可他偏偏被这条虫子打败。那你连虫子都不如。美国不希望中国强大就如同中国不希望美国称霸一样。中美关系有冲突,但也有一定的共同利益。如何化解冲突,发展共同利益,是当前中国外交家们应当努力去做的。中国要发展就不能断绝与世界的交往。现在世界是单级的。只有美国衰落才能出现多极世界。我们既不能断绝与美国的关系,又不能对美国抱有太大期望。目前与美国对抗并非是最适当的时机。国家利益应当永远是我们行动的最高准则。我们需要忍耐。忍耐并不是软弱。只有屈服才是软弱。美国当然亡社会主义心不死。美国当然不希望中国崛起,不希望中国经济发展上去。但我们应切记:与对手做斗争,一定要让你的对手见到一种最不愿意见到的局面。美国人希望中国人打内战,我们就真打内战了。他不在被窝里笑得浑身发抖才怪哩。当然,一味地"卧薪尝胆,韬光养晦"也不行,中国作为一个...大国可能象古代一个武侠一样躲进深山里苦练武功,待武艺高强了再出来与敌人决胜吗?以中国的人口和资源。特别是以中国的文化,中国不可能和美国一样强大,况且美国也不是停止不前。还是毛泽东说得好:"打还是要打,谈还是要谈,和还是要和。"人要机智。外交斗争更要机智。要牵着别人的鼻子走而不是被别人牵着走。赫鲁晓夫就是个机智的家伙。我给你们讲个故事:在一次大会上,赫鲁晓夫大肆揭露并批判斯大林的暴政。有人递上纸条,质问赫鲁晓夫,赫氏本人在斯大林当政时期也是权力核心集团的一员,为什么他在当时不起而反对斯大林的独断?赫鲁晓夫把质问的纸条高声念一遍,随即当众大声道:这是谁递上的条子?站出来!站出来......下面轻轻骚动了片刻,但是没有人站出来。赫鲁晓夫道:"你们瞧,我们现在这样民主,这样无须恐惧的情况下,递条子的同志尚且不敢站出来;试想想,在斯大林统治时期的那种气氛中,有人胆敢站出来顶撞斯大林么?"全场鼓掌。我们对美斗争。应该具有赫鲁晓夫这种机智。该韬光养晦时,就韬晦到家。就象小平同志当年对加拿大总理特鲁多讲的一段话:我们所讲的韬光养晦,包括不要脸面,也一定要与世界上最发达的国家保持关系。(大意)邓小平的意思是,中国一定要与世界文明同步。不能远离世界文明。在 "9.11"事件中,除了个别国家,中国一部分老百姓(而不是政府)是离世界主流文明最遥远的。该斗争时,寸步不让。"崇美"不对,"亲美"不对。"仇美 "也不对。美国政府和政客与美国人民既一样,又不一样。有共同处,有异处。你要有高度的智慧把他们区分开来。过去,美国人民为了帮助中国摆脱殖民统治,打败日本,为中国社会文明进步做出过巨大贡献。两国没有根本利益冲突。今天因为美国利益遍布全球,两国有了冲突。但我们仍要以道德之心来评判事物,不可冲动。我曾讲过,对屠杀了我几千万同胞并且没有认错的日本,我们经常说"要世世代代友好下去",对帮助我们打败了日本的美国人民,我们又有什么理由要仇视呢?
③美国真正的可怕之处在哪儿?美国虽然有着世界上最强大的军队,最先进的科技,但我认为这并不可怕。据说它的隐形飞机来去中国很自由,但这也没有什么可怕的。它可怕的东西不是这些。1972年我在武汉大学读书,上政治课,一个政治老师讲:"美国是腐朽、没落的资本主义国家的代表,已经日薄西山,气息奄奄了。"我,工农兵大学生,一身军装,立即站起来,反驳:"老师,我觉得你说得不对。美国虽然不象中国一样,是早晨八、九点钟喷薄而出的太阳,但它也不是什么夕阳,而是正午的太阳。"老师气白了脸,结结巴巴地说:"你这个同学,怎么敢说这话!"他没有问我为什么要说这话,却用了一个"敢" 字。其间心态,一眼看穿。就是这个腐朽、没落的资本主义国家,却在上世纪九十年代领导了世界上最新的一场科技革命。我大学毕业后,正逢改革开放。我又有一个观点:美国是由千千万万不爱自己祖国的人组成的国家、但他们都很爱美国。那时很多领导人,一边骂美国,一边把子女往美国送。反差巨大!讲了半天,美国可怕之处何在呢?我自己感觉有三点:第一,美国的精英体制不可小觑。他的干部制度,他的竞选机制,能够确保决策者是一批精英。我们中国的悲剧,大到国家,小到一个单位,多数的情况是,有思想的人不决策,决策的人没有思想。有脑子就没位子,有位子就没脑子。美国正好相反,他的宝塔尖体制,正好把一批精英弄上去了。因此,第一,他不犯错误,第二,他少犯错误,第三,犯了错误他能很快改正错误。我们是犯错误,这是第一。第二,常犯错误。第三,犯了错误很难改正错误。美国用一个小小的台湾牵制了中国整整半个世纪。他把这个棋子走活了,走神了,一个台湾,改变了东亚的国际政治生态。我最担心的中国新世纪发展的战略框架因为台湾而扭曲。现在对强势民族来说,领土的重要性大大下降,已经变追求领土为追求国势。美国人对任何国家都没有领土要求。它不在乎领土,它在二十世纪的全部作为都是造势,什么叫造势?除了经济强大以外,民心啊!有了民心国家就有凝聚力,失去的领土可以回来;没有民心,你拥有的土地肯定会失去。有的国家领导只看一步。美国行事往往看十步。因为如此,所以二次世界大战结束后发生的每一次重大的全球性事件都在加强美国的地位。如果我们被它牵着走,就可能丢掉所有的战略筹码。我一再讲,美国的战略重心不会移到亚洲来,但不意味着它不包围中国。很多同志只看到美国在军事上包围中国,就象很多人只看到中美双方在科技和武器装备方面的差距,而没有看到在大战略、尤其是外交层次上比装备落后更严重的失衡。我们的对美外交,要么有措施没有境界,要么有细节没有全局。 "9.11" 之后,美国迅速在两个月之内拿下阿富汗,从西面包抄中国。日本、台湾、印度的军事压力也未减轻。看起来我们从"9.11"中得到了一些眼前的利益,但这些利益不出一两年可能就会消失。我认为对我国的战略包围是另外一种,不是军事,超乎军事。你看,近些年,我国周围的国家纷纷改变社会制度,变成所谓的"民主 "国家,俄罗斯、蒙古变了,哈萨克斯坦变了。再加上原先的韩国、菲律宾、印度尼西亚,再加上台湾。这种威胁对我国而言比军事威胁更厉害。军事威胁或许是短期效应,而被所谓的"民主"国家包围则是长期效应。第二,美国的大气与宽容。你要到欧洲去,再去美国,你会发现一个重大差异:欧洲早晨大街上没有什么人,而美国早晨大街小巷有很多健身的人,甚至全天如此。我有句言论:健身是一种品质。健身代表一种蓬勃向上的文化。一个国家有没有朝气,看看它有多少人健身就知道了。美国人可以把国旗当裤衩穿在身上。我在美国买过一条星条旗裤衩。我常穿。我穿它是为了蔑视它,是出气,是一种心理的渲泄和满足。美国人穿则是一种调侃。本质不同。美国人可以在大街上焚烧自己的国旗。戴旭(作者朋友,《空军军事学术》编辑)说:如果一个国家连自己的国旗都可以烧的话,你还有什么理由去焚烧它呢?第三,精神和道德的伟大力量。这是最可怕的。"9.11"是一场灾难。当灾难袭来时,最先倒下的是躯体,但站的是灵魂。有的民族逢灾难,躯体未倒,灵魂已缴械。"9.11"事件中发生了三件事,都可以让我们从中看到美国人的力量。第一件,世贸大楼顶部被飞机撞击之后,烈焰奔腾,形势千钧一发。楼上的人们通过EXIT向下逃生的时候,并不特别慌乱。人往下走,消防队员往上冲。互相让道,并不冲突。有妇女、小孩、盲人到时,人们都自动地让出一条道来,让他们先走。甚至还给一条宠物小狗让道。一个民族的精神不强悍到一定的程度,断然做不出这种举动。面对死亡,冷静如斯,恐怕不是圣人也接近圣人了吧。第二件事,"9.11"的第二天,世界就知道这是阿拉伯恐怖分子所为。很多阿拉伯商店、餐馆被愤怒的美国人砸了。一些阿拉伯商人也受到袭击。这个时刻,有相当一批美国人自发地组织起来,到阿拉伯人的商店、饭馆为他们站岗。到阿拉伯人居住区巡逻,阻止悲剧的进一步发生。这是一种怎样的精神啊。我们自古就有报复的传统。我住在成都。邓艾破成都后,庞德的儿子把关羽一家老幼全杀光了。血腥报复,斑斑点点,不绝于史籍。第三件事,在美国宾夕法尼亚坠毁的那架767 客机,本来是要撞向白宫的。后来机上乘客与恐怖分子搏斗,才使飞机坠毁。因为当时他们已经知道世贸大楼、五角大楼被撞的消息,他们决定,不能无所作为,要和恐怖分子进行殊死斗争。即便是在这种情况下,他们还做了一件事:决定投票通过,是不是要和恐怖分子作斗争。在这么一个生死悠关的时刻,我都不把我的意志强加给别人。后来全体同意,才去与劫机者搏斗。什么叫民主,这就是民主。民主的理念已经深入到他们的生命中、血液里、骨髓中。这样的民族,他不兴盛谁兴盛;这样的民族,他不统治世界,谁能统治世界。我常作奇想:世界最尖端的武器、最新的科学技术、最强大的武装力量,掌握在这些人手中,还是挺合适的。总比掌握在日本人手中强吧,总比掌握在利比亚、伊拉克人手中强吧?就是掌握在我们手中,我们能做出些什么,也未可知。美国这个国家有很多成功的经验,值得我们学习的借鉴。"9.11"事件后,美国没有成立"9.11"委员会,没有成立什么应急指挥部。我非常反对不实在的东西。我到成空以后,要么不开会,要么就少开会。非开不可的会,开短会。我来成空,首先就把常委学习改成自学。拿着文件念,学习的什么呀。我在同习惯势力抗争。我个人力量有限,但我不能不抗争。哪怕碰得头破血流也不气馁。比方说我一般下部队不吃饭,只要一天能回来的,我都带着干粮,我不吃部队。我到三十三师,在北空也是这样。如果不得不吃,我只吃简单的。虽说一两酒喝不倒红旗,一顿饭吃不垮江山。但是太多了,太浪费了,积少成多,就难说。有人说打台湾不要用什么新式武器,派几个"真正的"...员上岛去吃喝他两三年,绝对把他吃光了。还有一个笑话是说开会的,有一个局长,病得要死了,就是不咽气。老婆说,孩子都来了,你放心上路吧,不行,死不了。老婆说,一切事都安排完了,你放心上路吧,不行,死不了。老婆说,家里财产都放好了,你走吧,不行。后来还是秘书比较了解他,凑过去悄悄在他耳边说: "局长,人到齐了,开会吧。"局长心满意足地闭上了眼睛。这故事当然是编的,但是,说明人们对这种东西的反感、厌恶。
"9.11"不仅是美国的机会,也是中国的机会。搞不好中国就是"9.11"最大的牺牲品,关键是你怎么把握,全世界都面临重新洗牌。研究美国,我们应把握它真正的内涵。不能光看小的,要看大处。有一句话说的好:经常议论别人的缺点,你就是一个道德水准低下者;经常议论人类的缺点,你就是一个思想家。
今天给你们讲了三个多小时,我的目标和我所追求的目标是人的解放。我相信,今天,我来跟大家讲课,与其说是我认识你们,不如说,是你们认识我。我十分坦荡,把我自己全部交给你们。我在你们面前展示我自己思想的裸体。尤其是我在最后谈了对西方、对美国的看法,并没有离开今天讲话的主题。有两条我要再补充讲一讲,第一,我是一个纯正的民族主义者。我讲的一切,都是为自己的国家好,自己的民族好。我在任何情况下,都会以民族利益为最高利益。为了它,我可以抛头颅、洒热血。我脑海中常留着朝鲜战争的一幕:1951年冬,我爸爸所在的部队向美军进攻。因为武器不如美军,必须在夜间潜伏在接敌最近处。一个连队悄悄潜伏下来,整整一晚上。那晚天降大雪,奇寒。天亮时,我军冲锋号吹响了,可潜伏的一百多个战士没有一个跃起来。原来他们全部被冻死了。至死他们仍保持着战斗队形。后来毛主席听了这件事的汇报,他当即脱下帽子,站立,久久不语。1962年中印边界自卫反击战中,我军歼灭了印军一个部队,这个部队当年曾编成在英军序列中,参加过第二次鸦片战争,火烧过圆明园。毛主席接到电报后,拍案而起,说:"百年国耻!"同时,同志们还应看到,中国国情和西方不一样。有些事情虽然看到了,但不能一蹴而就。有些事情还没有看到。有些观念的差距,有待时日,方能减小。譬如,前几天德国总理施罗德在竞选时,就因为一个小小的问题差点败北。什么问题?他染了头发。在我国,染头发算什么?爱美之心,人皆有嘛。爱年轻之心人皆有嘛!几乎没有领导不染发。但在西方则不行。因为你染头发,就是给人一假象,就是不真实的表现,就是欺骗。而政治家这样做,则被人打问号。你看,苛刻到任何地步!
第一次和昆明基地的营以上干部见面,就非常率真地、大胆地讲这么多,这都是我研究的成果,我对自己的讲话负责。讲对的地方,你们就往心里去,讲错的地方,你们就这个耳朵进,那个耳朵出,莞尔一笑,不要当回事。每个人都是一个个体,每个个体都是自由的。我不能要求我的思想都给你们。我更不能要求把你们的思想都统一到某一个思想上来,那是不可能的,但是我们偏要追求那种可能,这是非常虚无飘渺的,实际上做不到。
到此为止,谢谢大家。
|
文章收藏 乱闪 发表于 2005/2/24 19:20:22 |
| |
一个女大学生的幼稚言论和一位老伯的精彩反击
|
主题:我爱日本更爱日本男人
我是一个上海女大学生,刚来这里。我真不能理解,到底日本人对你们做过什么?要你们那么去恨他们?我现在知道了,你们是在妒嫉!从你们那些所谓“爱国者”龌龊的嘴脸中我看出来了,其实你们自己也知道你们是不如日本人的,尤其作为男人,你们这些中国男人更会觉得自悲不堪.
我从小就喜欢日本,喜欢日本人。我最大的梦想就是嫁个日本男人,我周围的许多朋友也都有这样的想法。我知道一定会有一些所谓的“正人君子”会“义正词严”地指责我们“没尊严”。但作为我们女人,我们永远只会选择强者做我们的丈夫,你们中国男人难道算是强者吗?你们人口是日本的十倍,所占资源和领土面积又不知要比日本多多少倍,但你们平均每人创造的财富有日本男人的百分之一多么?你们的行为素质有日本男人的百分之一高么?答案是没有。
作为中国男人,你们有着绝对的地理优势,但你们打仗打不过日本,拼经济拼不过日本,拼体质拼科技拼文学拼教育……你们哪个有日本强?你们这些中国男人自己不觉得羞耻还有脸去怪我们女人吗?你们自己没尽到责任给老祖宗蒙羞还要对着我们说三道四推卸责任,只能让身为中国女人的我感到羞耻我就是要嫁给日本男人,我只会选择强者!
你们这些所谓的“爱国者”除了在网上骂骂人以外没别的出息,你们有本事把自己国家搞好,让日本女人成天想着嫁给中国男人,让日本女星穿着中国军旗装,可你们没有这个本事!你们无能!你们成天叫喊着要让日本道歉,可这个世界上有强者对弱者道歉的道理么?为什么日本宁可对韩国人道歉也不愿对中国道歉?因为你们中国男人连韩国男人都不如,我们女人还能指望你们干什么呢?!
这就是我所要说的话,我知道一定会有不少人来骂我的,但无所谓,因为我看穿你们了!
********************************
[以下是回帖]:
我知道这位上海小姐,不管你是不是上海或者是中国其他什么地方的,这都不重要,我以下说的话可能你也看不见,你看不见并不代表我就不说,我不是为你发言,我是为我自己,为所有中国的爱国同胞发言,
所以你不要认为自己多了不起,你只不过大大学生而已,我都大学毕业很久了,加上社会阅历很生活经验,基本上可以当你的导师了。所以请你以后不要动不动就说“我是大学生”,会被人笑话的,我这里找不到工作的大学生很多。
我看了你的发言,我分析了一下你说的基本观点:中国人素质差,素质低下,被日本人看不起,你喜欢强者,你认为日本人是强者,所以你要嫁给日本人,我想我没有说错吧!
首先我们来说中国人的素质问题。
解放前的风风雨雨我就不说了,但是在解放后,中国消灭了四害,人民的主人翁精神发挥得淋漓尽致,人人都努力生产,为国家,为民族,人民的道德水品空前的提高,甚至做到了夜不闭户的程度,这需要多么强的自觉性。这种全国上下一条心的程度,我想不比日本的武士道精神差吧。
可是文革这场灾难给中国人民造成了巨大伤害,他不仅摧毁了中国的经济,还摧毁了中国人民的文化素质和道德素质,中国现代道德水平真正的起点应该是在文革过后,在1976年开始重新进行了精神文明建设,因此,中国经济的真正发展因该是冲1976年开始的,在短短27年中,中国人民的素质得到了空前的进步,不论是经济,社会文化,公共基础设施,体育等各方面都有飞跃性的发展,我想这不比日本差吧,中国人的素质是还有提高的空间,难道日本人的素质就到了顶点了吗,到了完美的地步了吗?
现在让我们看看日本的社会现象,在日本投降后,在美国的扶持下,日本经济快速发展,日本人民勤奋工作,日本有很多值得称道的地方。但是这并不能一美遮百丑,日本为什么在战败后能够飞速发展,日本经济学家说过,日本该感谢中国,因为中国政府主动放弃了日本的战争赔款,这笔钱对日本的经济发展起了 很巨大的作用。这是多么宽阔的胸怀,这需要多么大的勇气,但是请不要用伟人的名字注册!做出了这样的决定,为了什么,只是为了中日以史为荐,和平共处,为了两国人民能够幸福的生活。
但是日本又是在怎样对待中国的呢?这个世界没有无缘无故的爱,也没有无缘无故的恨。我小时候根本没有恨过日本,相反,我很喜欢日本的一休哥,花仙子等卡通形象,还很喜欢看日本电视剧《警犬卡尔》、《血凝》等影片,也很喜欢高仓建,但是为什么我在长大了却对日本有着刻骨铭心的恨呢?这不是中国政府宣传的结果,因为中国政府是单方面的一相情愿的在宣传中日友好,日本人在中国出了事,受到的照顾比中国人好,甚至叫特权阶级。在政府这样的宣传下仍不能消除中国老百姓对日本的敌意,为什么?
让我们看看日本对我们做了什么吧,日本侵华就不说了,我们都清楚日本是怎样用刀砍下中国人的头颅,在头颅落下的瞬间,鲜血中颈总动脉一喷而出,而头上的那张脸却在努力的挣扎,嘴张得大大得想尽力的呼吸,但是这是徒劳的。面队这样的野兽,中国人民以德报怨,可是日本呢,日本一再修改教科书,否认大屠杀,否认侵略,这好比我杀了你父亲,我尽情的蹂躏他的尸体,然后我对人说,我没有杀他,他人笨,该死,他没有用,该死。我想这种事情你不会接受吧。要是我也不会接受,因为我需要进行换位思考,而你有过吗?这种思考是人在做事情前的基本思考。
德国和日本一样,有过军国主义,进行过屠杀犹太人,但是你问现在的犹太人,有多少人恨德国人,你问过吗?我问过,他说我不恨德国人,但是我很德国法西斯。为什么,因为德国是光明磊落的民族,“跪着的德国人比站着的日本人跟高大”——这句话不是没有原因。德国政府历届总理都很郑重的向二战中的受害者道歉,在受害者的纪念碑前流下过忏悔的眼泪,我知道你会说这只代表总理个人,我的回答是——错,为什么?一个人能坐在总理这个位置上,如果没有人民的支持,他没有机会当总理,所以,他的忏悔就代表全部德国人的忏悔。如果德国民众不为二战感到羞愧的话,我想德国总理在道歉后就会有数不尽的叫骂,但事实是德国民众骂了吗,没有。
一样的道理,日本首相之所以可以屡次参拜,就是因为有国民支持,如果只是小部分人支持,日本首相是万万不敢这样做的,所以,现在的日本可以说举国上下都是反对承认侵略历史,反对承认战争和屠杀的,请问,连最基本的历史都不承认的民族,还有什么信用可以讲,连基本信用都没有的民族,还是优秀的民族吗?
我知道你会说日本人是讲信用的,从日本的经济发展就可以看出来。如果日本不讲信用,那是不会得到客户认可?对,这里是关键,日本在在战后大力发展经济,讲信用是商业往来的基本准则,其目的就是为了得到客户的定单,赚取利润。但是如果没有这个基本目的,那日本会怎样呢?告诉你一个现实,日本的地 铁是分段票制,但是并没有出口剪票,所以往往很多人买一站的票坐三站甚至更多站的路程。这是诚信吗?你读过书,我想你有基本判断能力。
中国的三峡工程,日本企业卖给中方的500吨优质钢铁,进行抽样检测,居然是全部不合格,如果这样的材料用在三峡工程,会有什么严重的后果,如果你不知道,我举例吧,你就可能在大街上游泳了。
当中方提出退货时,日本居然说中国的检测技术不科学,不严谨。就算是吧,为什么在不科学严谨的检测下都不能通过,你还有什么资格对中方说三道四的,事实是后来日方的检测结果和中方一样,搞到最后一样退货。
日本卖到中国的产品,都是三流产品,和中国的技术合作都是过时技术,这不是我胡说造谣,到过欧洲发达国家的人都知道是怎么样,中国上市的日本最新款MD或者其他商品,在欧洲都属于淘汰产品,在日本不多见,而在中国却是最新科技,而且价格奇高,这是典型的商业歧视,连商业这种讲诚信的事情都不能做到公正的国家和民族,那还有什么值得我们对其有好感呢?
你说中国的民族工业落后,我承认中国在某些领域落后,但是中国在更多的领域做到了后来居上,在彩电,背投,CPU(日本至今没有开发出自己的CPU),空调、冰箱、造船、航空等领域做得不比日本人更好吗?想想中国这个比日本晚起步,在一个被蒋介石运走了所有的黄金和财产的土地上,从1976年至今短短27 年时间做到这个程度,这需要多少人努多少力才能做到的啊。美国人能做到吗?日本人能吗?
在军工产业方面,日本能做得比中国好吗?日本的F2战斗机是美国的F16放大了15%的改造型,日本没有自己的完善的风洞,没有中国在空气动力学方面雄厚的技术储备,只能照搬美国现成的东西。日本的90坦克是很先进的,人进去的感觉象进高级轿车,把太多的尽力和财力没有放在重点上,他的坦克炮是买的德国 的,因为它没有这个科技和制造能力,而中国98坦克的125炮的火力在4000米的距离上仍可以击穿500—900毫米的均质装甲,说形象点就是美国最先进的M1A2都不能做到。
你说中国人没有素质,那没有素质的人怎么能办到这些举世瞩目的成绩?他们让世界惊叹。
作为中国人,我是无比的骄傲和自豪,我想这种感觉你是不会有的,因为在你的文章中到处都是“你们中国人”之类的言语,你早当自己是日本人了。所以我认为在这点上你可以说是麻木的。一个连起码爱国心都没有的人,还有什么资格在用汉字在这里发表言论?--因为你抛弃了你的国家,抛弃了生你养你的祖国。你会说生你养你的是你的父母?是,是你的父母生你养你,要是没有国家,没有共产党为国家、为人民做的贡献,我想你父亲早让日本鬼子砍了头,你母亲早做慰安妇了,那还有你在这里说话的机会和资格?
我不诅咒你什么,看现实吧:小山智利(原名何智利),我不想叫它的中文名字,因为它是日本人,我从来都不当它是中国人,炎黄会因为有这样的子孙而羞愧难忍。我们为之愤怒,那个为了日本,在球场上大叫“哟西”的日本女人,现在在日本又过得在怎样呢……没有人同情它。包括它的父母。它战胜过邓亚萍,但是现在它又怎样呢,在最近的乒乓球锦标赛中第一轮就被淘汰,自从它去了日本就在也没有拿过冠军,而中国乒乓球队员依然屹立在世界冠军的领奖台上,为什么?因为有祖国的强大支持,有蔡振华这样放弃国外优厚待遇甘心为国家奉贤的优秀的教练员。我想你不会说他不优秀吧?
中国在游泳、体操篮球、击剑、长跑、跳水、举重等很多体育项目都世界前矛,在亚洲是体育最强国,其实力不知比你所钟爱的日本高多少倍,你说中国体育靠女人支撑,那你知道同样项目的冠军,男女冠军的实力相差多少吗?你不知道,仅凭你一相情愿的对日本热衷爱慕,而把自己划归到日本“优秀”民族的行列中,对中国人,尤其是中国男人大加污蔑,你不要忘了:中国打仗还是要靠男人,发展经济的强势群体依然是男人,把握中国政治方向的绝大多数还是男人,--至少,你妈妈还是要靠你爸爸才能有你的存在!
你会说中国的科技不行?我想你是在自欺欺人,日本在科技方面好吗?在对基础理论研究的领域是否有很突出的成就?你可能会认为基础理论研究不重要,那是大错特错的,日本确实有其独到的地方,那就是制造业,在这方面他们是很先进的,连美国不得不服气。但是这些制造业的发展基础是什么?那就是基础理论了。中国在数学,物理,化学等很多方面都取得突出的成就,如果这方面知识你很缺乏你可以看看中国的科技杂志。可以拓宽你的知识面,这样你才能和你心爱的日本人看齐。
你说中国这么好,那为什么不能赶上日本呢?好,那就让我来告诉你,中国960万平方公里的土地,56个民族,在刚解放的时候,经济基础,军事基础,科技等等都很薄弱,如果换了是日本政府遇到这种情况,是否能治理好是很大的问题。而中国做到了,从76年开始,27年时间,中国不断的飞速发展,为世界的经济发展做出了突出贡献,作为一个在世界上敢于担负责任的政府,中国没有在亚洲金融风暴中对人民币贬值,为亚洲经济的恢复做出了巨大的牺牲,而日本政府为了自己的利益,可以随意贬值日圆,损人利己,这就是你的“优秀大和民族”的作风。我不知道你做何感想!!
我不是说中国人没有缺点,不是说中国政府就是完美的。中国人是有很多缺点,这是我们现在以至将来都要勇敢面对的问题。中国人不缺乏智慧,不缺少勇气,毅力,也不缺少勤劳,那我们缺少什么?我们缺少信心,在道德素养方面有很多工作要做,任何民族都有缺点,日本也一样。但是我们勇于面对现实,我们在公共卫生,基础设施,道德教育都在不断加强,我们看到了国民的自律性越来越高,扔垃圾的少了,骂脏话的少了,在公共场合更加注意文明礼貌了,但是我们做的好不够,还有很大的空间需要我们提高。至少我们勇于面对。
日本是有很多优点,难道就没有缺点吗?你知道日本国民的阴暗面吗?你去过日本吗?你没有去过,但是我去过。日本人在社交礼仪上做得很到位,但是对你礼貌并不代表多你友好,很多在我之前去日本的朋友告诉我,日本人对你彬彬有礼,实际上是拒人于千里之外。外国人很难真正融入日本社会当中。日本在礼貌的外壳下是什么?--在我住的地方,经常都有女孩子的内衣裤被偷,这不是少数现象,而是很普遍的,日本人的性开放程度可以说是赶超欧美的。日本的色情产业是举世注目的,除了美国就是日本了,而日本色情电影在变态程度上是世界第一的。你说这是个人自由。好,那我问你:你的日本老公每天晚上出去找小姐或者有其他性伴侣,我想你不会说是个人自由吧?人不能双重标准,那样就是没有标准,而你就是那种没有标准、凭自己的一相情愿对日本男人大加赞赏的无知女人。
你说你读过大学,不是无知的,那我告诉你:我也读过,还当过讲师。但是大学才毕业的学生的能力离社会对个人能力的基本需求还差很远,你要走的路还很长。我有个朋友取了日本女人做老婆,这个女人经常会让我的这位朋友去找小姐,说是要保持新鲜感,这不是在编故事,我说的是事实!我想你不会让自己的男人找小姐吧???
中国人有缺点,但是我们勇于面对,并努力改正。
而日本呢,面对自己的种种丑行却视而不见,这是优秀民族的作风吗?在二战问题上,屡屡翻案,美化战争。这是人的行为吗?一个不敢面对缺点,反而加以包庇的民族,我看不出来它的优秀在哪里。你会说中国政府不是称职的政府。对,我承认中国政府有腐败,中国社会制度不完善,但是中国政府至少能让你吃饱了撑的在这里说你爱日本。你鄙视中国,鄙视中国政府。鄙视全中国人,但是至少你记住,你走到那里人家都会说你是华人,你的血液流着炎黄的血,你若如此鄙视身为炎黄子孙那就请你不要带着祖宗的血骂祖宗!
你知道在中国的日本人最津津乐道的是什么吗?那就是中国女人。说中国女人是如何的舒服,是如何蹂躏中国女人,这让我想起了中国在二战中被侮辱杀害的同胞。愤怒啊,只要有血性的中国人都不会原谅日本人的兽性。--而你,只不过是日本下一个可以征服然后抛弃的玩物。
我不会为你伤悲,因为你不是中国人。到底日本人对我们做过什么?您没好好学习过历史么?难道中国的历史教科书也被人篡改了么?你没去深刻分析一下中日之战为什么会失败么?你认为中国人的素质真的没有日本人的百分之一么?堂堂中华,泱泱大国。耻辱啊,耻辱啊,我曾以为,日本人给我们的烙印是我们最大的耻辱,是我们心中永远的痛,今天,我知道了,我们最大的痛来自我们自己,当日本人给我们带上东亚病夫的帽子的时候,当公园上写着华人与狗不得入的时候,但举世震惊,南京大屠杀的时候。到如今,他们公开跳下流舞,羞辱你的时候。女士,他说他到底对你做了什么?嫁给日本人。婚姻自由固然是要的,但嫁给日本人何时竟成了你乃至很多中国女性的梦想!?悲哀啊,悲哀啊,知道么。你的言行,带给我们的,同样是无尽的耻辱! 记住,曾几何时,神州大地上,也有几许你这样美丽的姑娘。却充当了日本人的尉安妇
|
文章收藏 乱闪 发表于 2005/2/22 22:02:35 |
| |
|