狂想年代

这是一个狂想的年代,没有想法的人是可耻的。
在元宵节的晚上,吃完奇大无比的元宵,我与往常一样写着各式各样不同的代码,继续在Fireworks中画来画去,然后与apache, python斗争。忽然与小龙聊了起来,他说,今年有10个项目要做,吓我一跳。2005整整一年,除了工作的项目,我也就做了一件事情而已。然而,想法多未见得是好事,比如我就没有看到他做成熟的任何一件产品。
有一些以外的耳闻:一个网络游戏币交易网站,一个月居然有300~400万的现金进出,这一点让我匪夷所思。我玩的网络游戏仅仅是WoW, 汗颜的时候直到现在一张点卡还没有完,所以很费解为什么这样的一个小网站能够赚到这样多的钱。看来,IT正在逐渐成为渗透力最强的行业,我们身处其中,却越来越看不透:因为IT已经成为了商业的组成部分,而写程序的我们,当然不懂商业。
让我觉得比较有趣的是,他打算做一个联合通行证。很明显一看就知道是什么:一个通行证能够访问所有支持这个通行证的网站/社区,享受所有的服务。这样的思路在许多很2的blog中出现过,但没有人做出来。我的担心一如大众:能不能取得足够多的社区的支持?而小龙的回答充满社会责任感:
这个东西本身没有什么盈利模式 但主要是提供一种方便 一种服务
一个帐户 通行神州 至少是个人网站
显然,越来越多的人意识到,人性化,方便的服务正逐渐取代技术而成为产品能否成功的关键。我发现,只要提供给消费者可用、优质的服务,真心实意地为消费者考虑,一定有出路。这是一个最好的时代,也是一个最坏的时代,一个产品得到消费者认可需要的时间越来越长,只有狂想着提高产品可用性,以提供最好用户体验为目的的人/公司,才能真正获得回报。这种回报发自真心的、忠诚度极高的回报。回报是你狂想的附加值,不是你追求的目的,就像大海,浪花只是前进标志,而不是停止的信号。

让SpringMVC也支持自定义url mapping

[#SPR-703] Make Controller aware of the url mapping – Spring Framework
提供了一个RegexUrlMappingHandler, 可以支持类似于以下的使用:

<bean id="regexUrlMapping" class="spring.handler.RegexUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/archive/(\d{4})/(\d{2})/(.*).html">blogArchiveController</prop>
</props>
</property>
</bean>
在Spring controller中:

Map objects = new HashMap();
objects.put("year", parameters.get(0));
objects.put("month", parameters.get(1));
objects.put("tag", parameters.get(2));
return new ModelAndView("/archive.jsp", objects);

使用buffalo作为webwork的验证机制-实现

要的人比较多,废话少说,放代码:
ValidationError.java, 主要是错误信息的一个DTO

public class ValidationError {
private String name;
private String value;

public ValidationError() {

}

public ValidationError(String name, String value) {
this.name = name;
this.value = value;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}

}

ValidationService.java, buffalo要使用的service, 代码不复杂,没有注释,原理见前一篇文章

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.ActionContext;
import com.opensymphony.xwork.ActionProxy;
import com.opensymphony.xwork.DefaultActionInvocation;
import com.opensymphony.xwork.DefaultActionProxy;
import com.opensymphony.xwork.ValidationAware;
import com.opensymphony.xwork.config.entities.ActionConfig;
public class [...]

Friendly URL应当作为web2.0应用首先要考虑的问题

web2.0概念的提出给这个灰暗的web应用世界带来了鲜活的色彩;而ajax的使用又给用户提供了更好的操作体验。然而,在具体的使用上,他们 给开发者带来的考虑不是更少而是更多。ajax滥用比不用更加可恶——满屏的loading实在不是什么好的体验。如何真正给用户提供真正易于理解舒心畅 快的应用,是2.0应用开发者首先需要考虑的问题。
OPOA提出后,我一直在考虑一个问题:如何将操作型应用与内容型应用有机的结合起来呢?这个问题的提出并非空穴来风。实际上,除了类似于邮件这样 的简单应用不需要考虑友好URL之外,大部分web应用,无论是企业应用还是面向消费者的 web2.0应用,都存在面对友好URL的问题。例如:到底是portal/index.action?userid=10001比较好看还是 portal/michaelchen比较好看?到底是michaelchen/photo/12319 比较容易懂还是 photo/viewPhoto.action?userid=10001&photoid=12319 比较容易懂?
答案是很容易看明白,一个好的URL不应该经常变动。
一个典型的web2.0应用在URL上首先是友好的:看看成功的应用大多如此:Flickr, del.icio.us, 豆瓣,等等。体贴的URL为传播、共享、搜索提供了潜在的巨大的便利,只有那些操作型应用系统才不需要考虑URL的组织方式。
因此,一个典型的web2.0应用,首先要考虑的是如何组织对外的URL——这个URL规则一旦建立,以后要进行变更的可能性就比较小(因为成本巨 大,无数 的人链接到了这个地址)。你可能采用某一个独立的模块来对这一部分进行维护。遗憾的是,传统的J2EE框架在这方面所做的事情少之又少,无论是 webwork还是struts, 都没有明显的对这方面的支持(所以说用这类框架做web2.0应用很痛苦);tapestry相对好一些,在4.0中可以对url进行定制。另外UrlRewriteFilter对传统应用进行了修饰,但遗憾的是,怎么用怎么感觉不太好。
如何解决?我能想到的一个比较清晰的架构是:从一开始就考虑URL的结构,采用一个独立的servlet来管理URL链接,它的功能与 UrlRewriteFilter类似,但是它的结合点不是类似于product.action?id=xxx路径本身,而是直接指向相对应需要运行的 Struts/Webwork Action(或者Spring MVC的Controller)。
下午的时候无意中看到了django, 这个新型的类似于rails的快速开发框架,显然更懂web2.0——直接有了一个urls.py文件来对各类url映射进行配置,能够直接将某一个正则表达式支持的路径映射到一个执行的方法:

patterns = patterns(”,
(r’^blog/$’, ‘blog.views.page’),
(r’^blog/page(?P\d+)/$’, ‘blog.views.page’),
)

# View (in blog/views.py)
def page(request, num="1"):
# Output the appropriate page of blog entries, according to num.

上面的例子是不是能够给我们带来一些启发?
写到这里,我有了一些结论:一个完整的web2.0应用结构上应当包含两部分:URL处理引擎和Ajax引擎。前者用于在整个WWW范围内共享传 播,后者用于改善单个用户的操作体验。这样,架构渐渐完整和清晰了。不得不说的是,目前我还没有看到任何一个JavaEE web框架明显的独立出url处理引擎的概念,tapestry做了一些,但还不够独立,SpringMVC/Webwork/Struts更不提。也许 这与java在企业应用漫长的时间有关,但是在现在,这些框架已经表现出落后了。是不是buffalo应该做这件事情呢?