`
z276356445t
  • 浏览: 151230 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

利用java反射模拟struts2工作(二)

阅读更多
上一篇文章模拟struts2的工作机制,上一篇主要是对配置文件的编写以及解析,接着是使用servlet来控制对action的访问以及result返回的处理。由servlet来充当Control层,首先来看一下web.xml的配置。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<servlet>
		<servlet-name>baseServlet</servlet-name>
		<servlet-class>blog.base.servlet.BaseServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>baseServlet</servlet-name>
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>
	<login-config>
		<auth-method>BASIC</auth-method>
	</login-config>
</web-app>


再来看一下对url请求处理。
/**
 * 
 */
package blog.base.servlet;

/**
 * @author 张廷 2011-4-19下午04:54:41
 * 
 */
public class UrlParameter {
	private String reqURI;
	private String action;
	private String method;

	public UrlParameter(String _reqURI) {
		reqURI = _reqURI;
		urlHandler();
	}

	public void urlHandler() {
		// 取得请求的action
		String reqAction = reqURI.substring(reqURI.lastIndexOf('/') + 1, reqURI.length());
		// 如果有指定访问的方法这样处理
		if (reqAction.indexOf('!') >= 0) {
			action = reqAction.substring(0, reqAction.indexOf('!'));
			method = reqAction.substring(reqAction.indexOf('!') + 1, reqAction.indexOf(".action"));
		} else {
			action = reqAction.substring(0, reqAction.indexOf(".action"));
			method = "";
		}
	}

	public String getAction() {
		return action;
	}

	public String getMethod() {
		return method;
	}
}

UrlParameter.java 主要是将url请求中需要访问的action、method做了一个简单处理,再通过处理后的action、method来定位相应的Model层。
接下来是BaseConfig.java完成了什么工作。
/**
 * 
 */
package blog.base.servlet;

import java.util.Map;

import org.apache.log4j.Logger;

import blog.base.util.WebWorkXmlParser;
import blog.base.webwork.config.WebworkXmlConfig;

/**
 * @author 张廷 2011-4-18下午09:16:05
 * 
 */
public class BaseConfig {

	private Logger logger = Logger.getLogger(this.getClass());


	/**
	 * 装载webwork.xml配置文件
	 * 
	 * @param path
	 * @return
	 */
	public Map<String, WebworkXmlConfig> loadWebworkXmlConfig(String configLocation) {
		Map<String, WebworkXmlConfig> map = null;
		try {
			map = WebWorkXmlParser.readActions(configLocation);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 获取访问的方法
	 * 
	 * @param urlParameter
	 * @param webworkXmlConfig
	 * @return
	 */
	public String getMethod(UrlParameter urlParameter, WebworkXmlConfig webworkXmlConfig) {
		if ("".equals(urlParameter.getMethod()))
			return webworkXmlConfig.getActionConfig().getMethod();
		else
			return urlParameter.getMethod();
	}
}

此类主要是处理webwork.xml文件的装载,以及取得被访问的真实方法名。接下来看一下servlet如何来控制action的访问以及View层的访问。
/**
 * 
 */
package blog.base.servlet;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import blog.base.state.result.ResultManager;
import blog.base.webwork.config.WebworkXmlConfig;

/**
 * @author 张廷 2011-5-26下午02:45:10
 * 
 */
public class BaseServlet extends HttpServlet {

	private static final long serialVersionUID = -7616647500213995842L;

	private Logger logger = Logger.getLogger(this.getClass());

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		execute(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		execute(req, resp);
	}

	private synchronized void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 设置HTTP响应与请求编码方式
		setEncoding(req, resp);
		BaseConfig baseConfig = new BaseConfig();
		// 装载webwork.xml文件
		Map<String, WebworkXmlConfig> config = baseConfig.loadWebworkXmlConfig("webwork.xml");
		// 获取用户访问的URI
		UrlParameter urlParameter = new UrlParameter(req.getRequestURI());
		// 取出需要访问的action相关配置信息
		WebworkXmlConfig webworkXmlConfig = config.get(urlParameter.getAction());
		logger.info(" visited action is " + urlParameter.getAction());
		Object handler = webworkXmlConfig.getActionConfig().getActionClass();
		Method method = null;
		try {
			method = handler.getClass().getMethod(baseConfig.getMethod(urlParameter, webworkXmlConfig), new Class[] { HttpServletRequest.class, HttpServletResponse.class });
			String result = (String) method.invoke(handler, new Object[] { req, resp });
			ResultManager rm = new ResultManager();
			rm.doWork(req, resp, webworkXmlConfig, result);
		} catch (Exception e) {
			logger.error("not fount method " + baseConfig.getMethod(urlParameter, webworkXmlConfig), e);
			e.printStackTrace();
		}
	}

	/**
	 * 设置HTTP响应与请求编码方式
	 * 
	 * @param req
	 * @param resp
	 */
	private void setEncoding(HttpServletRequest req, HttpServletResponse resp) {
		try {
			req.setCharacterEncoding("utf-8");
			resp.setCharacterEncoding("utf-8");
		} catch (UnsupportedEncodingException e) {
			logger.warn(e.getMessage(), e);
			e.printStackTrace();
		}
	}

}

不管客户端是以get或post类型请求都将交给execute来处理,然而execute加了synchronized 关键字,主要是为了线程安全,为什么要在execute方法中每次都装载一次webwork.xml文件呢,这样设计的目的主要是为了有时需要改变webwork.xml中的逻辑时不需要再去重启服务器这样的麻烦事儿。
看一下方法执行后的结果交给了ResultManager类来处理,在返回值的处理使用了设计模式中的状态模式来处理,由于富应用的兴起,不能只是简单的视图跳转,所以可以通过状态模式来扩展自己想以各种各样的类型来返回数据给客户端,在这我只写了两个类型处理,分别是Jsp与Json状态类型。先来看一下两个状态的顶层接口。
package blog.base.state.result;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import blog.base.webwork.config.ResultConfig;

/**
 * 
 * @author 张廷 2011-5-27下午07:55:13
 * 
 */
public interface ResultState {

	public Logger logger = Logger.getLogger(ResultState.class);

	/**
	 * 结果类型处理
	 * 
	 * @param req
	 * @param resp
	 * @param actionClass
	 * @param rc
	 */
	public void operate(HttpServletRequest req, HttpServletResponse resp, Object actionClass, ResultConfig rc);
}

下面是它的两个实现类。
/**
 * 
 */
package blog.base.state.result;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import blog.base.webwork.config.ResultConfig;

/**
 * @author 张廷 2011-5-27下午07:51:15
 * 
 */
public class JspResultState implements ResultState {
	/**
	 * 返回结果集为Jsp类型的处理方式
	 */
	public void operate(HttpServletRequest req, HttpServletResponse resp, Object actionClass, ResultConfig rc) {
		try {
			req.getRequestDispatcher(rc.getToUrl()).forward(req, resp);
		} catch (Exception e) {
			logger.fatal("Can not access this page!", e);
			e.printStackTrace();
		}
	}

}

JsonResultState.java
/**
 * 
 */
package blog.base.state.result;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;
import blog.base.webwork.config.ParamConfig;
import blog.base.webwork.config.ResultConfig;

/**
 * @author 张廷 2011-5-27下午07:52:50
 * 
 */
public class JsonResultState implements ResultState {

	/**
	 * 返回结果集为Json类型的处理方式
	 */
	public void operate(HttpServletRequest req, HttpServletResponse resp, Object actionClass, ResultConfig rc) {
		resp.setContentType("application/json");
		PrintWriter writer = null;
		try {
			writer = resp.getWriter();
		} catch (IOException e) {
			e.printStackTrace();
		}
		for (ParamConfig pc : rc.getParamConfigs()) {
			if ("root".equals(pc.getParamName())) {
				JSONObject jsonObj = JSONObject.fromObject(getVaribleValue(actionClass, pc.getParamVarible()));
				writer.print(jsonObj);
			}
		}
		if (null != writer) {
			writer.flush();
			writer.close();
		}
	}

	/**
	 * 取得方法的返回值
	 * 
	 * @param actionClass
	 * @param varible
	 * @return
	 */
	private Object getVaribleValue(Object actionClass, String varible) {
		Class<? extends Object> clazz = actionClass.getClass();
		Object backResult = null;
		try {
			Method method = clazz.getMethod(getGetterMethod(varible), new Class[] {});
			backResult = method.invoke(actionClass, new Object[] {});
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("not found " + getGetterMethod(varible) + "  method", e);
		}
		return backResult;
	}

	/**
	 * 获取实例中的实例变量相应的getter方法名
	 * 
	 * @param varible
	 * @return
	 */
	private String getGetterMethod(String varible) {
		String firstWord = varible.substring(0, 1);
		firstWord = firstWord.toUpperCase();
		String methodName = "get" + firstWord + varible.substring(1, varible.length());
		return methodName;
	}

}

然后再来看一下ResultManager类如何来控制result类型的控制访问的。
/**
 * 
 */
package blog.base.state.result;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import blog.base.webwork.config.ResultConfig;
import blog.base.webwork.config.WebworkXmlConfig;

/**
 * @author 张廷 2011-5-27下午07:11:58
 * 
 */
public class ResultManager {

	private ResultState state;

	public void doWork(HttpServletRequest req, HttpServletResponse resp, WebworkXmlConfig wxc, String result) {
		String resultType = null;
		ResultConfig resultConfig = null;
		Object actionClass = wxc.getActionConfig().getActionClass();
		// 遍历当前action下的所有result
		for (ResultConfig rc : wxc.getResultConfigs()) {
			if (rc.getResultName().equals(result)) {
				resultType = rc.getResultType();
				resultConfig = rc;
				break;
			}
		}
		// 取得返回类型,采取相应的状态类来处理逻辑
		if ("".equals(resultType) || "jsp".equals(resultType))
			state = new JspResultState();
		else if ("json".equals(resultType)){
			state = new JsonResultState();
		}
		state.operate(req, resp, actionClass, resultConfig);
	}

}

当然想使用更多的返回结果处理,可以直接在这个类中进行扩展。
来测试一下,针对以Json类型的结果返回给客户端写一个AjaxAction类。
/**
 * 
 */
package test.ajax;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 
 * @author 张廷 2011-5-29下午07:51:24
 * 
 */
public class AjaxAction {

	private User user;

	public String execute(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("success!");
		return "";
	}

	public String ajaxTest(HttpServletRequest req, HttpServletResponse resp) {
		user.setAge(18);
		user.setBirth("1988-12-12");
		user.setSex("男");
		user.setUsername("admin");
		return "ajaxResponse";
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

}


测试结果表明json结果已经返回到客户端,在客户端自己需要下载json2.js来解析服务器端返回的json数据。
看……一个简单的MVC小框架就已经出来了,但是一个真正的MVC框架考虑的远不止这些,还有更多的工作需要去分析设计,这只是为了理解一下MVC模式。
3
0
分享到:
评论
2 楼 z276356445t 2011-06-12  
easyhaohao 写道
动态方法调用那不好用吗?请求进不去BaseServlet

你是指的用动态代理吗?怎么进不baseServlet?
1 楼 easyhaohao 2011-06-11  
动态方法调用那不好用吗?请求进不去BaseServlet

相关推荐

Global site tag (gtag.js) - Google Analytics