手动编写struts2框架核心内容

手动编写struts2框架核心内容

首先我们要做的第一件事就是替换servlet实现能够使用普通Java类实现servlet的功能,而替换servlet我们首先要考虑到的是servlet的职能

那么servlet能做些什么?

在之前的博客中我提到了Servlet 是运行在 Web 服务器中的小型 Java 程序。Servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。

所以这里暂且将servlet的职能归纳为

  1. 获取服务器整理后的请求信息
  2. 处理请求信息
  3. 根据处理的结果进行响应

那么要实现这个几个功能的话,只有Filter能够胜任了

/**
 *普通JAVA类
 */
public class UserAction {
	public String execute() {
		System.out.println("执行");
		return "success";
	}
}
/**
 *过滤器
 */
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
		throws IOException, ServletException {
	String uri = req.getRequestURI();
	uri = uri.substring(uri.lastIndexOf("/") + 1);
	if("user".equals(uri)){
		UserAction user = new UserAction();
		String result = user.execute();
		if(result.equals("success")){
			response.sendRedirect(request.getContextPath()+"/user.jsp");
		}
	}
}

这样就基本实现了servlet功能的替换,但是作为框架很多东西是不能写死的,大多要通过配置文件来灵活地执行功能
所以在这个基础上,我们结合反射技术便可以做到通过配置文件灵活地执行功能

配置文件

<root>
	<action name="user" class="wltyx.nyybw" method="execute">
		<result name="success" type=""></result>
	</action>
</root>

创建封装类用于存储从配置文件中解析出来的数据

public class ActionConfig {
	private String name;
	private String className;
	private String method;
	private Map<String, ResultConfig> map = new HashMap<>();
	
	public Map<String, ResultConfig> getMap() {
		return map;
	}
	public void setMap(Map<String, ResultConfig> map) {
		this.map = map;
	}
	public String getMethod() {
		return method;
	}
	public void setMethod(String method) {
		this.method = method;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	@Override
	public String toString() {
		return "ActionConfig [name=" + name + ", className=" + className + ", method=" + method + "]";
	}
}

public class ResultConfig {
	private String name;
	private String type;
	private String url;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	@Override
	public String toString() {
		return "ResultConfig [name=" + name + ", type=" + type + ", url=" + url + "]";
	}
}

创建封装类用于存储请求和响应信息

public class ActionContext {
	private HttpServletRequest req;
	private HttpServletResponse resp;
	private static ThreadLocal<ActionContext> context = new ThreadLocal<>();

	public static ActionContext getContext() {
		return context.get();
	}
	public static void setContext(ActionContext context) {
		ActionContext.context.set(context);
	}
	public HttpServletRequest getReq() {
		return req;
	}
	public void setReq(HttpServletRequest req) {
		this.req = req;
	}
	public HttpServletResponse getResp() {
		return resp;
	}
	public void setResp(HttpServletResponse resp) {
		this.resp = resp;
	}
}

解析xml配置文件

/* 
	 * 解析xml文件中的配置
	 */
	@Override
	public void init(FilterConfig config) throws ServletException {
		try {
			//获取解析文档对象
			SAXReader reader = new SAXReader();
			Document document = reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("core.xml"));
			//获取到action标签
			@SuppressWarnings("unchecked")
			List<Element> actions = document.selectNodes("//action");
			//遍历(org.dom4j.Element)
			for (Element action : actions) {
				/**
				 * 将读取到的xml数据封装到ActionConfig中
				 */
				ActionConfig actionConfig = new ActionConfig();
				
				//获取xml数据
				String name = action.attributeValue("name");
				String className = action.attributeValue("class");
				String method = action.attributeValue("method");
				
				//判断method如果没有定义给于默认值
				if(method==null){
					method="execute";
				}
				
				//将数据封装
				actionConfig.setName(name);
				actionConfig.setClassName(className);
				actionConfig.setMethod(method);
				
				/**
				 * 解析action下的result标签
				 */
				String xpath = "//action[@name="+name+"]/result";
				//获取action下的所有result标签
				@SuppressWarnings("unchecked")
				List<Element> results = action.selectNodes(xpath);
				//遍历获取到的当前的result对象
				for (Element element : results) {
					/**
					 * 将name封装到结果对象ResultConfig中
					 */
					ResultConfig resultConfig = new ResultConfig();
					//封装result标签的name属性
					String resultName = element.attributeValue("name");
					resultConfig.setName(resultName);
					//封装result标签的type属性(如果没有值给于默认值)
					String type = element.attributeValue("type");
					if(type==null){
						type="forward";
					}
					resultConfig.setType(type);
					//封装result标签的url属性(去空格)
					resultConfig.setUrl(element.getTextTrim());
					/**
					 * 将result结果对象ResultConfig封装到action结果对象中ActionConfig
					 */
					Map<String, ResultConfig> actionMap = actionConfig.getMap();
					actionMap.put(resultName, resultConfig);
				}
				
				//将配置信息对象存储到map中(key是访问路径,value是配置对象)
				map.put(name, actionConfig);
			}
			
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}

使用反射调用方法

	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		/**
		 * 转换成带协议的请求和响应
		 */
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		/**
		 * 封装请求和响应
		 */
		ActionContext context = new ActionContext();
		context.setReq(request);
		context.setResp(response);
		ActionContext.setContext(context);
		//请求路径
		String requestURI = request.getRequestURI();//	/项目名/访问路径
		//遍历包含配置信息的map
		for (Entry<String, ActionConfig> set : map.entrySet()) {
			//获取当前的路径可承接的子级完整路径
			String url = request.getContextPath()+"/"+set.getKey(); 
			//判断请求的是否是后台路径
			if(requestURI.equals(url)){
				try {
					//获取字节码对象
					ActionConfig config = set.getValue();
					Class<?> clz = Class.forName(config.getClassName());
					//创建对象
					Object newInstance = clz.newInstance();
					//获取方法对象
					Method method = clz.getMethod(config.getMethod());
					//调用方法并获取其返回值
					Object result = method.invoke(newInstance);
					/**
					 * 判断结果是否符合
					 */
					if(config.getMap().containsKey(result)){
						/**
						 * 判断跳转方式
						 */
						//获取ResultConfig对象
						ResultConfig resultConfig = config.getMap().get(result);
						if("redirect".equals(resultConfig.getType())){
							//重定向
							response.sendRedirect(request.getContextPath()+resultConfig.getUrl());
						}else{
							//转发
							request.getRequestDispatcher(request.getContextPath()+resultConfig.getUrl()).forward(request, response);
						}
					}
					//结束
					return;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值