struts2是基于xwork实现的。xwork是一个基于命令模式的通用型框架,独立于Web环境。xwork源自webwork1,而webwork2又基于xwork实现。
xwork入门
需要加入以下包:
跟struts一样,xwork有个默认的配置文件xwork-default.xml,在xwork-core-x.x.x.jar包下:
<!DOCTYPE xwork PUBLIC
"-//Apache Struts//XWork 2.0//EN"
"http://struts.apache.org/dtds/xwork-2.0.dtd">
<xwork>
<package name="xwork-default" abstract="true">
<!-- START SNIPPET: xwork2-default-result-types -->
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
</result-types>
<!-- END SNIPPET: xwork2-default-result-types -->
<interceptors>
<!-- START SNIPPET: xwork2-default-interceptors -->
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="filterParams" class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/>
<interceptor name="removeParams" class="com.opensymphony.xwork2.interceptor.ParameterRemoverInterceptor"/>
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scopedModelDriven"
class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptor name="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="conversionError" class="com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor"/>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
<!-- END SNIPPET: xwork2-default-interceptors -->
<!--interceptor name="static-params" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="filter-params" class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/>
<interceptor name="remove-params" class="com.opensymphony.xwork2.interceptor.ParameterRemoverInterceptor"/>
<interceptor name="model-driven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scoped-model-driven"
class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/-->
<!-- START SNIPPET: xwork2-default-interceptor-stack -->
<interceptor-stack name="emptyStack"/>
<interceptor-stack name="defaultStack">
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
<!-- END SNIPPET: xwork2-default-interceptor-stack -->
</interceptors>
<default-class-ref class="com.opensymphony.xwork2.ActionSupport"/>
</package>
</xwork>
配置了结果类型和拦截器等等。
使用xwork跟使用struts一样,需要开发自己的Action,然后配置在应用程序配置文件xwork.xml中(相当于struts.xml)。配置文件放在类路径下。
下面定义了一个Action:
package org.zzj.action;
public class LoginAction {
public String login() {
return "success";
}
}
自定义Result:
package org.zzj.action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
public class MyResult implements Result {
private static final long serialVersionUID = 1L;
@Override
public void execute(ActionInvocation invocation) throws Exception {
System.out.println("MyResult...");
}
}
配置文件xwork.xml:
<!DOCTYPE xwork PUBLIC
"-//OpenSymphonyGroup//XWork1.1.1//EN"
"xwork-2.3.dtd">
<xwork>
<include file="xwork-default.xml" /><!-- 必须引入,否则无法继承xwork-default -->
<package name="default" extends="xwork-default">
<result-types>
<result-type name="myResult" class="org.zzj.action.MyResult" />
</result-types>
<action name="login" class="org.zzj.action.LoginAction" method="login">
<result name="success" type="myResult" />
</action>
</package>
</xwork>
注意这里的dtd文件路径一定要正确。我把xwork-core-x.x.x.jar包中的xwork-2.3.dtd文件放到了类路径下。
测试代码:
package org.zzj.action;
import java.util.HashMap;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationManager;
public class Test {
static ConfigurationManager cfm = new ConfigurationManager();
public static void main(String[] args) throws Exception {
Configuration configuration = cfm.getConfiguration();
ActionProxyFactory actionProxyFactory = configuration.getContainer()
.getInstance(ActionProxyFactory.class);
ActionProxy actionProxy = actionProxyFactory.createActionProxy("",
"login", "login", new HashMap<String, Object>());
System.out.println(actionProxy.execute());
}
}
输出:
MyResult...
success
Container容器
我们可以在配置文件中配置bean,xwork运行时(加载时)会将bean实例化,并且存放到container中,这样在运行时就可以拿到bean的实例。这是struts插件实现的基础。
自定义一个解码器bean:
package org.zzj.action;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.inject.Inject;
public class Decoder {
private ObjectFactory objectFactory;
public ObjectFactory getObjectFactory() {
return objectFactory;
}
@Inject
public void setObjectFactory(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
}
在配置文件的xwork元素下配置该bean:
<bean class="org.zzj.action.Decoder" scope="singleton"/>
关于bean的详细配置可在网上查资料。
测试代码:
package org.zzj.action;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.inject.Container;
public class TestContainer {
static ConfigurationManager cfm = new ConfigurationManager();
public static void main(String[] args) {
Configuration configuration = cfm.getConfiguration();
Container container = configuration.getContainer();
System.out.println(container.getInstance(ObjectFactory.class));
System.out.println(container.getInstance(Decoder.class));
container.inject(Decoder.class);
System.out.println(container.getInstance(Decoder.class)
.getObjectFactory());
}
}
输出:
com.opensymphony.xwork2.ObjectFactory@1f6f296
org.zzj.action.Decoder@1e13d52
com.opensymphony.xwork2.ObjectFactory@5329c5
调用container.inject(Bean.class)方法可以给Bean注入属性(通过注解@inject)。container就是一个IOC容器。
容器的创建是由ContainerBuilder.create()方法完成:
public Container create(boolean loadSingletons) {
ensureNotCreated();
created = true;
final ContainerImpl container = new ContainerImpl(
new HashMap<Key<?>, InternalFactory<?>>(factories));
if (loadSingletons) {
container.callInContext(new ContainerImpl.ContextualCallable<Void>() {
public Void call(InternalContext context) {
for (InternalFactory<?> factory : singletonFactories) {
factory.create(context);
}
return null;
}
});
}
container.injectStatics(staticInjections);
return container;
}