手撸一个自己的简易struts2框架吧!

捋清逻辑

思想

1、整个应用只有一个servlet
2、每个请求访问的是单个的Action
3、所有请求的Action类都有公共的接口,接口中有个execute()
4、解耦,通过xml进行Action配置,后续操作无需更改核心Servlet源码,只需按规定方法创建Action类并配置xml文件即可

路由请求的执行路径

在这里插入图片描述

UML类图

在这里插入图片描述

包设计

–lf.blank
----lf.blank.framework
-------bean
-----------ActionMapping.java
-----------Result.java
-----------ConfigurationManager.java
----Action.java
----MainServlet.java
–blankstruts.xml

写代码前准备

编译环境:tomcat任意版本+jdk任意版本+eclipse (本人用tomcat9+jdk11+eclipse)
准备读取xml文件的jar包
dom4j-2.1.1.jar
jaxen-full.jar
saxpath.jar

开始撸代码

Action接口

package lf.blank.framework;

import java.io.IOException;

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

/**
 * Action通用接口
 * 
 * @author blank
 */
public interface Action {
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException;
}

ActionMapping封装类

package lf.blank.framework.bean;

import java.util.Map;

/**
 * 封装Action
 * 
 * @author blank
 * @Param name Action名
 * @Param className Action类全称
 * @Param method 要执行的方法
 * @Param results 结果视图Map
 */
public class ActionMapping {
	private String name;
	private String className;
	private String method;

	private Map<String, Result> results;

	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;
	}

	public String getMethod() {
		return method;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public Map<String, Result> getResults() {
		return results;
	}

	public void setResults(Map<String, Result> results) {
		this.results = results;
	}

}

Result封装类

package lf.blank.framework.bean;

/**
 * 封装结果视图
 * 
 * @author blank
 * @Param name 视图名称
 * @Param type 视图类型
 * @param page 视图地址
 */
public class Result {
	private String name;
	private String type;
	private String page;

	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 getPage() {
		return page;
	}

	public void setPage(String page) {
		this.page = page;
	}

}

blankstruts.xml

<?xml version="1.0" encoding="UTF-8"?>
<struts>
	<package>
		<!-- 我们对action标签属性限定 
			 name、class必填 且示例如下 
			 method非必填,默认为execute-->
		<action name="login" class="lf.blank.web.LoginAction">
			<!-- result标签我们也做限定 
				name必填 
				页面路径必填 
				type非必填 默认为dispatcher 还可为redirect -->
			<result name="success">/index.jsp</result>
			<result name="error">/error.jsp</result>
			<result name="login" type="redirect">/login.jsp</result>
		</action>
	</package>
</struts>

配置文件管理类

package lf.blank.framework.bean;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

/**
 * blankstruts.xml配置文件管理者 读取配置文件
 * 
 * @author blank
 * @Param actionMappings 所有配置的Action
 */
public class ConfigurationManager {
	private Map<String, ActionMapping> actionMappings;

	public ConfigurationManager() {
		// TODO Auto-generated constructor stub
		actionMappings = new HashMap<String, ActionMapping>();
		this.init();
	}

	/**
	 * 初始化函数,读取xml文件
	 */
	private void init() {
		try {
			// 1) 获得配置文件输入流
			InputStream inputStream = ConfigurationManager.class.getResourceAsStream("/blankstruts.xml");
			// 2) 创建SAXReader对象
			SAXReader saxReader = new SAXReader();
			// 3)获得文档信息
			Document doc = saxReader.read(inputStream);
			// 4)获得action标签列表
			List<Node> actionNodes = doc.selectNodes("//action");
			// 5)遍历action标签将信息加入actionMappings
			for (Node node : actionNodes) {
				Element actionElement = (Element) node;
				// 新建一个ActionMapping对象
				ActionMapping actionMapping = new ActionMapping();
				actionMapping.setName(actionElement.attributeValue("name"));
				actionMapping.setClassName(actionElement.attributeValue("class"));
				if (actionElement.attributeValue("method") == null) {
					// 设置默认方法
					actionMapping.setMethod("execute");
				} else {
					actionMapping.setMethod(actionElement.attributeValue("method"));
				}
				// 获取action内配置的结果视图
				List<Element> resultList = actionElement.elements("result");

				Map<String, Result> results = new HashMap<String, Result>();
				for (Element resultElement : resultList) {
					// 新建结果视图对象进行封装
					Result result = new Result();
					result.setName(resultElement.attributeValue("name"));
					if (resultElement.attributeValue("type") == null) {
						// 设置默认视图类型为 转发
						result.setType("dispatcher");
					} else {
						result.setType(resultElement.attributeValue("type"));
					}

					result.setPage(resultElement.getText().trim());
					// 将result放入results中
					results.put(result.getName(), result);
				}

				actionMapping.setResults(results);

				actionMappings.put(actionMapping.getName(), actionMapping);
			}
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public Map<String, ActionMapping> getActionMappings() {
		return actionMappings;
	}

}

MainServlet

package lf.blank.framework;

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

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

import lf.blank.framework.bean.ActionMapping;
import lf.blank.framework.bean.ConfigurationManager;
import lf.blank.framework.bean.Result;

/**
 * 框架入口Servlet 对所有后缀为.action的访问进行处理
 * 
 * @author blank
 * @Param manager 配置文件管理者对象
 */
@WebServlet("*.action")
public class MainServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private ConfigurationManager manager;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public MainServlet() {
		super();
		// TODO Auto-generated constructor stub
	}

	@Override
	public void init() throws ServletException {
		// TODO Auto-generated method stub
//		super.init();
		// 实例化管理者 仅创建一次
		manager = new ConfigurationManager();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	@SuppressWarnings("deprecation")
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		try {
			// 1) 获得配置文件管理者提供的配置文件信息
			Map<String, ActionMapping> actionMappings = manager.getActionMappings();
			// 2) 获得请求uri并截取
			String uri = request.getRequestURI();
			String path = uri.substring(uri.lastIndexOf('/') + 1, uri.lastIndexOf('.'));
			// 3) 获取访问的ActionMapping对象
			if (!actionMappings.containsKey(path)) {
				throw new RuntimeException("未找到" + path + "Action");
			}
			ActionMapping actionMapping = actionMappings.get(path);
			// 4) 实例化具体的Action类
			Class<?> classObj = Class.forName(actionMapping.getClassName());
			Object actionObj = classObj.newInstance();
			// 5) 利用反射调用actionObj的方法并获得结果视图名称
			String methodName = actionMapping.getMethod();
			Method method = classObj.getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
			String resultStr = (String) method.invoke(actionObj, request, response);

			// 6) 处理结果视图
			Map<String, Result> results = actionMapping.getResults();
			if (!results.containsKey(resultStr)) {
				throw new RuntimeException("未找到" + resultStr + "视图");
			}

			Result result = results.get(resultStr);
			String type = result.getType();
			String page = result.getPage();
			if (type.equals("dispatcher")) {
				request.getRequestDispatcher(page).forward(request, response);
			} else {
				response.sendRedirect(request.getContextPath() + page);
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

ok,现在这个我们自己搞得一个小的针对MVC模式的框架即可投入使用了,让我们测试一下吧!

代码测试

在这里插入图片描述
我这里是用假数据做了一个登陆做测试,目录结构如图

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值