锁定老帖子 主题:XWork2.0 入门实例代码
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-03-03
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 2.0//EN" "http://www.opensymphony.com/xwork/xwork-2.0.dtd"> <xwork> <include file="xwork-default.xml"/> <package name="default" extends="xwork-default" namespace="/test"> <result-types> <result-type name="successResult" class="com.jamesby.xwork.helloworld.SuccessResult" /> <result-type name="failedResult" class="com.jamesby.xwork.helloworld.FailedResult" /> </result-types> <interceptors> <interceptor name="testInterceptor" class="com.jamesby.xwork.helloworld.TestInterceptor"/> </interceptors> <action name="testAction" class="com.jamesby.xwork.helloworld.TestAction"> <result name="success" type="chain"> <param name="actionName">testChainAction</param> </result> <result name="failed" type="failedResult"/> <interceptor-ref name="params"/> <!--Model Driven--> <interceptor-ref name="model-driven"/> <interceptor-ref name="defaultStack"/> <interceptor-ref name="testInterceptor"/> </action> <action name="testChainAction" class="com.jamesby.xwork.helloworld.TestChainAction"> <result name="success" type="successResult"> <param name="param">Custom Type</param> </result> <result name="failed" type="failedResult"/> <interceptor-ref name="params"/> <interceptor-ref name="model-driven"/> <interceptor-ref name="defaultStack"/> <interceptor-ref name="testInterceptor"/> </action> </package> <constant name="devMode" value="false" /> </xwork> xwork-conversion.properties 属性文件 com.jamesby.xwork.helloworld.TestType=com.jamesby.xwork.helloworld.TestConvert Action 文件和测试Chain的Action 文件 public class TestAction implements Action, ModelDriven { TestModel book = new TestModel(); int id; public String execute() throws Exception { System.out.println("\nAction is invoked............"); System.out.println("Action:Received Id is " + id); System.out.println("Action:Receive Book Title is " + book.getTitle()); // book = bookDAO.findById(id, Book.class); book.setTitle("Action Title"); if (id < 1000) return "failed"; return "success"; } public TestModel getModel() { return book; } public void setId(int id) { this.id = id; } } public class TestChainAction implements Action, ModelDriven { TestModel book = new TestModel(); int id; public String execute() throws Exception { System.out.println("\nChain Action is invoked............"); System.out.println("Chain Action:Received Id is " + id); System.out.println("Chain Action:Receive Book Title is " + book.getTitle()); // book = bookDAO.findById(id, Book.class); book.setTitle("Chain Action Title"); if (id < 2000) return "success"; return "failed"; } public TestModel getModel() { return book; } public void setId(int id) { this.id = id; } } ModelDriven 的模型代码 public class TestModel { String id; String title; public void setId(String id) { this.id = id; } public void setTitle(String title) { this.title = title; } public String getId() { return this.id; } public String getTitle() { return this.title; } } Result代码 public class SuccessResult implements Result { private TestType param; public void setParam(TestType param) { this.param = param; } public void execute(ActionInvocation invocation) { System.out.println("\nSuccessResult is invoked.............."); System.out.println("param is "+param.getValue()); System.out.println("SuccessResult:Received Title is " + invocation.getStack().findValue("title")); } } public class FailedResult implements Result { public void execute(ActionInvocation invocation) { System.out.println("\nFailedResult is invoked.............."); System.out.println("FailedResult:Received Title is " + invocation.getStack().findValue("title")); } } TypeConvert 文件代码 import java.lang.reflect.Member; import java.util.Map; import ognl.DefaultTypeConverter; public class TestConvert extends DefaultTypeConverter { public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { return new TestType("" + value); } } public class TestType { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public TestType(String value) { this.value = value; } } 自定义Interceptor 和 PreResultListener public class TestInterceptor extends AbstractInterceptor { public String intercept(ActionInvocation invocation) throws Exception { invocation.addPreResultListener(new PreResultListener() { public void beforeResult(ActionInvocation invocation, String resultCode) { System.out.println("\nPre Result Listerer is invoked........"); } }); return invocation.invoke(); } } Main应用程序代码 public class HelloWorldMain { public static void main(String[] args) throws Exception { Map paramMap = new HashMap(); /** * 1000 以下 testAction Failed Result * 1000-2000 testAction testChainAction SuccessResult * 2000 以上 testAction testChainAction Failed Result */ paramMap.put("id", "500"); paramMap.put("title", "param title"); Map context = new HashMap(); context.put(ActionContext.PARAMETERS, paramMap); ConfigurationManager cm = new ConfigurationManager(); Configuration conf = cm.getConfiguration(); Container containter = conf.getContainer(); DefaultActionProxyFactory actionProxyFactory = new DefaultActionProxyFactory(); actionProxyFactory.setContainer(containter); ActionProxy proxy = actionProxyFactory.createActionProxy("/test", "testAction", context); String result = proxy.execute(); if ("success".equals(result)) { TestAction action = (TestAction) proxy.getAction(); System.out.println("\nReturn Success................."); System.out.println("Return:Return Title is "+action.getModel().getTitle()); } if ("failed".equals(result)) { TestAction action = (TestAction) proxy.getAction(); System.out.println("\nReturn Failed................."); System.out.println("Return:Return Title is "+action.getModel().getTitle()); } } } 刚刚学习Xwork2,本来想学struts2 发现需要xwork基础,个人认为学习xwork一是理解它的拦截器机制,二是理解它的ValueStack机制,准备写个xwork2学习小结,希望大家多指点。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-03-04
你说的很有道理
|
|
返回顶楼 | |
发表时间:2007-03-04
对于Xwork怎样传递参数不是很理解,下面说说我目前的理解:
Xwork 核心本身并不负责参数的传递,只是通过ActionContext来实现数据的共享,而ActionContext则是通过ValueStack来实现数据的共享的. 那么数据如何传递给Action,Result 如何使用数据呢? Result可以通过ActionInvocation获得Action,从而调用ActionInvocation.getAction 的get方法得到数据,也可以通过ActionInvocation直接访问ValueStack取得数据. 而ValueStack的数据是通过 ParametersInterceptor 拦截器实现,拦截器只负责将数据压入ValueStack. 下面是我的问题了,在ParametersInterceptor 并没有看到对Action的set方法的调用.但是Action 确通过设置了ParametersInterceptor 拦截器后,而得到数据,为什么? 我目前唯一的猜测是XWork对Action应用了字结码增强,通过生成子类并在子类的方法中访问ValueStack得到数据. 不知对否? |
|
返回顶楼 | |
发表时间:2007-03-05
通过反射很容易做到这一点,而且IOC中用得很多.
如execute方法(不用implements Action),Spring的ware,还有如Seam的@In等 不过WebWork的原码俺没看很多,而且有段时间了,也可能有其它实现方案吧. |
|
返回顶楼 | |
发表时间:2007-03-05
shaucle 写道 通过反射很容易做到这一点,而且IOC中用得很多. 我好像没有从代码中看到反射的调用,代码只是对execute进行反射方式的调用。没有对属性的set进行反射调用,才有了上面的猜测!
如execute方法(不用implements Action),Spring的ware,还有如Seam的@In等 不过WebWork的原码俺没看很多,而且有段时间了,也可能有其它实现方案吧. |
|
返回顶楼 | |
发表时间:2007-03-05
可能吧
我记得ActionContext ActionProxy 和ActionInvocation之间的关系有点tricky, 不过思想上就是一个ThreadLocal, 然后你就可以得到里面的任何内容. 忘了其具体怎么初始化的,你可以debug跟踪进去看一下. |
|
返回顶楼 | |
发表时间:2007-03-05
不错的入门教程。。
|
|
返回顶楼 | |
发表时间:2007-03-05
debug 结果如下,没有任何新的发现
2007-03-05 18:19:29,484 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loading action configurations from: xwork.xml 2007-03-05 18:19:29,859 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loading action configurations from: xwork-default.xml 2007-03-05 18:19:29,953 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded action configuration from: xwork-default.xml 2007-03-05 18:19:29,953 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded action configuration from: xwork.xml 2007-03-05 18:19:29,953 INFO [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Parsing configuration file [xwork.xml] 2007-03-05 18:19:30,000 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded type: name:default impl:com.opensymphony.xwork2.ObjectFactory 2007-03-05 18:19:30,031 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded type:com.opensymphony.xwork2.ActionProxyFactory name:default impl:com.opensymphony.xwork2.DefaultActionProxyFactory 2007-03-05 18:19:30,046 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded type:com.opensymphony.xwork2.util.ObjectTypeDeterminer name:default impl:com.opensymphony.xwork2.util.GenericsObjectTypeDeterminer 2007-03-05 18:19:30,078 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded type:com.opensymphony.xwork2.util.ObjectTypeDeterminer name:xwork1 impl:com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer 2007-03-05 18:19:30,093 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded type:com.opensymphony.xwork2.util.XWorkConverter name:xwork1 impl:com.opensymphony.xwork2.util.XWorkConverter 2007-03-05 18:19:30,093 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded type:com.opensymphony.xwork2.util.XWorkConverter name:default impl:com.opensymphony.xwork2.util.AnnotationXWorkConverter 2007-03-05 18:19:30,500 INFO [com.opensymphony.xwork2.util.ObjectTypeDeterminerFactory] - Detected GenericsObjectTypeDeterminer, initializing it... 2007-03-05 18:19:30,500 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - processing conversion file [xwork-conversion.properties] 2007-03-05 18:19:30,515 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - com.jamesby.xwork.helloworld.TestType:com.jamesby.xwork.helloworld.TestConvert [treated as TypeConverter com.jamesby.xwork.helloworld.TestConvert@64dc11] 2007-03-05 18:19:30,515 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - processing conversion file [xwork-conversion.properties] 2007-03-05 18:19:30,515 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - com.jamesby.xwork.helloworld.TestType:com.jamesby.xwork.helloworld.TestConvert [treated as TypeConverter com.jamesby.xwork.helloworld.TestConvert@1ac1fe4] 2007-03-05 18:19:30,515 INFO [com.opensymphony.xwork2.util.XWorkConverter] - Detected AnnotationXWorkConverter, initializing it... 2007-03-05 18:19:30,656 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - processing conversion file [xwork-conversion.properties] 2007-03-05 18:19:30,656 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - com.jamesby.xwork.helloworld.TestType:com.jamesby.xwork.helloworld.TestConvert [treated as TypeConverter com.jamesby.xwork.helloworld.TestConvert@18385e3] 2007-03-05 18:19:30,656 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - processing conversion file [xwork-conversion.properties] 2007-03-05 18:19:30,656 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - com.jamesby.xwork.helloworld.TestType:com.jamesby.xwork.helloworld.TestConvert [treated as TypeConverter com.jamesby.xwork.helloworld.TestConvert@1cb25f1] 2007-03-05 18:19:30,718 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded {PackageConfig Name:xwork-default namespace: abstract:false parents:[]} 2007-03-05 18:19:30,812 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded {PackageConfig Name:default namespace:/test abstract:false parents:[{PackageConfig Name:xwork-default namespace: abstract:false parents:[]}]} 2007-03-05 18:19:30,859 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded /test/testAction in 'default' package:{ActionConfig com.jamesby.xwork.helloworld.TestAction - action - file:/D:/workspace/xwork/bin/xwork.xml:12:79} 2007-03-05 18:19:30,875 DEBUG [com.opensymphony.xwork2.config.providers.XmlConfigurationProvider] - Loaded /test/testChainAction in 'default' package:{ActionConfig com.jamesby.xwork.helloworld.TestChainAction - action - file:/D:/workspace/xwork/bin/xwork.xml:25:89} 2007-03-05 18:19:30,890 DEBUG [com.opensymphony.xwork2.DefaultActionProxy] - Creating an DefaultActionProxy for namespace /test and action name testAction 2007-03-05 18:19:31,000 DEBUG [com.opensymphony.xwork2.interceptor.ParametersInterceptor] - Setting params title => param titleid => 500 2007-03-05 18:19:31,093 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - Property: id 2007-03-05 18:19:31,093 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - Class: com.jamesby.xwork.helloworld.TestAction 2007-03-05 18:19:31,109 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - converter is null for property id. Mapping size: 0 2007-03-05 18:19:31,109 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - field-level type converter for property [id] = none found 2007-03-05 18:19:31,109 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - global-level type converter for property [id] = none found 2007-03-05 18:19:31,125 DEBUG [com.opensymphony.xwork2.util.XWorkConverter] - falling back to default type converter [com.opensymphony.xwork2.util.XWorkBasicConverter@1507fb2] 2007-03-05 18:19:31,140 ERROR [com.opensymphony.xwork2.interceptor.ParametersInterceptor] - ParametersInterceptor - [setParameters]: Unexpected Exception catched: Error setting expression 'title' with value 'param title' 2007-03-05 18:19:31,140 DEBUG [com.opensymphony.xwork2.interceptor.StaticParametersInterceptor] - Setting static parameters {} 2007-03-05 18:19:31,140 DEBUG [com.opensymphony.xwork2.interceptor.ParametersInterceptor] - Setting params title => param titleid => 500 2007-03-05 18:19:31,156 DEBUG [com.opensymphony.xwork2.DefaultActionInvocation] - Executing action method = null Action is invoked............ Action:Received Id is 500 Action:Receive Book Title is param title Action Classes is class com.jamesby.xwork.helloworld.TestAction Pre Result Listerer is invoked........ FailedResult is invoked.............. FailedResult:Received Title is Action Title Return Failed................. Return:Return Title is Action Title 而且在ParameterInterceptor看到的代码如下: protected void setParameters(Object action, ValueStack stack, final Map parameters) { ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware) ? (ParameterNameAware) action : null; Map params = null; if( ordered ) { params = new TreeMap(getOrderedComparator()); params.putAll(parameters); } else { params = new TreeMap(parameters); } for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = (Map.Entry) iterator.next(); String name = entry.getKey().toString(); boolean acceptableName = acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name)); if (acceptableName) { Object value = entry.getValue(); try { stack.setValue(name, value); } catch (RuntimeException e) { if (devMode) { String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{ e.getMessage() }); LOG.error(developerNotification); if (action instanceof ValidationAware) { ((ValidationAware) action).addActionMessage(developerNotification); } } else { LOG.error("ParametersInterceptor - [setParameters]: Unexpected Exception catched: " + e.getMessage()); } } } } } 看到设置属性的代码也就是stack.setValue(name, value),望指点. |
|
返回顶楼 | |
发表时间:2007-03-06
...
俺指的debug不是print log 而是设断点然后step看值... |
|
返回顶楼 | |
发表时间:2007-03-15
ParametersInterceptor 扩展了抽象类AroundInterceptor。并在其预处理方法
(before)中实现了数据的转换。 数据转换的过程并不复杂: ⑴ 首先由ActionContext获得Map型的参数集parameters。 ⑵ 由ActionContext获得值栈(OgnlValueStack)。 ⑶ 遍历parameters中的各项数据。 ⑷ 通过OgnlValueStack,根据数据的键值,为Model 对象填充属性数据。 |
|
返回顶楼 | |