MySpace looks some like Portlet. Is it just like at face?
MySpace has a MySpace Developer Platform. What is it?
2008年7月29日星期二
MySpace and Portlet
标签: Web Development
2008年7月8日星期二
different framework, different web page
the Struts treats a page as a Command;
the Portlet treats a page as a Window;
the JSF treats a page as a lot of Components;
the Spring Web Flow treats a lot of pages as a Flow;
the Tapestry treats a page as a Java class
标签: Web Development
2008年3月15日星期六
从JSP到Velocity
1.JSP有优点。
Rails页面脚本的做法跟JSP其实差不多,也是在HTML中通过<%...%>将Server端语言嵌入其中,这应该是最容易实现的方法。如果说比JSP有强出的地方,那就是Ruby的语法比Java简洁很多。
Grails:
Struts:
对于这种用XML格式来表达逻辑,同JSTL大同小异,个人感觉总是别扭。一则不如Server端语言灵活,二则要掌握另外一种语法。
相比velocity就做的很直观了:
#foreach ( $item in [1..5] )
On this iteration, refers to the value $item.
#end
其做法更多是贴近一般语言的习惯,仿佛只不过是在语句前加上#(velocity里面称为Directives),变量前加上$。
Grails里面变量的表示为"${}"。一些流行的Javascript框架如prototype、JQuery也采用这种写法。不过这种变量的表示在JSP 2.0里面也被引入,我们就再也不必看到难看如<%=name%>的写法了。
对于XML格式的标签写法,可能对于机器来说容易处理,其实在这里没有一般的语法的校验,有的只是XML的scheme的校验,当然这也是一种语法,不过就容易处理多了。
对于Velocity,其采用了Antlr来产生语法分析器,在其源代码包org\apache\velocity\runtime\parser 下可以看到详细的代码。
还有另外一种模板框架freemarker,跟velocity很类似。
如果我们采用更为简洁的做法:将逻辑和页面彻底的分离,如JSF或者Tapestry的做法,让页面更为单一和纯净。这可能是最理想的做法,也有更好的对页面组件的重用性。但是当前台页面异常复杂,需要浏览器端较多javascript操作,特别是AJAX的引入,势必有越来越多的页面逻辑转移到客户端,从而破坏了整个架构的一致性,让扩展更难处理。
这说明B/S架构中的逻辑存在于浏览器端和server段是导致系统复杂的根本原因。
C/S就没有这样的烦恼。
为什么呢?
对旧技术的补丁,最好的技术是GWT,其将逻辑集中于java代码中(虽然客户端的代码和server端的代码还是分开的)。
而新的技术,则是RIA。
标签: Web Development
2008年3月9日星期日
jQuery的做法
最近学习jQuery.
jQuery正如其名字一样,是一个用来方便的查找到HTML文档中的元素的javascript框架,其查找条件的语法借鉴了CSS和XPath中对DOM元素定位的方式,由于CSS的广泛流行,jQuery可以很快的上手。
jQuery对查询的结果统一返回为集合,而且可以对该集合再次查询,如:
$('div.disText').attr('title','点击来编辑数据').mousemove(handleMouseMove).mouseout(handleMouseOut).click(handleClick);
这是很直观的方式,让人奇怪:为什么很少在其他地方见到这样的简洁的模式呢?
(其实在JAVA中也有,比如:
StringBuffer buff = new StringBuffer(128);
buff.append(getModuleName("dojo"))
.append(".require('")
.append(getModuleName(name))
.append("');");
)
jQuery这种视一切为“集合”的方式对“批量”的处理DOM可谓得心应手,而在Web应用中,页面可以显示大量的信息,这些信息可以以常以相同的样式表现,比如“超链接”,在这里用jQuery就可以统一的这些元素处理。和传统的Fat Client不一样,这些页面以XML的格式来定义,还有比如XUL,也以XML来定义界面。XML是一种结构化的数据格式,所以就需要jQuery这样的框架。
后记:LINQ,.net下的一个框架,也有跟上面类似的语法:
var myList = [
{FirstName:"Chris",LastName:"Pearson"},
{FirstName:"Kate",LastName:"Johnson"},
{FirstName:"Josh",LastName:"Sutherland"},
{FirstName:"John",LastName:"Ronald"},
{FirstName:"Steve",LastName:"Pinkerton"}
];
var exampleArray = From(myList).
Where("item.FirstName == 'Chris'").
OrderBy("item.FirstName").
Select("item.FirstName");
标签: Web Development
2007年11月27日星期二
Rethink the big element in web page: Data Table
Data Table is heavily used in information system. In most case, these tables just display a query result set. They are read only. The operations on them are: paging, sorting, single selection and multi-selection. The all elements of a table include: field, field title, sort and page number state, and value format(or convert). In some extend, a data table is not too much associated with other page elements. So it will be a better way to define a table in one place other than several places in application.
标签: Web Development
Commet, Grizzly and Tomcat 6
一个比较早的对这方面讨论的帖子在这里: Comet,下一代Ajax? DW上面好几篇文章做了介绍:Comet:基于 HTTP 长连接的“服务器推”技术,面向 Java 开发人员的 Ajax: 使用 Jetty 和 Direct Web Remoting 编写可扩展的 Comet 应用程序。在《Ajax Design Patterns》这本书上也有介绍,不过称为HTTP Streaming。Java EE 迎合 Web 2.0 采用事件驱动的异步架构应对现代 Web 应用程序带来的挑战这篇文章从理论的高度说明了异步模式对提高系统吞吐量的作用。
如果要实现Comet,Server端就需要NIO来解决HTTP长连接的问题,否则Server端支持的并发数就会大大减少。
Servlet和NIO的使用可以参考Servlet API 和 NIO: 最终组合在一起 使用非阻塞 I/O 构建基于 Servlet 的 Web 服务器。虽然是一篇较早的文章,仍然提供了很多关于NIO的有用信息。
Tomcat 6里面相关NIO的配置可以参考其文档,只用修改Connector的protocol即可。接下来可以写一个简单的Servlet A,其implements CometProcessor接口。为测试方便,将Sender存放在Application变量中,在另外一个Servlet B中就可以调用Sender的send(...)方法,当浏览器访问A时,可以动态看到Server端push过来的信息(这时浏览器会一直处于页面正在装载的状态,实际应用中可以用AJAX来接受信息)。
由于是长连接,数据在传送过程中就存在缓冲的问题。一般的一个Server端的发送到客户端的消息(注意这里不是一个响应)不会很大,而默认的Tomcat缓冲配置偏大,导致客户端响应滞后,出现这种奇怪的现象:1)当send(...)方法触发多次后,server才会一次把消息全部push到客户端(即是每次使用了flush方法);2)1 发生后,每次的send(...)的调用会导致server段立即把这条消息发送到客户端(这是buffer又好像不存在一样)。
对于Tomcat 6自带例子里面的bug,也有位哥们在他的blog中提到:Asynchronous IO is hard!。
标签: Web Development
2007年10月31日星期三
A nice article about JSF state
developerWorks recently posted an article: Auto-save JSF forms with Ajax. The article provided an approach to implement auto-save function(some like Word's auto-save) in web tie. It told us where the data saved and how to recover from the saved data. This article used much JSF knowledge(some like component state) which is different from JSP tag-lib or other technology and in this case we can see JSF and Ajax is powerful.
And more, in some other scenario where auto-save is no need. For example, the customer want to keep some crucial form and he can resume from it later, he can do it by click a "Save" button by himself. Because auto-save isn't needed everywhere. And auto-save sometimes makes customers confused. Only the customer thinks that he has finished the form nearly, then recover from that point is constructive for him. Though AJAX is useless here, the way the author provided is also helpful and suggestive if JSF is still the choice of web framework.
So from the viewpoint of an end user, a good designed page should tell him, whether the current form is auto-save or not. Something should notify the user, whether the save action is success or failed. And the user can find all forms he has saved somewhere. So he can resume from there conveniently. At last the system looks maybe some like a workflow system.
标签: Web Development
2007年9月12日星期三
The unique of Tapestry
What's the difference between web development and traditional C/S application such Swing? Personally I like Swing because it let me more efficient. All the code is Java code and there is little type-cast. And Tapestry also follows this way. The author admitted that:
An advantage for Tapestry, I think, is the way the two pages (the firsts containing the form, the second displaying the result) communicate ... in proper, type-safe Java code.This means if you want to invoke a web page, what you face is a java class. Blow is a example:
public IPage doSubmit()
{
ShowProject showProject = getShowProject();
showProject.setProject(getProject());
return showProject;
}Get a page class(by injection), give it some value and then you can forward to that page. The page class has included a page and we can say it is the interface of the page. But the best way, I think, is the function like way. Some likes "showProject(project);". Compared with Object initialization which is not undocumented and not self-explaining, function maybe is more intuitive.
Tapestry just resolved the problem of the two pages communicate. As to multi-page, or a conversation, there are a lot of work. For example, how to get a page's return value?
Unlike this way that page and bean are bound together, JSF let page outside the backend bean. And a jsf page can bind multi-bean. A backend bean can be used in many jsf pages. This loose bind let a page include another page easily.
标签: Web Development
2007年6月6日星期三
RESTful Web development
What RESTful means? I found this document : RESTful Rails development is very clear to express this point. And It is also quickly to test it in Rails. Soon you will find the amazing of RESTful. It just used HTTP GET, POST, DELETE, PUT to manage the resource and some likes JDBC CRUD implement. And more it is a new RPC implement. It has been used widely in web service. So a web service can be invoked by RESTful URL. And I think it make web service more powerful. In some traditional web application, for example a struts or JSF application, RESTful just provides nice URL format.
But obviously RESTful will be more important when application need to invoke 3rd party functions
标签: Web Development
2007年5月7日星期一
Question on JSF state saving
JSF state is restored or used in "Restore View" of JSF life cycle. These state can be stored in 2 places:client and server. There are some links about the difference of them:
http://www.jroller.com/page/mert?entry=state_saving_method_client_side
http://www.jroller.com/page/cagataycivici?entry=jsf_state_saving_best_of
http://www.jroller.com/page/cenkcivici?entry=changing_default_state_management_method
These states are used to store data about the JSF component tree(the elements in f:view), including components and component id. They can be seen between 2 request. That is the difference from backend bean. At first thought most of components have no state, or just have a value which presents its state. A text field has state? But YES. Disable/Enable is a common state. In the component implement java code, saveState and restoreState methods deal all these work: choose some attributes and save them to an object which can be found as a hidden field named javax.faces.ViewState in client's browser source code. It was Base64 encoding. And of course, the view state has been configurated to be stored in the client. In Sun's webui implement, many attributes are stored in view state, such as javascript event method and style.
Some component such as Table can be very complex and has its own states such as the current page number and ordered column. If these states doesn't be stored in component tree, we have to save them in hidden input field.
Myfaces even has a component t:saveState
This technology is powerful when user's action is within one page. When page is refreshed, all he has done are saved. If he just jumps between page, navigate from one page to another page, then the state of a page is discarded, and more it is useless. In one page scenario, AJAX is also a good choice. They all improve user's experience.
Somebody provides stateless approach.
There is a cool tool called FacesTrace to monitor JSF application. It displays not only session data, but also the whole JSF life cycle dynamically.
标签: Web Development
2006年10月26日星期四
JSP,Velocity,Jelly and Ruby
项目中要动态产生文档,开始用JSP做了个简单原型,后来觉得代码比较混乱,换上了Velocity:一种模板语言。 虽然大同小异,但有些地方还是很方便。比如原来jsp中:<%=person.getPostion()%>
现在只要$person.position就可以了,少了很多讨厌的百分号。还可以定义function,以及其他一些你能想到的特性。很有点脚本语言的味 道,有如prototype.js的$(),更符合编程思路,大家都喜欢,觉得这样才自然(prototype这里大概从ruby中汲取了灵感)。
还有另外一个类是的库jellyXML-based scripting and processing engine。使用了一种XML和${}的混和语法。比如:
<j:forEach items="${IMPORTS}" var="i" trim="false">
import ${i};</j:forEach>
而velocity则较为一致:
#macro( getBox $thisboxvalue $boxvalue )
#if ( $thisboxvalue == $boxvalue ) a #else b #end
#end
单从语法上讲,jelly类似jsp + jstl。While Jelly has found some success in projects such as Maven, the general consensus is that XML is a poor choice for a programming language even the creator of Jelly apologized at http://radio.weblogs.com/0112098/2004/03/26.html#a472.
其实ANT用XML作语言也有同样的问题。TheServerSide上有篇文章Allen Holub: Just Say No to XML 说明了这一点。 那为什么jsp不做成这样子呢?连rails也是这种讨厌的风格?(还好ruby的语法很方便)个人认为一则效率的考虑:velocity大概有个预先装入、解析、预编译的过程(待考证),还会将结果放在cache中。二则(更主要)多了一种语法,造成复杂和重复。
velocity还有些设计上的亮点:使用中遇到一种情况,从bean中取出属性后要作个代码页转换然后在页面上显示。由于原来bean的getXXX方 法都已经产生好,手工改费力不讨好。这时参考velocity文档时发现有一个get()的方法:当对于属性A,bean不存在getA()方法时,调用 bean的该方法。nice! 让人想到了ruby也有类似设计:Object有个method_missing的方法.也是很好的idea,方法简单但是效果很好。(参考我的blog:Ruby的method的动态特性 )
从脚本语言看,Groovy之类从语法上更为强大,也更复杂。如果Java有成熟的、广泛接受的脚本语言技术,velocity大概也无立足之地了。
另: Roller Weblogger的模板也是用了Velocity技术。
标签: Web Development
2006年8月30日星期三
appfuse(1.9.3)中的几个小问题
1.如果创建了一个新的应用,ApplicationResources_zh_CN.properties在创建过程中被转换为乱码。简单的做法就是用appfuse原来的文件直接覆盖。
2.displaytag_zh_CN.properties没被转换。修改build.xml的copy-resources task:
<!-- Copy any resource or configuration files -->
<target name="copy-resources" depends="prepare"
description="Copy .properties and .xml files from source directory">
<copy todir="${build.dir}/web/classes" includeEmptyDirs="no">
<fileset dir="web/WEB-INF/classes">
<exclude name="ApplicationResources_zh*.properties"/>
<exclude name="displaytag_zh_CN.properties"/>
<include name="*.properties"/>
<include name="*.xml"/>
<include name="*.vm"/>
</fileset>
<filterset refid="variables.to.replace"/>
</copy>
<native2ascii src="web/WEB-INF/classes" dest="${build.dir}/web/classes"
includes="*_zh*.properties" encoding="UTF-8"/>
<generate-database-properties/>
<copy todir="${build.dir}/web/classes" file="database.properties"/>
</target>
3.appgen的ant install的做法
ant install的所做的工作包括了ant[default]的工作,好像文档写的不是很准确。而且这个appgen一股脑的将ibtias and hibernate的dao都产生出来,没有一个设置目标DAO的地方。
忘了在哪里看到的说法:j2ee开发中deploy是一个非常关键的过程,确实真知灼见。
发布过程要有几个特征:
1.方便(自动化的发布);
2.灵活(定制);
3.有升级的功能(持续的升级);
4.速度要快。这样才能减少测试-开发-测试需要的round时间。
4.中文编码的问题
刚开始遇到中文问题的时候,觉得小case:统一将编码改为gb2312,原来就是经常这么干的。后来网上查了会儿,原来大家现在都用UTF-8了,就像google一样,cool!
appfuse本身就是utf-8的配置,问题在于数据库的编码,需要在my.ini中加入:
[mysqld]
default-character-set=utf8
或者mysqld命令行带上参数。
但是ant setup-db后,依然乱码。后来发现新建表的character set为latin1,column也为latin1,god! 都改为utf8后问题解决。而如何让ant setup-db自动创建utf-8的table呢?
所以appfuse的中文问题就是所有地方都要用utf-8编码!
标签: Web Development
2006年8月16日星期三
continuation in Spring Web Flow
平心而论,SWF是现在java中对continuation支持最好的和最现实的,虽然这种支持是模拟的。其他的一些框架都有点技术上的理想而造成的不成熟。
SWF默认使用的控制是SimpleFlowExecutionRepository,这是不支持continuation的,比如浏览器回退、新开浏览器等。如果要支持,要使用ContinuationFlowExecutionRepository。SWF这样的设置是很灵活的,因为一般的应用可以使用SimpleFlowExecutionRepository来避免continuation引起的不必要的开销。
以swf-sample中的guessnumber为例(guess number是一个经典的例子),修改/web-inf/dispatcher-servlet.xml相关内容如下: <bean name="/play.htm" class="org.springframework.webflow.executor.mvc.FlowController">如此后,应用就支持浏览器后退键了。这里的后退键是跟后台逻辑关联在一起的:按下后退键,相当于刚才的猜测不算,再猜一次,而计数也“后退”(或者说“恢复”)到前面到状态。如果是购物篮应用,后退就表示“退回”刚才购买的商品。(这种方式也可能造成用户感觉上的混乱)
<property name="flowExecutor" ref="flowExecutor"/>
</bean>
<bean id="flowExecutor" class="org.springframework.webflow.executor.FlowExecutorImpl">
<constructor-arg ref="repositoryFactory"/>
</bean>
<bean id="repositoryFactory" class="org.springframework.webflow.execution.repository.continuation.ContinuationFlowExecutionRepositoryFactory">
<constructor-arg ref="flowRegistry"/>
</bean>
这种功能用一般的会话变量(比如将计数存在session中、将购物篮存在session中)是很难处理的。这里的会话变量比如计数、购物篮是一个会话活动中多个步骤的结果的记录,用一个变量是无法记录这些步骤的先后顺序的。而一般的会话变量只是一个步骤中标志或者状态的记录,一个变量就足够使用。
SWF的解决方法就是在每个步骤中添加一个标志,当这个步骤提交时,后台根据提交上来的标志恢复(在回退的情况下)当时这个步骤的上下文,这样就可以在work flow中继续运行下去。
例如当步骤1->2->3->4,当浏览器在步骤4时回退时,浏览器会把步骤2提交的数据再次提交。
用户每次提交,后台都要形成一个上下文的continuation(每次提交的数据都可能不一样),这可能会占用大量的资源。
标签: Web Development