由于在另一篇文章中已经分析过Struts2的执行流程,所以直接开始尝试。
声明:只是简单实现过程,没有使用代理。
首先:因为struts2会当用户访问action时候加入一个过滤器,将用户请求拦下来。用户请求路径"./action/StudentInfo"
所以我们也在web.xml加一个过滤器dispatcher。如下:
<filter>
<filter-name>dispatcher</filter-name>
<filter-class>com.gary.video.dispatcher.Dispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>dispatcher</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
然后:在com.gary.video.dispatcher包下创建一个Dispatcher类实现Filter接口。并在src下创建模仿struts2的xml配置文件。
<struts>
<action name="StudentInfo" class="com.gary.video.action.StudentAction"
method="" type="json">
<result name="SUCCESS" url="./teacherInfo.html"></result>
</action>
</struts>
在实现init方法中,我们创建一个工厂ActionBeanFactory,这个工厂目的是为了得到在xml中配置的相关Action的名称以及全部路径、方法、类型、返回内容等。
package com.gary.video.dispatcher;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Element;
import com.mec.util.XMLParser;
public class ActionBeanFactory {
private static final Map<String, ActionDefinition> actionMap = new HashMap<>();
static void scanActionConfig(String xmlPath) {
new XMLParser() {
@Override
public void dealElement(Element element, int index) {
String name = element.getAttribute("name");
String className = element.getAttribute("class");
String method = element.getAttribute("method");
String type = element.getAttribute("type");
try {
actionMap.put(name, new ActionDefinition()
.setKlass(className)
.setMethod(method.length() <= 0 ? null : method)
.setType(type));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}.dealElementInTag(XMLParser.getDocument(xmlPath), "action");
}
ActionDefinition getAction(String action) {
return actionMap.get(action);
}
}
package com.gary.video.dispatcher;
public class ActionDefinition {
private Class<?> klass;
private String method;
private EActionType type;
public ActionDefinition() {
}
Class<?> getKlass() {
return klass;
}
ActionDefinition setKlass(String className) throws ClassNotFoundException {
this.klass = Class.forName(className);
return this;
}
String getMethod() {
return method;
}
ActionDefinition setMethod(String method) {
this.method = method;
return this;
}
EActionType getType() {
return type;
}
ActionDefinition setType(String type) {
this.type = EActionType.valueOf(type);
return this;
}
}
接着我们在doFilter方法中完成一些内容(不完善):
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String uri = httpRequest.getRequestURI();
int actionIndex = uri.indexOf("/action/");
if (actionIndex == -1) {
chain.doFilter(request, response);
return;
}
String action = uri.substring(actionIndex + 8);
//ActionBeanFactory最好应该是取到相关action类的代理,就可以具体在执行action的方法时进行拦截器对方法的拦截。
ActionDefinition ad = new ActionBeanFactory().getAction(action);
if (ad == null) {
return;
}
String result = null;
Class<?> klass = ad.getClass();
try {
Object object = klass.newInstance();
// TODO 根据klass中的Getters,回推出ognl中的键,并完成DI
if (object instanceof IAction) {
IAction actionObj = (IAction) object;
result = actionObj.execute();
} else {
// TODO 根据method,找到返回值类型为String,且无参的某一个方法,执行之!
}
switch (ad.getType()) {
case json:
// TODO 按照ajax,进行response!返回result的json字符串!
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
chain.doFilter(request, response);
}