在使用 CSS 定位的时候,经常会遇到 <div> 嵌套中,被嵌套层增加高度而外层不能自动伸缩改变大小的问题
比如开始是这样定义的:
代码:
<div class="div3">
<div class="div1">
</div>
<div class="div2">
</div>
</div>
样式:
<style type="text/css">
<!--
.div1 {
border: 2px solid #FF0000;
float: left;
width: 200px;
height: 50px;
}
.div2 {
border: 2px solid #00FF00;
float: right;
width: 100px;
height: 50px;
}
.div3 {
border: 2px solid #0000FF;
width: 400px;
height: 100px;
}
-->
</style>
后来我在 div1 层里放上内容,这时 div1 层变高
.div1 {
border: 2px solid #FF0000;
float: left;
width: 200px;
height: 150px;}
在 Firefox 下看(IE6 下可以自动伸缩),就变成了这样:
怎样才能用最简单的方法使 div3 层能自动适应里面的 div1 或 div2 层的变化呢
就是使用 overflow 属性
把 div3 中过去定位高度的
height: 100px; 换成
overflow:auto;.div3 {
border: 2px solid #0000FF;
width: 400px;
overflow:auto;}
这样 div3 就可以自动调整高度了
posted @
2006-05-28 17:51 死亡猎人 阅读(397) |
评论 (0) |
编辑 收藏
先看效果图:
--------------------------------------------------------------------
代码:
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<style>
v\:* {behavior: url(#default#VML);}
</style>
</head>
<body>
<v:RoundRect style="width:200;height:100px">
<v:shadow on="true" type="single" color="#b3b3b3" offset="5px,5px"/>
<v:textbox style="font-size:12px">
<div>圆角表格显示效果<br /><br /><a href="http://blog.eliuzd.com/">http://blog.eliuzd.com/</a></div>
</v:textbox>
</v:RoundRect>
</body>
</html>
----------------------------------------------------------------------
实现代码很简单,主要就是用到了微软的VML技术(代码里的
xmlns:v 相关部分):
-----------------------------------------------------------------------
首先我们解释以下什么是VML?
VML的全称是Vector Markup Language(
矢量可标记语言)
VML可以理解为是IE里面的画笔工具,可以通过它来实现你所想要画出的图形,而且结合脚本,可以让图形产生动态的效果。VML是微软1999年9月随 IE5.0 一起发布的,也就是说,在
IE5.0+ 里都支持。
在VML里面,使用的是XML扩展标记,需要一个namespace(命名空间),在上面的程序里就是那个“v”
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<style>
v\:* {behavior: url(#default#VML);}
</style>
</head>
这部分代码其实就是把命名空间“v”和系统预定义的行为VML连接。这样定义以后,我们就可以使用下面的标记了,和普通的HTML标记有所区别,每个标记都增加了一个命名空间:
如:<v:shape></v:shape>
“v” 是我们定义的VML,“:” 后面就是VML的对象(shape 是VML最基本的对象,利用它可以画出所有你想要的图形),每个VML对象都有许多属性,这些大家可以查 VML教程 细看,我这里不多说了。
我们看前面的代码:
<body>
<v:RoundRect style="width:200;height:100px">
<v:shadow on="true" type="single" color="#b3b3b3" offset="5px,5px"/>
<v:textbox style="font-size:12px">
<div>圆角表格显示效果<br /><br /><a href="http://blog.eliuzd.com/">http://blog.eliuzd.com/</a></div>
</v:textbox>
</v:RoundRect>
</body>
body 中的内容就是在使用VML对象画图了。
RoundRect:从名字就可以看出,是画个圆角矩形
style="
width:200;height:100px" 设置矩形的长宽
shadow:阴影
----------------------------------------------------------------------------------------------
textbox:内容
style="
font-size:12px" 就是设置字体大小,它还有个属性是 print (true/false) 是否被打印机打印。
VML 对象除了自己的属性外,基本支持CSS2样式表的所有样式属性。
我这里只是对就圆角表格对 VML 技术中相关的几个对象做了点介绍,如果有兴趣可以自己查阅相关资料。但需要注意的是,由于这是微软的技术,除了 IE 之外目前许多浏览器都不支持,比如 Firefox,浏览上面的代码就看不到表格。
posted @
2006-05-28 17:36 死亡猎人 阅读(368) |
评论 (0) |
编辑 收藏
代码:
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>符合标准的不能正常工作的对联广告</title>
<script language="JavaScript" type="text/javascript">
lastScrollY=0;
function heartBeat(){
diffY=document.body.scrollTop;
percent=.1*(diffY-lastScrollY);
if(percent>0)percent=Math.ceil(percent);
else percent=Math.floor(percent);
document.getElementById("lovexin12").style.top=parseInt(document.getElementById("lovexin12").style.top)+percent+"px";
document.getElementById("lovexin14").style.top=parseInt(document.getElementById("lovexin12").style.top)+percent+"px";
lastScrollY=lastScrollY+percent;
}
suspendcode12="<DIV id=\"lovexin12\" style='left:2px;POSITION:absolute;TOP:120px;'>ad1</div>"
suspendcode14="<DIV id=\"lovexin14\" style='right:2px;POSITION:absolute;TOP:120px;'>ad2</div>"
document.write(suspendcode12);
document.write(suspendcode14);
window.setInterval("heartBeat()",1);
</script>
<style type="text/css">
<!--
#lovexin12,#lovexin14{
width:120px;
height:250px;
background-color:#e5e5e5;
border:1px solid #ddd;
}
html,body{
height:1000px;
}
#mm{
height:1000px;
}
-->
</style>
</head>
<body>
<div id="mm">
</div>
</body>
</html>
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
那么,为什么小小的标准声明让对联广告无法工作呢?
问题的根源:
google了几篇文章之后,找到了真凶!哦,抱歉,没有这么夸张了。
让我们回到第一段代码:
注意这一句:diffY=document.body.scrollTop;
当我们采用标准声明之后,你会发现无论你怎样拖动滚动条,diffY的值始终为零。见鬼了吗?不,事实上从html4/loose.dtd开始,只要你采用了相应的文档类型声明,diffY的值就会恒为零(有一种特殊情况,下面谈)。
为什么会这样?
因为采用标准的文档类型声明后,document.body.scrollTop已经无效,而应该用document.documentElement.scrollTop代替。
不仅仅是scrollTop有这种改变,更多请参加表(一)。
在表(一)中有这样一行:“Note: scrollLeft and scrollTop also work on DIV's with overflow: auto in Explorer 5+ on Windows and Mozilla 1.1”,这就是我所说的特殊情况。
怎么解决?
将第一段代码做一些修改:
var diffY;
if (document.documentElement && document.documentElement.scrollTop)
diffY = document.documentElement.scrollTop;
else if (document.body)
diffY = document.body.scrollTop
else
{/*Netscape stuff*/}
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>符合标准的正常工作的对联广告</title>
<script language="JavaScript" type="text/javascript">
lastScrollY=0;
function heartBeat(){
var diffY;
if (document.documentElement && document.documentElement.scrollTop)
diffY = document.documentElement.scrollTop;
else if (document.body)
diffY = document.body.scrollTop
else
{/*Netscape stuff*/}
//alert(diffY);
percent=.1*(diffY-lastScrollY);
if(percent>0)percent=Math.ceil(percent);
else percent=Math.floor(percent);
document.getElementById("lovexin12").style.top=parseInt(document.getElementById
("lovexin12").style.top)+percent+"px";
document.getElementById("lovexin14").style.top=parseInt(document.getElementById
("lovexin12").style.top)+percent+"px";
lastScrollY=lastScrollY+percent;
//alert(lastScrollY);
}
suspendcode12="<DIV id=\"lovexin12\" style='left:2px;POSITION:absolute;TOP:120px;'>ad1</div>"
suspendcode14="<DIV id=\"lovexin14\" style='right:2px;POSITION:absolute;TOP:120px;'>ad2</div>"
document.write(suspendcode12);
document.write(suspendcode14);
window.setInterval("heartBeat()",1);
</script>
<style type="text/css">
<!--
#lovexin12,#lovexin14{
width:120px;
height:250px;
background-color:#e5e5e5;
border:1px solid #ddd;
}
html,body{
height:1000px;
}
#mm{
height:1000px;
}
-->
</style>
</head>
<body>
<div id="mm">
</div>
</body>
</html>
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
posted @
2006-05-28 17:06 死亡猎人 阅读(79) |
评论 (0) |
编辑 收藏
text-overflow : clip |
ellipsis------------------------------------------------------------------------------------
取值:
| clip | : | 默认值。不显示省略标记(...),而是简单的裁切 |
| ellipsis | : | 当对象内文本溢出时显示省略标记(...) |
------------------------------------------------------------------------------------
overflow : hidden
text-overflow : ellipsis ;
posted @
2006-05-28 16:59 死亡猎人 阅读(103) |
评论 (0) |
编辑 收藏
在输入文本TD里面加入style="word-break:break-all;"
posted @
2006-05-28 12:09 死亡猎人 阅读(91) |
评论 (0) |
编辑 收藏
本文部分内容来自emllab,在后部分,加入了本人的一个整合范例
在过去的一年里,对于开发人员来说使用flash与javascript通讯总会碰到一些麻烦的事情,从flash调用javascript函数已经没有什么问题了,因为我们可以使用getURL方法来直接调用,但是要想使用javascript返回flash在许多浏览器上几乎是不可能的。但是现在可以了。
Flash8的出现,这件事就变的比较容易了。
The ExternalInterface API
之前我们使用flash调用javascript函数,一般使用这样的方法:
代码:
getURL(“javascript:alert(‘hello webstudio.com.cn’);”);
但是使用这种方法从flash调用javascript函数仍存在许多困难。特别是在处理多个javascript函数调用问题上。ExternalInterface API可以与javascript实现无缝调用,并且它的能力达到可以在flash时间线使用。
在我们正式进入它的使用方法之前,我们需要确保在flash时间上可用,就要导入它的类向这样:
代码:
import flash.external.*;
现在它已经允许我们做的第一件事就是可以调用javascript函数了。
Call 调用方法
call方法对于ExternalInterface对象来说是一个静态方法,也就是说我们不需要使用ExternalInterface对象的实例来调用方法,我们可以直接通过对象类来调用,向这样:
代码:
ExternalInterface.call(functionName:String,Parameters);
这个方法有两个参数:
· functionName – 你想要调用的javascript函数名要以字符串的形式
· Parameters – 需要传递给javascript函数的参数,用逗号分开,是可选的。
这些是基本的内容,现在让我们来看一个例子:
1. 创建一个flash文档命名为external1.fla.
2. 创建两个层上面的层命为AS,下面的层命名为”内容”
3. 在内容层里面,创建一个文本域,将它设置为输入文本域,打开显示边框以方便你能看到,并给它取个名字为alert_txt,将它放在场景的左边。
4. 仍然在内容这一层上,拖动一个按钮组件于场景中并把它放在动态文本的右边,设置它的label为”Alert”并给它起个名字为alert_butn.
5. 选择上方的as层在第一帧上输入代码,
6. //调用alert
7. 代码:
import flash.external.*;
alert_butn.clickHandler = function() {
ExternalInterface.call("alert", alert_txt.text);
}
前面部分的代码是导入ExternalInterface类包。然后为按钮组件设置事件,当点击时调用javascript函数,并将文本中输入的文本通过externalInterface传递给javascript函数。
现在发布你的影片,将它和html放在服务器上,当你在服务器上测试时不论你在文本中输入什么信息,它都将显示在alert对话框中,但是如果你在本地测试,你可能就会发现当你点击按钮时,什么也没发生,这是由flashplayer的安全特性造成的。
演示文件
上面这个范例是一个方法的例子,使用getURL方法也可以做到,然而externalinterface不只是能做到这些,除了发送信息给javascript,它还可以通过addCallback方法接收从javascript返回的信息。
addCallback 方法
AddCallback方法允许javascript调用flash时间上函数,基本的语法结构如下:
代码:
ExternalInterface.addCallback(functionID:String,instance:Object,functionName:Function);
与call方法类似,它也是一个静态方法,它有三个参数
· functionID - 从 JavaScript 调用 ActionScript 函数时可使用的名称。此名称不必与 ActionScript 方法的实际名称匹配。
· instance - this 在该方法中被解析成的对象。此对象不一定是在其上可找到该方法的对象,您可以指定任何对象(或 null)。
· functionName - 要从 JavaScript 调用的 ActionScript 方法。
现在让我们开始一个例子,在这个例子中我们将使用flash调用javascript的命令来请示用户输入色值,当色值输入后点击ok,对象返回到flash并更改它的色彩,如下方法:
1. 创建一个flash文档命名为external2.fla.
2. 与第一个例子相同,创建两层上层命名为as.下层命名为“内容”。
3. 在内容层拖动一个按钮组件至场景中,放在左上方,将label设为”变色”,实例名为change_butn.
4. 确保当前在”内容层”,绘制一个色值为0x000000的盒子,大小为100*100,当然这个没有限制。
5. 将这个方块转换为movieclip.实例名称命名为rec_mc.
6. 在第一帧上输入代码如下:
代码:
import flash.external.*;
//改变方块的色彩
function onChange(clr:Number) {
var temp_color:Color = new Color(rec_mc);
temp_color.setRGB(clr);
}
//允许javascript调用onChang函数
ExternalInterface.addCallback("onChange", this, onChange);
//打开命今窗口
change_butn.clickHandler = function() {
ExternalInterface.call("callPrompt", "你想用什么的色彩? (ex: 0xff0000)");
}
在代码的前边我们要先导入externalinterface类包,然后我们创建一个能改变场景中方块色彩的函数,完成后,我们调用addCallback方法以使javascript可以调用flash的onChang函数。最后,我们针对按钮创建事件来调用javascript命令。
你需要发布swf和html,然后用编辑软件打开编辑器,如果你只是从flash调用javascirpt,那么你什么也不用做。但是如果你需要使用javascirpt调用flash函数,还有一些小的工作需要做。
在tilte标签的下方加入下面的javascript代码:如下:
<script language=JavaScript>
var me; //代表swf的id
//获取正确的引用
function getID(swfID) {
if (navigator.appName.indexOf("Microsoft") > -1) {
me = window[swfID];
} else {
me = document[swfID];
}
}
//下面这段调用onChang函数并返回到flash.
function makeCall(str){
me.onChange(str);
}
//下面这个函数是被flash调用的。
function callPrompt(str){
makeCall(prompt(str));
}
</script>
开始,我们创建变量me来存放swf的引用。如果没有它,我们不能调用flash函数。然后我们使用函数getID通过条件针对不同的浏览器来设置引用,之后,我们创建makeCall函数,用来调用flash函数,最后我们创建由flash来调用的函数callPromt().它将调用makeCall函数来发送信息返回到flash.
在html的body标签的属性中加入onload,并设置它等于getID函数,如下:
<body bgcolor="#ffffff" onload="getID('external2');">
注意,当我们设函数给onload事件,我们传递给它swf的id.它可以在swf的嵌入位置找到,现在,当页初始化完成后,函数getID将被调用,变量me就会被设置,以使javascript可以调用flash函数。
将文件上传到服务器上,并进行测试,当你点击按钮并在提示中输入色彩值,flash中的方块色就会改变。如下。
演示文件
在弹出窗口时如果你没有输入色彩值,而是点击了取消,会返回null空回flash.flash中的方块仍会保持原色。
最终源文件下载(source)
本人对上面的内容进行了一下整合,制作了一个终合范例,集成有显示swf信息,获取网址,调用对话框.
范例演示
posted @
2006-05-28 10:56 死亡猎人 阅读(100) |
评论 (0) |
编辑 收藏
上次自己做了一个,不成功,看到现成的,先转过来
作者:
frank
原文:http://www.riacn.com/bbs/showthread.asp?threadid=1648
在Flash中使用remoting发邮件很容易,由于目前remoting没有支持asp,所一需要用别的方法来做。一般是用loadvars或者getURL,也很简单。
首先写asp文件:
main.asp:
<%
if request("action") = "send" then
frommail = Request.Form("frommail")
tomail = Request.Form("tomail")
if Request.Form("mailsubject")<>"" then
mailsubject = Request.Form("mailsubject")
else
mailsubject = Request.Form("mailsubject1")
end if
mailbody = Request.Form("mailbody")
MailType = Request.Form("MailType")
response.write(frommail)
response.write(tomail)
response.write(mailsubject)
response.write(mailbody)
response.write(MailType)
if tomail<>"" then
Set objCDOMail = Server.CreateObject("CDONTS.NewMail")
objCDOMail.From = frommail
objCDOMail.To = tomail
objCDOMail.Subject = mailsubject
if MailType = 0 then
objCDOMail.BodyFormat = 0
objCDOMail.MailFormat = 0
end if
objCDOMail.Body = mailbody
objCDOMail.Send
Set objCDOMail = Nothing
else
sql="select mail from mail"
set rs=conn.execute(sql)
Response.Write("asd" )
while not rs.eof
Set objCDOMail = Server.CreateObject("CDONTS.NewMail")
objCDOMail.From = frommail
ObjCDOMail.To = rs("mail")
objCDOMail.Subject = mailsubject
if MailType = 0 then
objCDOMail.BodyFormat = 0
objCDOMail.MailFormat = 0
end if
objCDOMail.Body = mailbody
objCDOMail.Send
RS.MoveNext
wend
set objCDOMail = Nothing
end if
Response.Write "<script>alert(""Success"");location.href=""main.asp"";</script>"
Response.End
end if
%><title>Send</title>
这个文件已经完成了asp中的发邮件功能,接下去的Flash中的部分,只要把数据穿传给main.asp?action=send.send是这里定义的一个动作。
我在Flash中新建一个按钮。使用两个方法,getURL和LoadVars.send()得到的效果一样。
LoadVars.send()方法:
on (press) {
var my_data:LoadVars = new LoadVars();
my_data.frommail = "youmail@any.com";
my_data.tomail = "receivermail@any.com";
my_data.mailsubject = "asd";
my_data.mailbody = "asdasdasd";
my_data.MailType = "1";
my_data.send("main.asp?action=send", "_self", "POST");
}
getURL方法:
frommail="youmail@any.com"
tomail="receivermail@any.com"
mailsubject="asd"
mailbody="asdasdasd"
MailType="1"
getURL("main.asp?action=send","_self", "POST");
youmail@any.com是发送者的地址
receivermail@any.com是接受者的地址.
Thats all:D
posted @
2006-05-28 10:42 死亡猎人 阅读(279) |
评论 (1) |
编辑 收藏
引言 性能是一个特征。您必须预先设计性能,否则您以后就得重写应用程序。就是说,有哪些好的策略可使 Active Server Pages (ASP) 应用程序性能达到最佳?
本文介绍了优化 ASP 应用程序和 Visual Basic® Scripting Edition (VBScript) 的技巧。本文讨论了许多陷阱。本文列出的建议已经在 http://www.microsoft.com 和其它站点中进行了测试,效果十分显著。本文假定您已经对 ASP 开发,包括 VBScript 和/或 JScript、ASP Application、ASP Session 和其它 ASP 固有对象(Request、Response 和 Server)有了基本了解。
通常,ASP 性能主要取决于 ASP 代码本身以外的很多因素。我们不在一篇文章中罗列出所有的信息,在本文结尾处我们列出了与性能有关的资源。这些链接涵盖了 ASP 和非 ASP 主题,包括 ActiveX® 数据对象 (ADO)、组件对象模型 (COM)、数据库和 Internet Information Server (IIS) 配置。这些都是我们喜欢的一些链接 - 一定要去看看。
技巧 1:将经常使用的数据缓存在 Web 服务器上
典型的 ASP 页从后端数据存储中检索数据,然后将结果转换成超文本标记语言 (HTML)。无论数据库的速度如何,从内存中检索数据总要比从后端数据存储中检索数据快得多。从本地硬盘读取数据通常也比从数据库中检索数据更快。因此,通常可以将数据缓存在 Web 服务器上(存储在内存或磁盘中),来提高性能。
缓存是传统的以空间换取时间的做法。如果您缓存的内容正确,那么您可以看到性能会有显著的提高。为使缓存有效,必须保存那些经常重复使用的数据,且要重新计算这些数据需要(适度)大的开销。如果缓存的都是些陈旧的数据,就会造成内存浪费。
不经常发生改变的数据是很好的缓存候选数据,因为您不必担心随着时间的迁移该数据与数据库同步的问题。组合框列表、引用表、DHTML 碎片、扩展标记语言 (XML) 字符串、菜单项和站点配置变量(包括数据源名称 (DSN)、Internet 协议 (IP) 地址和 Web 路径)都是很好的缓存候选内容。注意您可以缓存数据的“表示”,而不缓存数据本身。如果 ASP 页很少更改,且缓存的开销也很大(例如,整个产品目录),则应考虑事先产生 HTML,而不是在响应每个请求时重新显示。
应将数据缓存在哪里,有哪些缓存策略?通常,数据缓存在 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 function (not shown) ' fetches data from DB, returns an Array d = FetchEmploymentStatusList() Application(?EmploymentStatusList?) = d End If GetEmploymentStatusList = d End Function %>
可以为所需要的每个数据块编写类似的函数。
应以什么格式存储数据?可以存储任何变体类型,因为所有脚本变量都是变体型。例如,您可以存储字符串、整数或数组。通常,您将以这些变量类型之一存储 ADO 记录集的内容。要从 ADO 记录集获取数据,您可以手工将数据复制到 VBScript 变量,一次一个字段。使用一个 ADO 记录集持久函数 GetRows()、GetString() 或 Save()(ADO 2.5),可加快速度且更容易一些。其详细情况已超出本文所讨论的范围,但下面给出了一个函数举例,说明使用 GetRows() 返回记录集数据的一个数组:
' Get Recordset, return as an Array Function FetchEmploymentStatusList Dim rs Set rs = CreateObject(?ADODB.Recordset?) rs.Open ?select StatusName, StatusID from EmployeeStatus?, _ ?dsn=employees;uid=sa;pwd=;? FetchEmploymentStatusList = rs.GetRows() ? Return data as an Array rs.Close Set rs = Nothing End Function
对上面举例做更进一步改进,可以将 HTML 缓存为列表,而不是数组。下面是简单的示例:
' Get Recordset, return as HTML Option list 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 Field Binding Do Until rs.EOF ' Next line violates Don't Do String Concats, ' but it's OK because we are building a cache s = s & ? <option>? & fldName & ?</option>? & vbCrLf rs.MoveNext Loop s = s & ?</select>? & vbCrLf rs.Close Set rs = Nothing ' See Release Early FetchEmploymentStatusList = s ' Return data as a String End Function
在适当的条件下,可以将 ADO 记录集本身缓存在 Application 或 Session 作用域中。有两个警告:
必须将 ADO 标记为自由线程 必须使用断开连接的记录集。 如果不能保证满足这两个要求,则不要缓存 ADO 记录集。在下面的“非敏捷组件”和“不要缓存连接”技巧中,我们将讨论将 COM 对象存储在 Application 或 Session 作用域中的危险性。
当您将数据存储在 Application 或 Session 作用域时,数据将保留在那里,直到您以编程方式改变它、Session 过期或 Web 应用程序重新启动为止。如果数据需要更新怎么办?要手工强制对 Application 数据进行更新,您可以访问只有管理员才可访问的 ASP 页来更新数据。或者,您可以通过函数定期自动刷新数据。下面例子存储带有缓存数据的时间戳,并隔一段时间后刷新数据。
<% ' error handing not shown... Const UPDATE_INTERVAL = 300 ' Refresh interval, in seconds
' Function to return the employment status list Function GetEmploymentStatusList UpdateEmploymentStatus GetEmploymentStatusList = Application(?EmploymentStatusList?) End Function
' Periodically update the cached data Sub UpdateEmploymentStatusList Dim d, strLastUpdate strLastUpdate = Application(?LastUpdate?) If (strLastUpdate = ??) Or _ (UPDATE_INTERVAL < DateDiff(?s?, strLastUpdate, Now)) Then
' Note: two or more calls might get in here. This is okay and will simply ' result in a few unnecessary fetches (there is a workaround for this)
' FetchEmploymentStatusList function (not shown) ' fetches data from DB, returns an Array d = FetchEmploymentStatusList()
' Update the Application object. Use Application.Lock() ' to ensure consistent data Application.Lock Application(?EmploymentStatusList?) = Events Application(?LastUpdate?) = CStr(Now) Application.Unlock End If End Sub
请参见 World's Fastest ListBox with Application Data,上面还有一个例子。
要知道在 Session 或 Application 对象中缓存大的数组不是一个好的做法。在访问数组的任何元素之前,脚本语言的语法要求必须临时复制整个数组。例如,如果将由字符串组成的有 100,000 个元素的数组(该数组将美国邮政编码映射到当地的气象站)缓存在 Application 对象中,ASP 必须先将所有的 100,000 个气象站复制到临时数组中,然后才能提取一个字符串。在这种情况下,用自定义方法建立一个自定义组件来存储气象站 - 或使用一个词典组件会更好。
再警告大家一下,不要将婴儿与洗澡水一起倒掉:数组能快速查寻和存储在内存中是邻近的关键数据对。索引一个词典比索引一个数组要慢得多。应针对您的实际情况,选择提供最佳性能的数据结构。
技巧 3:将数据和 HTML 缓存在 Web 服务器的磁盘上
有时,数据可能太多,无法都缓存在内存中。“太多”只是一个说法,这要看您想消耗多少内存,以及需缓存的项目数和检索这些项目的频率。在任何情况下,如果数据太多而无法都缓存在内存中,则考虑将数据以文本或 XML 文件缓存在 Web 服务器的硬盘上。可以同时将数据缓存在磁盘和内存中,为您的站点建立最适宜的缓存策略。
注意当测量单个 ASP 页的性能时,检索磁盘上的数据可能不一定要比从数据库检索数据更快。但缓存会降低数据库和网络上的负载。在高负载的情况下,这样做可大大改善总体吞吐量。当缓存开销很大的查询结果(如多表联接或复合存储过程)或大的结果集时,这是非常有效的。与往常一样,要测试一下几种方案的优劣。
ASP 和 COM 提供一些建立基于磁盘的缓存方案的工具。ADO 记录集 Save() 和 Open() 函数保存和装载磁盘中的记录集。可以使用这些方法重新编写上面 Application 数据缓存技巧中的代码示例,用文件的 Save() 代替写到 Application 对象中的代码。
有一些其它组件可以用于文件:
Scripting.FileSystemObject 可使您创建、读和写文件。 与 Internet Explorer 一起提供的 Microsoft® XML 解析器 (MSXML) 支持保存和装载 XML 文档。 LookupTable 对象(例如,用在 MSN 上)是从磁盘装载简单列表的最好选择。 最后,应考虑将数据的表示缓存在磁盘上,而不是数据本身。预先转换的 HTML 可以用 .htm 或 .asp 文件存储在磁盘上,超级链接可以直接指向这些文件。可以使用商用工具,如 XBuilder,或 Microsoft® SQL Server™ Internet 发布功能将产生 HTML 的过程自动化。或者,您可以将 HTML 代码片断放在 .asp 文件中。还可以使用 FileSystemObject 从磁盘读取 HTML 文件,或使用 XML 尽早转换。
技巧 4:避免将非敏捷的组件缓存在 Application 或 Session 对象中
尽管将数据缓存在 Application 或 Session 对象中是一个好的做法,但缓存 COM 对象却有严重的陷阱。通常,人们倾向于将经常使用的 COM 对象缓存到 Application 或 Session 对象中。很遗憾,许多 COM 对象(包括所有以 Visual Basic 6.0 或更低版本编写的对象)当存储在 Application 或 Session 对象时,会引起严重的瓶颈。
具体来讲,当任何不敏捷的组件缓存在 Session 或 Application 对象时,将引起性能瓶颈。敏捷的组件是被标记为 ThreadingModel=Both 的组件,它聚集 Free-threaded marshaler (FTM);或被标记为 ThreadingModel=Neutral 的组件。(Neutral 模型是 Windows® 2000 和 COM+ 的新增模型。) 下列组件不是敏捷的:
自由线程的组件(除非它们聚集 FTM)。 单元线程组件。 单线程组件。 配置的组件(Microsoft Transaction Server (MTS)/COM+ 库和服务器程序包/应用程序)不是敏捷的,除非它们是 Neutral 线程。单元线程组件和其它非敏捷的组件在页作用域内是最适合的(即,它们在单个 ASP 页上创建和销毁)。
在 IIS 4.0 中,被标记为 ThreadingModel=Both 的组件被认为是敏捷的。在 IIS 5.0 中,只有这一点还不够。组件必须不仅被标记 Both,还必须聚集 FTM。有关敏捷性的文章讲述了如何使以 Active Template Library 编写的 C++ 组件聚集 FTM。要注意如果组件缓存界面指针,那么那些指针本身必须是敏捷的,或必须存储在 COM 共用界面表 (GIT) 中。如果您不能重新编译 Both 线程组件以聚集 FTM,那么您可以将组件标记为 ThreadingModel=Neutral。或者,如果您不想让 IIS 执行敏捷性检查(因此,您可以允许非敏捷的组件存储在 Application 或 Session 作用域中),您可以在配置数据库中将 AspTrackThreadingModel 设置为 True。不建议更改 AspTrackThreadingModel。
如果您想将以 Server.CreateObject 创建的非敏捷的组件存储在 Application 对象中,IIS 5.0 将出现一个错误。您可以在 Global.asa 中使用 <object runat=server scope=application ...> 避免这一错误,但不建议这样做,因为这会导致汇集和串行化,关于这一点将在下面讲述。
如果您缓存非敏捷的组件会出现什么毛病?缓存在 Session 对象中的非敏捷的组件将 Session 锁定于 ASP 工作者线程。ASP 维护一个工作者线程池来处理请求。通常情况下,一个新请求总是由第一个可用的工作者线程来处理。如果 Session 被锁定于一个线程,那么请求必须等到其相关的线程可用为止。这里有一个类比,也许会有所帮助:您去一家超级市场,挑选了一些商品,并在 #_3 收款台付款。其后,每当您在那家超级市场为商品付款时,您总是必须在 #_3 收款台付款,即使其它收款台前排队的人较少或者没有人排队,也是如此。
将非敏捷的组件存储在 Application 作用域对性能的影响甚至更坏。ASP 必须创建一个特殊的线程运行存储在 Application 作用域中的非敏捷组件。这会有两个结果:所有调用都必须汇集到此线程,且所有调用都排成长队。“汇集”的意思是参数必须存储在内存的共享区域;执行一个开销很大的到特殊线程的上下文切换;执行组件的方法;将结果汇集到共享区域;执行另一个开销很大的上下文切换,将控制返回到原始的线程。“串行化”意思是指每次只运行一个方法。两个不同的 ASP 工作者线程不能同时在共享组件上执行多个方法。这样就杜绝了并发性,特别是在多处理器计算机上。更糟的是,所有非敏捷的 Application 作用域的组件共享一个线程(主机 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 ' step 1
' Populate the recordset with data rs.Open strQuery, strProv
' Now disconnect the recordset from the data provider and data source rs.ActiveConnection = Nothing ' step 2
有关连接池的更详细信息,可以在 ADO 和 SQL Server 参考资料中找到。
技巧 6:合理地使用 Session 对象
既然我们已经讨论了缓存在 Application 和 Session 中的优点,现在开始讨论避免使用 Session 对象的问题。正如下面所讨论的,当与忙的站点一起使用时,Session 有几个缺点。“忙”的意思一般是指一秒钟要求几百页面或成千上万同时用户的站点。这个技巧对于必须水平扩展的站点 - 即,那些利用多台服务器以处理负载或实现容错的站点 - 甚至更重要。对于较小的站点,诸如 Intranet 站点,要想实现 Session 带来的方,必然增大系统开销。
简言之,ASP 自动为每个访问 Web 服务器的用户创建一个 Session。每个 Session 大约需要 10 KB 的内存开销(最主要的是数据存储在 Session 中),这就使所有的请求都减慢。在配置的超时时段(通常是 20 分钟)结束以前,Session 一直保留有效。
Session 的最大的问题不是性能,而是可扩展性。Session 不能跨越几台 Web 服务器,一旦在一台服务器上创建 Session,其数据就留在那儿。这就意味着如果您在一个 Web 服务器群使用 Session,您必须设计一个策略,将每个用户请求始终发到用户 Session 所在的那台服务器上。这被称为将用户“粘”在 Web 服务器上。术语“粘性会话”就是从这里派生而来的。如果 Web 服务器崩溃,被“粘住的”用户将丢失他们的会话状态,因为会话不是粘到磁盘上。
实现粘性会话的策略包括硬件和软件解决方案。诸如 Windows 2000 Advanced Server 中的网络负载平衡和 Cisco 的 Local Director 之类的解决方案都可以实现粘性会话,代价是要损失一定程度的可扩展性。这些解决方案是不完善的。不建议此时部署您自己的软件解决方案(我们过去常常使用 ISAPI 筛选器和 URL 转换等等)。
Application 对象也不跨越多台服务器,如果您必须跨越 Web 服务器群共享和更新 Application 数据,您必须使用后端数据库。但是,只读 Application 数据在 Web 服务器群中仍是有用的。
如果只是因为要增加运行时间(处理故障转移和服务器维护),大多数关键任务站点至少需部署两台 Web 服务器。因此,在设计关键任务应用程序时,必须实现“粘性会话”,或干脆避免使用 Session,以及任何其它将用户状态存储在单个 Web 服务器上的状态管理技术。
如果您不使用 Session,一定要将它们关闭。您可以通过 Internet Services Manager,为应用程序执行此操作(参见 ISM 文档)。如果您决定使用 Session,您可以采用一些方法减轻它们对性能的影响。
您可以将不需要 Session 的内容(如帮助屏幕,访问者区域等等)移到另一个关闭了 Session 的 ASP 应用程序中。您可以逐页提示 ASP,您不再需要该页面上的 Session 对象,使用以下放在 ASP 页面最上面的指令:
<% @EnableSessionState=False %>
使用这一指令有一个很好的理由是,这些 Session 在框架集方面存在一个有意思的问题。ASP 保证任何时候 Session 只有一个请求执行。这样就确保如果浏览器为一个用户请求多个页面,一次只有一个 ASP 请求接触 Session,这样就避免了当访问 Session 对象时发生的多线程问题。很遗憾,一个框架集中的所有页面将以串行方式显示,一个接一个,而不是同时显示。用户可能必须等候很长时间,才能看到所有的框架。该故事的寓意:如果某些框架集页面不依靠 Session,一定要使用 @EnableSessionState=False 指令告诉 ASP。
有许多管理 Session 状态的方法,可替代 Session 对象的使用。对于少量的状态(少于 4 KB),我们通常建议使用 Cookies、QueryString 变量和隐式变量。对于更大数据量,如购物小车,后端数据库是最适合的选择。有关 Web 服务器群中状态管理技术的文章很多。有关详细信息,请参见 Session 状态参考资料。
技巧 7: 将代码封装在 COM 对象中
如果您有许多 VBScript 或 JScript,您可以经常将代码移到编译的 COM 对象中,从而可改善性能。编译的代码通常比解释的代码运行得更快。编译的 COM 对象可以通过“早绑定”访问其它 COM 对象,与脚本使用的“晚绑定”相比,“早绑定”是调用 COM 对象的更有效方法。
将代码封装在 COM 对象中还有一些优点(除性能之外):
COM 对象有利于将表示逻辑与业务逻辑分开。 COM 对象可以保证代码重复使用。 许多开发人员发现以 VB、C++ 或 Visual J++ 编写的代码比 ASP 更容易调试。 COM 对象也有缺点,包括初始开发时间和需要不同的程序设计技巧。注意封装少量的 ASP 可能引起性能下降,而不会得到性能改进。这种情况通常在少量的 ASP 代码被封装进 COM 对象时发生。在这种情况下,创建和调用 COM 对象的系统开销超过了编译的代码的优点。应反复地试验,以确定什么样的 ASP 脚本和 COM 对象代码的组合产生最好的性能。注意,与 Microsoft Windows NT® 4.0/IIS 4.0 相比,Windows 2000/IIS 5.0 中在脚本和 ADO 性能方面有了很大的改进。因此,随着 IIS 5.0 的推出,编译代码比 ASP 代码的性能优势有所降低。
有关在 ASP 中使用 COM 的优点和缺点的详细讨论,参见 ASP Component Guidelines and Programming Distributed Applications with and Microsoft Visual Basic 6.0。如果您部署 COM 组件,以负荷对它们进行测试特别重要。事实上,理所当然应对所有的 ASP 应用程序进行负荷测试。 |
posted @
2006-03-02 14:12 死亡猎人 阅读(212) |
评论 (0) |
编辑 收藏
只要把下面写出的这些内容复制到新建的注册表项,然后双击运行,重新启动电脑就可以实现,一般的adsl下,不用下载工具就可以达到100k以上的下载速度,而且比较稳定,可以同时从一个网站用ie来下载多个文件
注册表项建立方法:打开记事本,将下列内容(不包含=====)复制到记事本,保存时选择保存类别为“所有文件”,然后文件名必须以.reg为后缀,保存后,生成的则是注册表项了,可以直接双击生成的.reg文件来执行注册表的修改.
XP网速提升
====================================================
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
"SackOpts"=dword:00000001
"TcpWindowSize"=dword:0003e640
"Tcp1323Opts"=dword:00000001
"DefaultTTL"=dword:00000040
"EnablePMTUBHDetect"=dword:00000000
"EnablePMTUDiscovery"=dword:00000001
"GlobalMaxTcpWindowSize"=dword:0003e640
====================================================
让IE6可以9线程下载
====================================================
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings]
"MaxConnectionsPer1_0Server"=dword:00000009
"MaxConnectionsPerServer"=dword:00000009
====================================================
开启IE的下载功能
====================================================
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3]
"1803"=dword:00000000
====================================================
完成之后记得重新启动电脑,然后你上网看看,就感觉的到变化了
posted @
2006-03-02 14:08 死亡猎人 阅读(174) |
评论 (0) |
编辑 收藏