2007-01
30

最近一直在开发Ajax应用程序。众所周知Ajax的特点是客户端和服务器分离, 客户端通常由纯Javascript组成,通过XMLHttpRequest对象与服务器通信。 在调试客户端代码时,如果服务器开在本地,尚可通过samba等方式直接编辑 服务器上的客户端js代码,倘若服务器在异地,那么每次修改js代码后通过FTP等 方式上传之后再调试就十分费事。说到这里自然会想到将js代码放到本地, 然而XMLHttpRequest却只能访问同一域名下的URL,本地的js代码无法直接使用 远程服务器上的服务。

迷茫之际,同事介绍了delegate这款软件,利用它即可实现本地调试客户端代码。

delegate可以在这里下载。 delegate实际上是一个功能强大的代理服务器,它有个类似于Linux的mount功能, 能够将Internet上的URL映射到本地。利用这个功能, 即可将远程的服务器端和本地的客户端集成到同一个域名下, 实现客户端代码的本地调试。

方法如下:

  1. 将Apache配置到本机的8080端口,然后将客户端代码放在htdocs下, 使之能够通过 http://localhost:8080/client/ 访问。
  2. 下载delegate并解压缩。
  3. 编辑以下的配置文件 delegate.cfg。
    -P80
    ADMIN="yourname@yourmail.com"
    MOUNT="/client/* http://localhost:8080/client/*"
    MOUNT="/cgi-bin/* http://server-address/cgi-bin/*"
    第一行的 -P80 指定delegate使用80端口;第二行的ADMIN指定管理员邮件地址, 可以随意设置;第三行将客户端映射到 delegate 的 /client/ 路径下; 第四行将远程服务器目录映射到 delegate 的 /cgi-bin/ 路径下。
    另外,如果你需要通过代理服务器访问远程服务器,可以这样设置:
    MOUNT="/cgi-bin/* http://server-address/cgi-bin/*" PROXY="代理服务器地址:端口"
  4. 在命令行输入以下命令安装delegate。注意不同版本的delegate的可执行文件名不同。
    dg9.4.1.exe +=delegate.cfg
  5. 打开浏览器,访问 http://localhost/client/。这样即可随时看到对js代码的修改。

实际上,用好这个方法还可以“盗用”许多网站的服务,即自己开发客户端, 再通过 delegate 将请求转发给服务器。其方法不再详述。



2007-01
29

今天打开Opera发现Opera又升级了。不过这次版本号跳得好快啊,实在是钦佩Opera的开发者们。原来的版本是9.02,这次居然是……

opera90-2.png

取消之后再次检查更新,还好这次版本号正常了。

opera9-10.png


2007-01
24

或许很多人已经知道这个插件了吧,Tab Effect。它能让你的Firefox在切换标签时使用类似于Linux下的Compiz的3D效果。看看下面的截图。

tab-effect.png

装上以后感觉原来的设置切换速度有点慢,打开插件目录下 content/javascript.js,寻找这一段代码:

if(TabEffect.currentTab != gBrowser.selectedTab){
    var back = currentTabIndex > gBrowser.mTabContainer.selectedIndex || currentTabIndex == -1;
    TabEffect.xpcomObj.translateToNextTab(back, 24);
    TabEffect.currentTab = gBrowser.selectedTab;
}

将 translateToNextTab(back, 24)中的24改成12,重新启动Firefox,可以看到旋转速度快了许多。不过在切换页面时有明显的延迟,使这个插件减色不少。不过总的来说,这个插件还是值得推荐的,它带来了插件开发的一个新思路。

该最新版本为1.1,仅有Windows版,需要DirectX 8支持。

ps. 如何找到插件目录?我使用的是Mr Tech Local Install,安装该插件之后,在插件管理面板上选中想要查看的插件点右键,选择浏览安装目录就可以了。要是没有安装该插件,那就在 C:\Documents and Settings\用户名\Application Data\Mozilla\Firefox\Profiles\nnnnnn.default\extensions 目录下一个个找吧。



2007-01
17

花了一个小时时间做了这个新的网站主题。本以为能很快搞定的,结果在细节部分用了比较多的时间。侧边栏的颜色有些不协调,没时间改了。

不多说了,先上图看看效果吧。具体能不能用CSS实现以后再说吧。

inspiremedia-design-vista.jpg

感谢frank提供背景照片,我先用着了,回头跟你打招呼



2007-01
16

我从大学时使用电脑到现在已有将近八年的历史了,期间病毒也遇到过不少,但从来没遇到什么麻烦。 总结一下经验,下面的十条可以让你远离病毒的烦恼。

系统安装盘多多益善

不管你是用Windows XP,还是Windows 2000,甚至更老的Win98, 安装盘至少要有两张以上。仅有一张盘则很容易坏掉或丢掉。

系统崩溃时要有办法恢复数据

我通常用CDLinux作为启动盘,即使Windows系统崩溃了,使用CDLinux启动系统也能将里面的数据复制出来。 如果你不会用Linux,就把重要数据都放在FAT32分区上,崩溃时用Win98的启动盘恢复数据。 据说ntfsdos能读取NTFS分区,不过我从来没成功过。不要用WindowsXP的恢复控制台, 因为(1)功能太弱 (2)不支持网络,即使能恢复数据也没法拷出来 (3)登录时需要管理员密码, 如果Windows的用户数据库损坏就无法登录了 (4)太脆弱,注册表坏掉就无法登录。

阅读全文 »

2007-01
11

眼看Windows Vista就要正式发布了,趁着这个机会咱也赶赶时髦。这是Vista的黑色任务栏按钮。所用软件为Photoshop 7。

  1. 新建一张图,前景色选灰色(作为辅助色,可随意选一种较淡的颜色),用圆角矩形工具, 设置圆角半径为 3 像素,画一个高 30 左右的矩形。
    ps-vista-button-01.png
  2. 新建图层,用矩形选择工具在按钮上部约50%的地方选择一个矩形。选区越靠上,按钮就越显得凸起。 然后按住Ctrl+Alt+Shift,单击图层面板中第一步建立的形状图层,以选中按钮的上半部。
    ps-vista-button-02.png
  3. 选择前景色 rgb(200,200,200),背景色 rgb(90,90,90),使用渐变工具由上至下在选区中填充渐变色。
    ps-vista-button-03.png
  4. 按Ctrl+Shift+I反选,再按住Ctrl+Alt+Shift单击图层面板中第一步建立的形状图层,选择按钮下半部分。
  5. 设置前景色为 rgb(24,24,24),按Alt+Del填充选区。
    ps-vista-button-04.png
  6. 按Ctrl键单击图层面板中的形状图层,然后选择减淡工具,宽度5像素,曝光度设置为50%,加亮按钮的边缘。 特别是圆角部分可以适当加大高光区。
    ps-vista-button-05.png
  7. 保持前景色为 rgb(24,24,24),选择主菜单编辑->描边,居中1像素。 然后选择前景色为rgb(200,200,200),再次选择主菜单编辑->描边,居外1像素。最后按Ctrl+D取消选区。
    ps-vista-button-06.png

效果还不错吧?最后可根据需要隐藏背景层和形状图层,输出成png格式,便于在网页上使用。



2007-01
10

昨天晚上上网发现,原来几乎很慢的国内网站已经能打开了,今天又发现原来一直连不上的抓虾也能正常使用了,虽然速度稍稍慢一点。难道海底光缆已经修好了吗?

查了一下发现新浪今天凌晨发出了首期光缆修复昨日完成 20日有望连接的报道,看来的确是这条修复的光缆起了作用。另据报道,全部修复可能要到一月底,和当初的预想一样。看来工作进展不是很顺利。


2007-01
05

Wordpress的官方文档对数据库的结构描述得并不充分,索性自己来分析一下。首先从整体结构入手。 下面是2.0.5版的数据库结构图(E-R图)。为了节约篇幅,这里仅列出了主键和外键。 图中菱形表示1:n的关系,白色部分为1,黑色部分为n。

wordpress-db-er-diagram.png

Wordpress共有10个表,按照功能大致分为四类。

  • user: 用户信息,包括wp_users表和wp_usermeta表。
  • post: 文章及评论信息,包括wp_posts、wp_postmeta、wp_comments、wp_post2cat以及wp_categories五个表。
  • link: 链接信息,包括wp_links表和wp_linkcategories表。
  • option: 全局设置信息,包括wp_options表。

个人认为这个数据库有两个冗余的地方。一个是wp_post2cat表中的主键rel_id,其实可以不要rel_id,而使用post_id和category_id两列作为主键; 另一个是wp_options表,option_id列为自动增长列,仅使用该列即可作为主键,而不需要option_id、blog_id、option_name三列联合做主键。

另外,表的命名规则也很有意思。基本规则总结如下:

  • 保存对象的基本属性,命名为 wp_objects,使用复数(如 wp_posts,wp_comments);
  • 保存对象的扩展属性,命名为 wp_objectmeta,使用单数(如wp_postmeta,wp_usermeta);
  • 多对多关系,命名为 wp_a2b,其中a和b分别为多对多关系两端的对象名的缩写(如wp_post2cat)。


2007-01
02

301就是HTTP协议中的应答状态301 Moved Permanently。 当你的网站更换地址后,应当在原地址上写个程序返回301, 以便让访问者能够知道你更换了地址,也让搜索引擎能迅速地收录新地址。 我的blog更改地址之后,经fcicq的提醒, 使用 mod_rewrite 返回301,三天后就有100多页面被Google收录。

下面是使用各种语言返回301的方法。调试时可使用Firefox+ Tamper Data插件, 也可以用IE的ieHTTPHeaders插件。

ASP

直接调用Response.Redirect函数会返回302 Object Moved。为了返回301, 我们需要手工设置信息。

<%@ Language=VBScript %>
<%
  Response.Status = "301 Moved Permanently"
  Response.AddHeader "Location", "http://www.inspiremedia.org/"
  Response.End
%>

PHP

简单地调用 header() 函数输出头信息即可。

<?php
  header("301 Moved Permanently");
  header("Location: http://www.inspiremedia.org/");
?>

Perl

#!/usr/bin/perl -w
print "Status: 301 Moved Permanently\n";
print "Location: http://www.inspiremedia.org/\n\n";

mod_rewrite

如果你使用Apache,那么用mod_rewrite进行重定向是最简单的选择了, 只要在 httpd.conf 的全局配置或者虚拟主机配置中写一条规则即可。

RewriteEngine On
RewriteRule ^/(.*) http://www.inspiremedia.org/$1 [R=permanent,L]

注意一定要使用 [R=permanent] 选项,仅用 [R] 选项会返回 302 。



2007-01
02

Wordpress的效率问题似乎一直是议论的热点,今天来看看其中一条SQL语句的效率。

首先将所有插件禁用,并切换为默认模板。 然后按照《WordPress执行效率问题》这篇文章的方法, 在 wp-config.php 中加入

<?php define('SAVEQUERIES', true); ?>

在模板的 footer.php 中加入

<!-- <?php var_dump($wpdb->queries); ?> -->

访问首页,即可从源代码中看到SQL语句。

执行时间最长的是这一条,花了0.02秒:

SELECT DISTINCT * FROM wp_posts  
WHERE 1=1 
  AND post_date_gmt <= '2007-01-02 07:12:59' 
  AND (
    post_status = 'publish' 
    OR
      post_author = 1 
      AND post_status != 'draft' 
      AND post_status != 'static'
  )
  AND post_status != 'attachment' 
GROUP BY  wp_posts.ID  
ORDER BY post_date DESC 
LIMIT 0, 10"

这条语句位于 class.php 的 WP_Query->&get_posts() 函数。

说说这个SQL语句的问题。不妨先来看看 wp_posts 表的结构(省略无关列)。

列名类型索引
IDbigint(20)PRIMARY
post_authorbigint(20)
post_date_gmtdatetime
post_statusenumINDEX
post_namevarchar(200)INDEX

首先是关键字 DISTINCT,DISTINCT的作用是去掉重复的数据, 相当于对选择的列进行 GROUP BY。而这条语句中选择了 * 列,包含了主键列 ID, 每行数据必然不相同,因此 DISTINCT 关键字起不到任何作用, 白白浪费一次排序。

其次是 post_date_gmt 和 post_author 上的比较操作。wp_posts表仅有 ID、post_status 和 post_name 列上有索引,对其他列的比较操作使得mysql不得不访问wp_posts表的所有数据, 影响效率。

然后是 post_status 上的不等于的比较。对索引列使用不等于比较, 会导致数据库不能使用索引(索引只能判断等于关系)。 另外显然已经有了 post_status = 'publish' 的条件, 不必再判断 post_status != 'attachment'。

最后是 GROUP BY wp_posts.ID,仍然是对一个不会重复的列进行 GROUP BY, 毫无意义。

如果不考虑功能损失,将这个 SQL 语句优化为下面这样,则仅需花费0.003秒。

SELECT * FROM wp_posts  
WHERE 1=1 
  AND post_status = 'publish' 
ORDER BY post_date DESC 
LIMIT 0, 10"

使用Apache Bench做测试,优化前平均每个请求的处理时间为 503.125ms,优化后为 478.125ms。