|
锁定老贴子 主题:XWork2.0 入门实例代码
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
时间:2007-03-03
Xwork.xml 配置文件
<!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学习小结,希望大家多指点。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
时间: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 对象填充属性数据。 |
|
| 返回顶楼 | |







