尝试模拟实现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);
	}

猜你喜欢

转载自blog.csdn.net/gary0917/article/details/84504752
今日推荐