实现MVC三层框架

发表时间:2017-05-16 15:39:41 浏览量( 22 ) 留言数( 0 )

学习目标:

1、掌握并理解自定义的三层架构


学习过程:

要实现上面这个MVC框架,我们需要新建立一个项目,在这个项目里,我们已经实现了dao层的框架,数据库自己根据jdbc.properties建立一个。项目源码下载:

一、建立中转站——核心的servlet类。现在我们建立一个包com.mvc,在这个包下面建立一个ActionServlet。

public class ActionServlet extends HttpServlet {
    // 初始化方法
    public void init() throws ServletException {
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        doGet(request, response);// 调用doget方法
    }
}

由于这个servlet将会拦截所有需要进入后台控制器(我们现在成为Action类),这里我们约定所有的Action的url访问路径的后缀名是do,当然你也可以约定其他的。所以在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">
	<display-name></display-name>
	<servlet>
		<servlet-name>ActionServlet</servlet-name>
		<servlet-class>com.mvc.ActionServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>ActionServlet</servlet-name>
		<!-- 凡是以.do后缀名才拦截 -->
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

二、设计配置文件。我们需要一个配置文件沟通url、action控制类和执行方法的文件,一般配置文件我们会使用xml进行配置,我们在src目录下建立一个actions.xml文件。文件的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<actions>
    <action url="listtypes" clz="com.action.GoodsTypesAction" method="listGoodsTypes"></action>
</actions>

三、解析xml。接下来我们需要解析这个xml并把信息保存在服务器的内容中,为了保证运行效率,这个xml只会解析一次,所以我们在核心类ActionServlet的初始化方法中解析。为了解析后能保存,我们在com.mvc包中设计一个Action类与xml对应。

public class Action {
    private String url;
    private String clz;
    private String method;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getClz() {
        return clz;
    }
    public void setClz(String clz) {
        this.clz = clz;
    }
    public String getMethod() {
        return method;
    }
    public void setMethod(String method) {
        this.method = method;
    }
}

在类ActionServlet中解析actions.xml,解析xml我们之前讲过有多种方式,这里我们使用dom4j,所以首先,我们需要先导入dom4j包。然后修改ActionServlet代码如下:

public class ActionServlet extends HttpServlet {
	Map<String, Action> actions = new HashMap<String, Action>();//记录配置文件信息
	public void init() throws ServletException {
		// 读取所有的配置信息
		SAXReader saxReader = new SAXReader();
		try {
			Document document = saxReader.read(this.getClass().getClassLoader()
					.getResourceAsStream("actions.xml"));
			Element rootElement = document.getRootElement();
			List<Element> actionElements = rootElement.elements("action");
			for (Element actionElement : actionElements) {
				Action action = new Action();
				String url = actionElement.attributeValue("url");
				String clz = actionElement.attributeValue("clz");
				String method = actionElement.attributeValue("method");

				action.setUrl(url);
				action.setClz(clz);
				action.setMethod(method);

				actions.put(url, action);

			}

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

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);// 调用doget方法
	}
}

四、反射执行action的方法。接下来我们可以使用反射的技术调用Action的方法就行了。因为所有Action都必须有request和response这个两个变量,所以这里我们就在com.mvc包下设计一个BaseAction类。代码如下:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class BaseAction {
	protected HttpServletRequest request;
	protected HttpServletResponse response;
	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}
}

同时修改ActionServlet的goGet方法,代码如下:

public void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	// 1、获得用户的url
	String url = request.getServletPath();
	url = url.substring(1, url.lastIndexOf("."));
	// 2、根据url从配置文件获得对应Action和method
	Action action = actions.get(url);
	// 3、执行Action和method
	try {
		Class clazz = Class.forName(action.getClz());
		BaseAction baseAction = (BaseAction) clazz.newInstance();

		baseAction.setRequest(request);
		baseAction.setResponse(response);

		Method method = clazz.getDeclaredMethod(action.getMethod());
		
		// 4、根据返回值跳去其他页面
		method.invoke(baseAction);
		//
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

五、完成跳转。下面我们还差跳转这一步。我们在com.mvc包中专门设计一个跳转类ActionForward。同时约定所有的Action类的所有的方法都必须要返回ActionForward类型。代码如下:

/**
 * 跳转
 */
public class ActionForward {
	//true 重定向  false 转发
	private boolean isRedirect;//
	private String path;
	public ActionForward(boolean isRedirect,String path){
		this.isRedirect=isRedirect;
		this.path=path;
	}
	public boolean getRedirect() {
		return isRedirect;
	}
	public String getPath() {
		return path;
	}
}

再次修改ActionServlet的doGet方法。

//4、根据返回值跳去其他页面
	ActionForward actionForward = (ActionForward) method
					.invoke(baseAction);
	if (actionForward.getRedirect()) {
		// 重定向
		response.sendRedirect(actionForward.getPath());
	} else {
		// 转发
		request.getRequestDispatcher(actionForward.getPath()).forward(request, response);
	}

六、建立action类。好,大功告成了,现在我们可以测试一下我们这个mvc框架了。新建一个GoodsTypesAction类,必须继承BaseAction类。然后写一个listGoodsTypes方法,这个方法返回值必须是ActionForward。GoodsTypesAction的信息应该和上面的actions.xml的文件信息相对应。代码如下:

/**
 * 控制层
 * 
 * @author Administrator
 * 
 */
public class GoodsTypesAction  extends BaseAction{
	private GoodsTypesDao goodsTypesDao=new GoodsTypesDao();
	// 遍历商品类别
	public ActionForward listGoodsTypes() {
		// 1、获得页面的输入
		String abc=request.getParameter("abc");
		System.out.println(abc);
		// 2、调用业务逻辑
		List<GoodsTypes> types=goodsTypesDao.getAllTypes();
		request.setAttribute("goodsTypeses", types);

		// 3、返回数据
		ActionForward actionForward=new ActionForward(false, "goodstypeslist.jsp");

		return actionForward;
	}
}

在index.jsp中添加一个超链接<a href="listtypes.do?abc=liu">商品的类别</a>,代码如下:

<!-- 这个url对应actions.xml的url -->
<a href="listtypes.do?abc=liu">商品的类别</a>

七、部署和测试项目。在主页上面点击这个超链接,查看后台能否打印abc的信息,同时转发到goodstypeslist.jsp页面。如果没有意外应该可以跳转成功。

attcontent/5dca7cff-0214-4440-99dc-e322535b76be.png