正在查看: Saturn 所写的文章(第 1 页 / 共 53 篇)

全新的开始

这可能是自我2007年初开始架设独立博客以来,感受到的最沉重的教训——博客文章、留言以及友情链接等数据全部丢失。

由于需要准备出国的一些事宜,自2008年年底开始,我一直疏于对自己博客的打理。直到最近,在墨尔本的生活和学业事宜一切安定下来之后,我却突然发现,由于忘记续费,原来的博客主机提供商关闭了我的主机空间——这也直接导致了目前大家所见到的我的全新博客。

所以说,不管做什么网站,网络管理员和网站所有者都应要有一份危机意识,时刻居安思危,做好网站的数据备份,以备不时之需。

幸好还有Google和Baidu这样的搜索引擎,我还可以通过SITE命令找回原来博客中的一些重要信息。在此时,搜索引擎成了我博客的时光机。

你现在所看到的这个博客的程序,是我花了大概4天时间,使用CodeIgniter这个PHP敏捷MVC框架编写的全新博客程序。

我将这个博客程序命名为STBlog——以我的英文名Saturn缩写命名的博客程序。在时间允许的情况下,我会进一步修改此博客程序的源代码,然后在适当的时候公布它,也希望有朋友和我共同进行开发和拓展。

虽然仅花费大约4天时间(每天编程10小时以上)完成了现在这个版本的程序,但我认为它已经达到了一个轻量级博客程序的所需的基本元素,包括:

  • 程序的所有URL均采用REST友好风格,非常适合SEO;
  • 日志的CRUD(Create创建- Retrieve获取-Update更新-Delete删除)可视化操作
  • 文章分类的CRUD可视化操作
  • Trackback的CRUD可视化操作
  • 可自定义生成所需页面

这个版本的程序所采用的一些技术和思想:

  • 博客前台和后台均完全采用MVC架构进行设计
  • 借助CodeIgniter对可能访问量较大的页面进行缓存(Cache)
  • 使用所见即所得文本编辑器Tiny-mce。
  • 前台留言使用在Wordpress中非常流行的Akismet进行垃圾留言(Spam)过滤。

从某种程度上来讲,一套博客程序的评论和留言功能就是程序和Spam进行斗争的正面战场,因为83%的评论都是垃圾留言

虽然我们可以通过在程序中加入算法复杂的验证码来一定程度的杜绝Spam的推送,但问题也随之而来:第一,你无法保证这个算法会永远有效,Spammer们迟早有一天会破解;第二,它会严重影响用户体验。所以,在迫不得已的情况下,建议不要使用验证码来杜绝Spam。

我博客的评论部分,没有采用验证码来防止Spam的发生,而是采用目前非常流行的Akismet服务机制。Akismet是一个提供垃圾留言和评论过滤的Web Service,我们可以将它想象成一个Spam信息垃圾场——收集了全球最多的关于Spammer的信息。

但它有一个比较大的缺陷:因为是调用的第三方服务,虽然在Spam的拦截效率上会随着时间的推移而提高,但是它会影响程序的执行效率——特别是在网络条件不好的时候。

这或许就是矛盾论在程序设计中的一个突出体现吧。

以此文作为我重新开始博客写作的第一篇吧!

Tags: 博客,blog

隐藏CodeIgniter程序URL中index.php的方法

CodeIgniter(以下简称"CI")是一款国外优秀的PHP轻量级MVC框架,它支持PHP4和PHP5,是开发中小型可拓展性需求高的Web应用程序的利器。目前你所见到的这个博客程序,正是采用CI进行的编写。

秉承MVC架构的思想,CI中的所有控制器都需要经过单点入口文件index.php(默认)来加载调用。也就是说,在默认情况下,所有CI开发项目的URL都形如以下这种形式:

http://localhost/index.php/blog/logs/this_is_a_test_entry

很显然,默认情况下,index.php在URL地址段中的存在一定程度上影响了URL的简洁和SEO的进行。我们可以通过下面本文介绍的方法来去掉这个讨厌的Index.php。

你或许已经注意到在CodeIgniter用户手册中,已经存在关于此问题的解决方法。但官方提供的这个.htaccess配置,并不是所有时候都能解决问题。本文现在给出一个更完善的解决方案。

注意:在继续之前,请确认你的主机支持.htaccess配置。其中,如果Apache作为Web服务器,需要开启mod_rewrite模块的支持;如果将IIS作为Web服务器,则需要额外安装ISAPI_Rewrite拓展。

具体方法如下:

1. 将以下配置信息复制并保存为.htaccess文件。

RewriteEngine On

RewriteBase /  

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d  

RewriteRule ^(.*)$ /index.php?/$1 [L]      

#如果没有安装mod_rewrite模块,所有的404页面都将被 # 发送到index.php,此时,程序会像没有设置隐藏时一样运行  

ErrorDocument 404 /index.php

2. 将以上.htaccess文件上传到CI所在项目的根目录(即与index.php同级目录下)

3. 修改application/config.php中的如下参数:

$config['index_page'] = "index.php";

$config['index_page'] = ""; //设置为空

以上三步,缺一不可。如果一切配置正常,你会发现,再次运行程序的时候,程序已经自动隐藏index.php这个URL段了!

最简单去除UTF-8文件中BOM的方法

当你采用UTF-8格式作为网页编码时,如果发现网页在不同浏览器中外观表现不同,比如在Firefox中正常显示,但是在IE浏览器中出现多余的本不该出现的空行(通常在网页头部);此时你应该怀疑是BOM(Byte-Order Mark )在作祟了。当然,本文的前提是你的HTML和CSS代码均正确无疑。

志勇兄曾专门撰文提到过如何去掉UTF-8文件中BOM的方法。在这里,我想补充一个非常简单的办法——使用Notepad++去除文件中的BOM。

Notepad++是由一个台湾程序员开发的优秀的文本编辑器,也是我除了Editplus之外,非常喜欢的一款代码编写工具。它在处理文本格式方面应该算是诸多免费文本编辑器中最强的一个了。

言归正传,要去除存在UTF-8文件中的BOM,你只需要使用NotePad++打开这个文件,然后选择“格式”,再选择“以UTF-8无BOM格式编码”,最后重新保存文件即可!

使用Notepad++去除UTF-8文件中的BOM

本文的最后,我介绍一个小经验:

当大家在碰到网页解析上(包括CSS和HTML解析)的诸多奇怪问题(比如这个由BOM导致的奇怪空白行)时,切勿急躁,首先应该确定你的代码编写无误;如果问题仍然存在,将代码提交到W3C网站进行HTML验证CSS验证;最后根据验证结果的提示,更正自己的代码。尽量遵守W3C规范,按这个流程,一般问题都能得到解决。

Tags: bom,编码

博客加入代码高亮功能

我的博客程序后台使用的是TinyMCE编辑器,今天花了点时间给编辑器整合了Geshi代码高亮

C#语法高亮测试:

测试:c#代码高亮
1 2 3 
private static void test(){  Console.WriteLine("Welcome to cnSaturn.com"); }

ASP语法高亮测试:

1 2 3 
function test(){  response.write "Welcome to cnSaturn.com" }

JAVA语法高亮测试:

1 2 3 
public static void test(){  out.println("Welcome to cnSaturn.com"); }

PHP语法高亮测试:

1 2 3 
public function test(){  echo "Welcome to cnSaturn.com"; }

JAVA实现向上取整、Unix时间戳到普通日期转换等函数

最近正在做的一个项目使用Java在同一个客户端中Consume多个REST类型的WebService,包括Yahoo! Search API, YouTube Video APIFlickr

我这里想说的不是如何使用Java来调用这几个知名的WebService,而是我个人在客户端制作过程中编写的几个简单实用的函数。关于Java调用WebService的具体方法和方案,我会在稍后的系列日志中详细说明。

说明:由于我本人也是正式接触Java不久,如果以下函数有不妥的地方,请告诉我。

1、Java中的向上取整:

我们知道,在PHP中如果要对一个浮点数进行向上取整操作,只需要使用PHP的内置函数ceil即可。

比如,要将1/3向上取整为1,只需要如下操作:

echo ceil(1/3);

那么在Java中,我们也可以编写一个小函数来实现上面的功能:

public int ceil(int a, int b){
    return(((double)a/(double)b)>(a/b)?a/b+1:a/b);
}

2、Java中将Unix时间戳字符串转换成普通日期格式。

//Convert Unix timestamp to normal date style
private String TimeStamp2Date(String timestampString){
  Long timestamp = Long.parseLong(timestampString)*1000;
  String date = new java.text.SimpleDateFormat("dd/MM/yyyy hh:mm:ss").format(new java.util.Date(timestamp));
  return date;
}

在调用Yahoo! News Search的WebService中,当我们提交了一个REST请求之后,假定Yahoo服务器回传给我们一个XML格式文档(假定是因为REST可以以多种格式回传数据流,比如JSON和CSV),此时每条新闻的日期均采用Unix时间戳来显示。在实际运用中,我们需要将它们转换成人们可以理解的正常格式。这就用到了下面我写的这个简单函数。

FAQ:什么是Unix时间戳?

Unix时间戳(英文为Unix epoch, Unix time, POSIX time 或Unix timestamp)是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。

Tags: java,日期

语义化:未来搜索引擎的发展方向

最近几天,关于wolframalpha挑战Google搜索引擎霸主地位的新闻在业界抄的是沸沸扬扬。

一款名为WolframAlpha(简称WA)的新型网络搜索引擎于16日正式上线(英文网址为www.wolframalpha.com)。这种搜索引擎不会返回大量网页链接,而是基于新的算法和大型数据库,直接给出答案。

我并不认为现在的wolframalpha能够对Google造成任何形式的挑战和威胁,那些耸人听闻的说法不过是媒体的大肆炒作罢了。毕竟类似wolframalpha目前这种新式语义化搜索技术尚不成熟,而以一种不成熟的技术去颠覆Google苦心经营了十年的搜索帝国,这显然是天方夜谭。更何况,从心理学角度讲,用户对Google本身的依赖,并不只决定于Google搜索技术水平,还由Google在某一特定区域的品牌价值决定。

这也是就为什么Google在中国市场很难战胜Baidu的原因。2005年的时候,百度可以自豪的称,百度更懂中文。但经过若干年的本地化,谷歌对汉语搜索的支持似乎并不比百度差多少。不过,就目前的市场份额来看,Google仍然不能对百度造成太大的威胁。这主要是因为中国网民已经对百度,或者说这个品牌产生了依赖。

回到wolframalpha挑战Google这一话题上来。

人们对于wolframalpha作为“Google杀手”的愿景,实际上是对未来搜索引擎的愿景——语义化搜索。

传统搜索引擎,不管是雅虎,Google还是百度,对搜索结果的处理都是首先对搜索关键字进行分析,然后根据“网页受欢迎度”对其已索引的网页进行排序,然后展现给用户,由用户对信息进行进一步检索。这里所提到的“网页受欢迎度”就是我们通常所说的“网页评级”。

换句话说,搜索引擎本身并不理解用户输入关键字的具体意思,它只对字符本身进行匹配。

传统搜索引擎的诟病就出在这里:一个网页评级很高的网站所输出的某篇文章(比如国内的几大门户网站),或许文章的“质量”并不高,而且可能并不是用户所希望检索到的文章。但就是因为这篇文章所在网站的网页评级很高,导致这篇文章在搜索引擎的排序却很高。这其实在一定程度上是对用户的一种误导,因为用户失去了以最短时间获取最高质量文章的机会,他们得到的结果可能仅是一些牛头不对马嘴的文章,此时他们需要更多的时间来进一步对这些文章进行筛选甄别。换个角度,如果某个独立博客上有一篇非常优秀的文章,但正是因为这个博客本身的网页评级不高,导致这篇文章失去了被“曝光”的机会。

语义化搜索引擎所需要做的就是传统搜索引擎没有做到,或者说没有做好的这一部分。那就是:搜索引擎“理解”用户输入文字的意思,然后根据语义给出筛选结果。

Wolframalpha正是一个集成此思想的新型搜索引擎,它就像一个互联网的先知,负责回答用户的各种问题,比如在Wolframalpha上搜索"China",你会看到有关中国的各种统计信息,包括人口,GDP,语言等等很多信息。

假设你进一步精确你的搜索关键字,输入"Where is China"(中国在哪?),Wolframalpha会直接告诉你中国在世界地图中的位置。

至此,或许你已经不难理解为什么国外媒体喜欢将Wolframalpha当作Google杀手了。

语义化搜索引擎,国外比较有名的还有Hakia(国内的我还没有发现,如果谁发现了请告诉我),它同样以文章质量的评级来对搜索结果进行排名,而非受欢迎程度。Hakia还是一个SaaS的典型应用,在以后的文章中我还会提到。

毫不夸张的说,语义化搜索本身的确可以对Google造成致命一击,但问题是,现在的wolframalpha并不等于语义化搜索引擎。如果你多尝试输入几次关键字,就会发现它目前能回答的问题很少。但不管怎样,Wolframlapha的出现或许昭示着搜索引擎格局的重大变更。互联网的准则就是"Nothing is impossible"(没有什么不可能),不相信这句话的人结局会很悲惨,比如现在的雅虎。

但不管怎样,我斗胆预言,在未来二十年内,搜索引擎的格局势必会再次发生转变,而转变的重心之一即是搜索引擎的语义化。

NetBeans 6.5下编写BPEL的WEB客户端出现nullpointerException的问题

今天在用NetBeans下开发BPEL时碰到了一个非常郁闷的事情,极可能是个BUG。

在NetBeans 6.5下,当我在一个WEB Project中调用已经部署好的BPEL时,SOAP始终返回的是Null值,就是我标题里面的NullPointerException。

此BPEL流程在逻辑和代码上绝对没有问题,这100%可以肯定,理由是在部署在服务器上的复合应用程序里面,我做过TEST CASE,SOAP数据返回一切正常。

让人崩溃的事情出现了,当我直接通过桌面用户的程序或者Console应用程序来Consume这个BPEL WebService却可以返回正常的数据。

于是,我开始怀疑是服务器的问题,在J2EE容器由Tomcat换成Glassfish后,发现问题依旧。

值得注意的是,在NetBeans的邮件列表里面有不少人碰到与我类似的问题。但到目前为止,我仍没有找到原因所在。

NetBeans 6.5对BPEL开发的支持实在是比较鸡肋。举个例子来说,我到现在为止都没有发现直接支持RESTful WebService的NetBeans插件。Eclipse倒是不少,比如JOpera,它可以直接将RESTful WEB服务返回过来的数据编组为SOAP格式,再供BPEL作为合作伙伴方式调用。

Java中的冒泡排序算法

在Java里面有内建的排序函数,比如要对一列字符数组进行排序,可以使用如下方法:

double[] lengths = {120.0, 0.5, 0.0, 999.0, 77.3};
Arrays.sort(lengths);
System.out.println(Arrays.toString(lengths));

当然,我们可以用最原始的排序方法,比如冒泡法来对数组列进行排序,如下:

Integer[] arrIds = {12,24,1,2345,24,10};

int len = arrIds.length;

int temp;

if(len>0){
    for(int i = 0;i<len;i++){
  for(int j=len-1;j>=i;j--){
      if(arrIds[j]>arrIds[i]){
    temp = arrIds[i];
    arrIds[i] = arrIds[j];
    arrIds[j] = temp;
   }
  }
 }
}

for(int i=0;i<len;i++){
    System.out.println(arrIds[i]);
}

可以将以上算法简单的封装成方法,在实际中应用。

Tags: java,排序

防止AJAX动态结果在前端页面缓存的方法

在利用AJAX从后台程序提取数据,然后在前端页面显示出来的过程中,我们经常会碰到AJAX提取的数据被缓存,导致结果异常的问题。

具体原因是因为AJAX依赖于JavaScript,而浏览器会自动将JavaScript代码和文件数据缓存在客户端,这有利于用户下次访问时页面的快速下载和解析。

要解决数据被缓存,大概有两种做法。

第一种,是在客户端进行,在AJAX发送请求到后台数据处理页面的URL上加一个随机字符串 即可。这样一来,浏览器会认为AJAX发出的HTTP请求每次都不同(URL不同),从而每次都重新请求。具体做法如下:

xmlHttp.open("GET", "ajax.php?r="+new Date().getTime(), true);

既然是随机字符串,还可以使用:+math.random(),只要保持字符串随机即可。

另外一种是在服务器端进行。具体做法是修改HTTP头信息,手动设置让其过期。下面以PHP为例说明:

header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
 header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified
 header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
 header ("Pragma: no-cache"); // HTTP/1.0

其他语言,比如ASP,J2EE,做法与此非常类似。

通常情况下,我们只需要选其以上两种方法的其中一种即可。

Tags: ajax,缓存

解决办法:服务器未能识别 HTTP 标头 SOAPAction 的值

本文主要探讨跨平台调用Web Service出现:"服务器未能识别 HTTP 标头 SOAPAction 的值"的解决办法。

症状一:

Web Service + ASP.NET 应用程序部署到服务器默认目录中,在IE中用http://<服务器地址>/<程序目录名>/<默认启动页面名>发生“服务器未能识别 HTTP 标头 SOAPAction 的值”错误。

症状二:

在Java平台上调用.NET Web Service的服务时,出现"服务器未能识别 HTTP 标头 SOAPAction 的值"。

症状三:

在Java平台下调用.NET WEB Service,出现数据时有时无。

解决对策:

给.NET的WebService类(即.asmx文件下的类)添加属性[SoapDocumentService(RoutingStyle=SoapServiceRoutingStyle.RequestElement)]

小知识:

什么是SoapAction?它在WSDL中有何作用?

SOAPAction HTTP request header被用来标识SOAP HTTP请求的目的地,其值是个URI地址。SOAP发送并不限制格式、URI特征或其必须可解析,那么在这种情况下,发送一个HTTP SOAP请求时,其HTTP客户端必须使用/指明SOAPAction HTTP request header。

SOAPAction header的内容可以被用在服务端,诸如:防火墙适当的过滤基于HTTP的SOAP请求消息等场景。SOAPAction header的值为空串("")表示SOAP消息的目的地由HTTP请求的URI标识;无值则表示没有指定这条消息的目的地。