精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-12-21
Struts2的出现在Web2.0纷争的年代,以Ajax为代表的富客户端(Rich Client)应用正唱着Web2.0的主角。虽然Struts2本身对Ajax的应用也提供了自己的Ajax标签,但是这种比较牵强的支持也是赶鸭子上架,不是Struts本身的特长。
这里,就Struts对JSON支持的技术特点,来构建一个Rich Client应用,UI层使用的是YUI工具包,详情参考Yahoo的YUI网站。http://developer.yahoo.com/yui/。
本文中所涉及的Web应用的大致结构图如下:
先一睹为快,该应用的实际运行界面如下:
页面功能大致是,用户加入一个New Test User和New Message,然后点击按钮Add Now,页面无刷新添加新加入的消息。
首先,建立一个Struts的Action类StrutsTestAction,代码如下: package com.tail.test.actions; import java.util.ArrayList; import java.util.List; //import org.apache.log4j.Logger; import com.opensymphony.xwork2.ActionSupport; import com.tail.test.objects.Message; public class StrutsTestAction extends BaseAction { // Our logger. // private static Logger logger = Logger.getLogger(StrutsTestAction.class); private String newUser; private String newMessage; private List<Message> messageList; public List<Message> getMessageList() { return messageList; } public void setMessageList(List<Message> messageList) { this.messageList = messageList; } public String getNewMessage() { return newMessage; } public void setNewMessage(String newMessage) { this.newMessage = newMessage; } public String getNewUser() { return newUser; } public void setNewUser(String newUser) { this.newUser = newUser; } @Override public String execute() throws Exception { return super.execute(); } public String loadMessages() { messageList = new ArrayList<Message>(); messageList.add(new Message("tail", "This is an piece of initial message.")); return result(SUCCESS); } public String addMessageToUser() { messageList.add(new Message(newUser, newMessage)); //logger.debug("Add user='" + newUser + "', message='" + newMessage + "'"); return result(SUCCESS); } }
其中,newUser和newMessage分别对应界面上的New Test User和New Message这两个输入框中的value。messageList则是下方显示的消息内容,注意messageList本身内含多个Message对象的List,Message类的定义如下: package com.tail.test.objects; public class Message { private String userName; private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Message() { } public Message(String userName, String content) { this.userName = userName; this.content = content; } }
loadMessages()方法负责初始化装载数据,比如说我们从数据库或第三方资源中取出数据来初始化现有的List,它在页面上的实现,实际上也是结合Ajax来进行的。
addMessageToUser()方法对应了界面上Add Now按钮的动作内容,他们中间的交互过程也是通过Ajax来完成的,这也是这个应用的核心所在。
注意,这里的Struts Action Bean本身的默认的excute方法也被override过来了,而方法体本身是空的,这里这样做的目的就是,可以让界面操作用户一进入此页面,界面能马上构造出来,而不用等待服务器端的数据装载和返回,在初始装载数据量较大的时候,这一点尤其重要。这一点,大家可以结合后部分讲到的YUI部分的代码来体会。
现在已经有了StrutsTestAction这个工作类,那么这里的Struts核心的配置文件struts.xml也显得更加重要。 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="test" namespace="/" extends="json-default"> <global-results> <!-- any exceptions should redirect to the exception page --> <result name="exception" type="redirect-action"> <param name="actionName">exception</param> <param name="namespace">/</param> </result> </global-results> <action name="exception" class="com.tail.test.actions.ExceptionAction"> <result>/exception.jsp</result> </action> <action name="home" class="com.tail.test.actions.StrutsTestAction"> <result>/userMessage.jsp</result> <result name="input">/userMessage.jsp</result> </action> </package> <package name="tail-json" namespace="/page" extends="test"> <global-results> <!-- Don't redirect to login for ajax requests. --> <result name="login" type="httpheader"> <param name="status">403</param> </result> <!-- Send a 503 for errors in ajax requests. --> <result name="error" type="httpheader"> <param name="status">503</param> </result> </global-results> </package> <package name="tail-home" namespace="/home" extends="tail-json"> <global-results> <result name="input" type="json"> <param name="includeProperties"> result, actionErrors.*, fieldErrors.* </param> </result> </global-results> <action name="loadMessages" method="loadMessages" class="com.tail.test.actions.StrutsTestAction"> <result type="json"> <param name="includeProperties"> result, messageList.* </param> </result> </action> <action name="addMessageToUser" method="addMessageToUser" class="com.tail.test.actions.StrutsTestAction"> <result type="json"> <param name="includeProperties"> result, messageList.* </param> </result> </action> </package> </struts>
其中定义了三个package,前两个package没有什么好讲的,如果要详细了解其配置原理,可以参考Struts2的官方文档。
大家注意到,针对StrutsTestAction事实上已经在第一个package中定义了一次,为什么在第三个tail-home包中也要定义一遍呢,看到其中的json result的定义,大家应该也就看出其中的异样了。
不错,这里的定义主要是为了利用Struts JSON的插件功能将Action中的一个或多个属性/对象转换为json对象,提供到UI层去使用。而第一个package中定义的action,仅仅是页面第一次进入时的入口。
这里的result和messageList.*则是对StrutsTestAction的result和messageList属性的对外公布,includeProperties节点是支持正则表达式的,当然还有其他的json param,详细地大家可以参考struts2-jsonplugin-0.6.jar中的定义。
这里提到一个messageList,主要是给大家谈谈Struts2的conversion的支持,看看StrutsTestAction-conversion.properties文件的内容,大家应该就明白了。 Element_messageList = com.tail.test.objects.Message
不错,这里的定义主要是为了让json对象能被解析和传输。精确一点地说,在Action->UI的时候,他事实上用处不大,或者说可以省去。但是,如果如果经历UI->Action的时候,这个conversion定义就是必须的,否则Struts Action无法理解UI传送过来的数据。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-03-25
Where is the "RICH" client?
|
|
返回顶楼 | |
发表时间:2008-03-25
Here is just a demo for RICH client.
You may take a look at my following article "http://tailsherry.iteye.com/blog/149892" |
|
返回顶楼 | |
浏览 8375 次