Struts2框架中有很多值得学习的地方,本文讲述Aware接口的使用。
在Struts2和Spring框架中,为了在运行时获得某个对象,可以采用实现某个Aware接口的方式来获得。
例如,使用ServletRequestAware、ServletResponseAware等Aware 接口与外部环境交互。
public class ServletConfigInterceptor extends AbstractInterceptor implements StrutsStatics {
private static final long serialVersionUID = 605261777858676638L;
public String intercept(ActionInvocation invocation) throws Exception {
final Object action = invocation.getAction();
final ActionContext context = invocation.getInvocationContext();
/**
* 8个可能实现的接口,8个if,而不是if else,因为可能需要同时接收8个参数
*/
if (action instanceof ServletRequestAware) {
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
((ServletRequestAware) action).setServletRequest(request);
}
if (action instanceof ServletResponseAware) {
HttpServletResponse response = (HttpServletResponse) context.get(HTTP_RESPONSE);
((ServletResponseAware) action).setServletResponse(response);
}
//省略了很多代码
return invocation.invoke();
}
}
逐次扫描Action是否实现了某个Aware接口,然后将Action强制转化成这个Aware接口并调用其方法完成交互对象的设置。实际上,ServletConfigInterceptor 这个拦截器为我们打造了一个对Action进行扩展的范例。
这个范例的打造分为三个过程:
1.定义一个接口;
2.让Action实现接口;
3.在拦截器中将Action强制转化为接口,完成接口方法的调用逻辑。
这三个过程的代码逻辑调用蕴含了两种不同的Action扩展结果:
其一,通过Action实现的接口,向Action传递外部信息;
其二,通过Action实现的接口,完成功能扩展。这里所采用的交互方式,其主要依据实际上是面向对象概念中类与接口之间的关系。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
如果,我们将Action和拦截器换成自己代码中的定义或实现,就可以获得这种设计方法所带来的好处。
下面是模仿ServletConfigInterceptor 改编而来的例子。
package org.leiwen.struts2.aware;
public interface Application {
String getName();
}
package org.leiwen.struts2.aware;
//ApplicationAware接口
public interface ApplicationAware {
void setApplication(Application app);
}
package org.leiwen.struts2.aware;
//Session接口
public interface Session {
Object getAttribute(String name);
void setAttribute(String name, Object value);
}
package org.leiwen.struts2.aware;
//SessionAware接口
public interface SessionAware {
void setSession(Session session);
}
package org.leiwen.struts2.aware;
//MyAction实现了ApplicationAware和SessionAware两个接口
public class MyAction implements ApplicationAware, SessionAware {
private Application app;
private Session session;
@Override
public void setApplication(Application app) {
this.app = app;
}
@Override
public void setSession(Session session) {
this.session = session;
}
public String getName() {
return app + " " + session + getClass();
}
}
package org.leiwen.struts2.aware;
//action代理
public class MyActionProxy {
private Object action;
public Object getAction() {
return action;
}
public void setAction(Object action) {
this.action = action;
}
}
package org.leiwen.struts2.aware;
import org.leiwen.struts2.aware.impl.DefaultApplication;
import org.leiwen.struts2.aware.impl.DefaultSession;
public class MyInterceptor {
// 也可以在运行时注入
Application app = new DefaultApplication();
// 也可以在运行时注入
Session session = new DefaultSession();
public void intercept(MyActionProxy actionProxy) {
Object action = actionProxy.getAction();
// 如果传入的action实现了ApplicationAware接口,就向action中传入Application实例。
if (action instanceof ApplicationAware) {
((ApplicationAware) action).setApplication(app);
}
// 如果传入的action实现了SessionAware接口,就向action中传入Session实例。
if (action instanceof SessionAware) {
((SessionAware) action).setSession(session);
}
}
}
package org.leiwen.struts2.aware.impl;
import org.leiwen.struts2.aware.Application;
//Application接口的默认实现类
public class DefaultApplication implements Application {
@Override
public String getName() {
return "DefaultApplication";
}
}
package org.leiwen.struts2.aware.impl;
import java.util.HashMap;
import java.util.Map;
import org.leiwen.struts2.aware.Session;
//Session接口的默认实现类
public class DefaultSession implements Session {
private Map<String, Object> context = new HashMap<String, Object>();
@Override
public Object getAttribute(String name) {
return context.get(name);
}
@Override
public void setAttribute(String name, Object value) {
context.put(name, value);
}
}
package org.leiwen.struts2.aware;
public class AwareTest {
// 测试
public static void main(String[] args) {
//构造action和actionProxy
MyAction action = new MyAction();
MyActionProxy actionProxy = new MyActionProxy();
actionProxy.setAction(action);
//构造拦截器,调用拦截器的intercept方法
MyInterceptor interceptor = new MyInterceptor();
interceptor.intercept(actionProxy);
System.out.println("MyAction的name:" + action.getName());
}
}
一共4个接口,6个类。