嘗試模擬實現struts2(一)
阿新 • • 發佈:2018-12-23
由於在另一篇文章中已經分析過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);
}