1. 程式人生 > >嘗試模擬實現struts2(一)

嘗試模擬實現struts2(一)

由於在另一篇文章中已經分析過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);
	}