给大伙儿preview一个有意思的东西

用了一段时间的seam,感觉seam有很多先进的思想值得发扬,但这段时间内我正一步一步地变得不喜欢JSF;因为它的组件开发很困难,还因为JSF本身许多已实现的组件——像richFaces或iceFaces——也有很多很多让人眼花缭乱的属性在使用的过程中需要学习,熟悉,感觉还是很麻烦,不如直接使用HTML和JS的知识来作view方便。
我在这里没有带任何感情色彩地针对JSF,我只是实话实说我认为的JSF的缺点;
并且,更重要的,我想让seam脱离JSF也能使用,而且因为比较着急,我从上个星期开始,就在抽时间做一件事情——Seam-Velocity;并且到现在,这个工具(我暂且叫它工具吧),已经能胜任大部分的seam-web开发工作了,虽然可能会有一些bug;seam手册自带的前几个例子是没问题的;
好了,说说这个seam-velocity到底是个什么东西吧:
它当然是一个抛弃JSF,转而使用velocity,用传统的HTML、JS来开发seam应用的东西,彻底替换seam中view的开发技术,算是个小小的表现层——控制层框架。

介绍一些大致的信息:

首先,请求处理流程:
给大伙儿preview一个有意思的东西_第1张图片

那么,front-controller的代码骨架就差不多是这样:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
            IOException {
        /*
         * if value binding exists, update values in contexts, except
         * conversationId, 'action' param and converter setting params
         */
        
        this.updateValue(req, exList);

        // if action event exists, execute the action
        if (StringUtils.isNotEmpty(req.getParameter(FORM_ACTION_PARAM))) {

            // invoke action
            String target = this.doAction(req);

            // action invoke returned non-null value
            if (StringUtils.isNotEmpty(target)) {

                // need redirect, doing redirect
                if (target.startsWith(REDIRECT_PREFIX)) {
                    resp.sendRedirect(StringUtils.substringAfter(target, REDIRECT_PREFIX));
                    return;
                    // end request
                } else {
                    /*
                     * need no redirect, merge returned page and context vars,
                     * send out conversation id, write response
                     */
                    try {
                        this.mergeContextVarsAndConversationIdAndWriteResponse(target, req, resp);
                    } catch (Exception e) {
                        log.error(e);
                    }
                    return;
                    // end request
                }
            }

            /*
             * action invoke returned empty, doing the same as
             * 'no-action-event-request'
             */
        }

        /*
         * no action event, merge requesting page and context vars, send out
         * conversation id, write response.
         */
        String requestingPageVm = this.getRequestingPageVm(req);
        try {
            this.mergeContextVarsAndConversationIdAndWriteResponse(requestingPageVm, req, resp);
        } catch (Exception e) {
            log.error("Write response failed!");
            log.error(e);
        }
        return;
        // end request
    }


也就是在一个SeamVelocityController的Servlet中描述了上图中所画出的请求处理流程。

以及我简单实现的一个小例子,跟手册里的第一个例子——registration差不多:

给大伙儿preview一个有意思的东西_第2张图片
给大伙儿preview一个有意思的东西_第3张图片


这个例子的页面写起来就是这样——完全是velocity的页面,没有JSF:
#set($entries=$pullTool.pull("entries"))
<html>
<head>
  <title>Seam Without JSF Demo</title>
  <script language="javascript">
  	function deleteEntry(id){
		document.form1.entry_id.value = id;
		form1.submit();
	}
  </script>
</head>
<body>
	#if(${cid})
		<h1>ConversationId: ${cid}</h1>
	#end
	<hr />
	Add new entry: 
	<form>
		<lable for="title">Entry Title:</lable>
		<input id="title" type="text" name="entry_title" value=""><br />
		<lable for="entryContent">Entry Content:</lable>
		<TEXTAREA id="entryContent" name = "entry_content"></TEXTAREA>
		<input type="hidden" name="action" value="entryAction_createNewEntry"><br />
		<input type="submit" value="Add">
	</form>
	#if(${entries}&&${entries.size()}!=0)
		<table border="1" cellpadding="0" cellspacing="0" width="500">
			<tr>
				<td>
					<h6>Id</h6>
				</td>
				<td>
					<h6>Title</h6>
				</td>
				<td>
					<h6>Action</h6>
				</td>
			</tr>
			<form name="form1">
    			#foreach(${e} in ${entries})
    				<tr>
    					<td>
    						${e.id}
    					</td>
    					<td>
    						${e.title}
    					</td>
    					<td>
    						<input type="hidden" name="action" value="entryAction_deleteEntry">
    						<input type="button" value="Delete" onclick="deleteEntry(${e.id})">
    					</td>
    				</tr>
				#end
				<input type="hidden" name="entry_id" value="">
			</form>
		</table>
	#else
		<h2>There are no entries.</h2>
	#end
</body>
</html>


可以从页面源码里面看到,已经支持了表单值绑定、action方法提交、pullTool工具;

这个例子很简单,以后我会用它实现更多手册里的示例;
这个小框架的目标是保留seam的所有功能,但砍掉JSF;

对于这个表现层本身,这里列一下我想要让他支持的功能:
1)数据单向绑定,提交时更新
2)表单提交时,可执行action方法
3)提供“拉(pullTool)”工具,让velocity页面里也能写EL表达式从服务端“拉”数据
4)表单提交值转换(converter),以及自定义converter
5)分模块开发,seam-velocity并不会因为失去了Facelets而失去了分页面模块开发的功能

以后可能会再增加;

目前在googleCode上的项目地址: http://code.google.com/p/seam-velocity/

svn中有一个毛坯实现,基本能用,不过可能会有一些bug;暂不提供release下载,还需成熟。

接下来这段时间要忙论文的事情,所以要等到7月初的时候我再来推这个项目;
也正好,在这段停滞时间中可以听听圈子里的意见,我相信还有人跟我有类似的想法,想用别的东西来代替JSF。

欢迎大家讨论,最好能多提点意见。

你可能感兴趣的:(SVN,JSF,velocity,Richfaces,seam)