【SSH进阶之路】一步步重构MVC实现Struts框架——完善转向页面,大功告成(六)

目录:

【SSH进阶之路】Struts基本原理 + 实现简单登录(二)

【SSH进阶之路】一步步重构MVC实现Struts框架——从一个简单MVC开始(三)

【SSH进阶之路】一步步重构MVC实现Struts框架——封装业务逻辑和跳转路径(四)

【SSH进阶之路】一步步重构MVC实现Struts框架——彻底去掉逻辑判断(五)

【SSH进阶之路】一步步重构MVC实现Struts框架——完善转向页面,大功告成(六)

第四篇博客【SSH进阶之路】一步步重构MVC实现Struts框架——封装业务逻辑和跳转路径(四),我们解决了第一个问题:封装业务逻辑和跳转路径。第五篇博客【SSH进阶之路】一步步重构MVC实现Struts框架——彻底去掉Servlet中的逻辑判断(五),我们解决第二个问题:彻底去掉Servlet中的逻辑判断。这篇我们解决最后一个问题,完善转向页面,显示和控制分离。

比如添加用户逻辑,成功不仅仅可以返回成功页面,失败也可以返回失败页面,代码如下:

AddUserAction

package com.liang.action;

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

import com.liang.manager.UserManager;

public class AddUserAction implements Action {

	@Override
	public String execute(HttpServletRequest req, HttpServletResponse resp)
			throws Exception {
		//获取参数
		String username = req.getParameter("username");

		//调用业务逻辑
		UserManager userManager = new UserManager();
		try{
			//添加的业务逻辑
			userManager.add(username);
		}catch(Exception e){
			//返回添加失败的界面
			return "/add_error.jsp";//转向路径可以通过配置文件读取
		}
		//返回添加成功的界面
		return "/add_success.jsp";//转向路径可以通过配置文件读取
	}

}

从上篇博客中,我们知道,若想系统变的灵活,所有变化都配置到配置文件中,修改时,修改配置文件即可。因此,我们只需要在struts-config.xml中配置转向页面,不仅仅要有成功的转向页面,而且要有失败的转向页面。

我们修改一下struts-config.xml,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<action-config>
	<action-mappings>
	 	<!--根据不同的path路径,访问各自的Action  -->
		<action path="/servlet/addUser" type="com.liang.action.AddUserAction">
			<!-- 转向页面 -->
			<forward name="success" path="/add_success.jsp"></forward>
			<forward name="error" path="/add_error.jsp"></forward>
		</action>

		<action path="/servlet/delUser" type="com.liang.action.DelUserAction">
			<forward name="success" path="/del_success.jsp"></forward>
			<forward name="error" path="/del_error.jsp"></forward>
		</action>

		<action path="/servlet/modifyUser" type="com.liang.action.ModifyUserAction">
			<forward name="success" path="/modify_success.jsp"></forward>
			<forward name="error" path="/modify_error.jsp"></forward>
		</action>

		<action path="/servlet/queryUser" type="com.liang.action.QueryUserAction">
			<forward name="success" path="/query_success.jsp">/</forward>
			<forward name="error" path="/query_error.jsp"></forward>
		</action>
	</action-mappings>
</action-config>

我们修改了配置文件,使用dom4j读取配置,配置信息也需要放到一个map结构中,我们需要一个存储转向信息的map,因此,在ActionMapping中增加一个map。

ActionMapping

package com.liang.action;

import java.util.HashMap;
import java.util.Map;

public class ActionMapping {

	private String path;
	private String type;
	//存储转向信息的map
	Map forward = new HashMap();

	public Map getForward() {
		return forward;
	}
	public void setForward(Map forward) {
		this.forward = forward;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
}

读取配置需要发生相应的变化,但是我们有了上篇博客的例子,修改起来并不难。

ConfigInit

package com.liang.servlet;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

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

import com.liang.action.*;

public class ConfigInit {

	public static void init(String config) {
		// 创建saxReader对象
		SAXReader reader = new SAXReader();
		File f = new File(config);
		try {
			// 通过read方法读取xml文件, 转换成Document对象
			Document doc = reader.read(f);
			// 得到配置文件的根结点
			Element root = doc.getRootElement();
			Element actionmappings = (Element) root.element("action-mappings");
			// 解析action结点的所有参数
			for (Iterator j = actionmappings.elementIterator("action"); j
					.hasNext();) {
				Element am = (Element) j.next();
				ActionMapping actionMapping = new ActionMapping();

				// 设置actionMapping的path和type
				actionMapping.setPath(am.attributeValue("path"));
				actionMapping.setType(am.attributeValue("type"));

				Map forward = new HashMap();
				// 解析forward结点的所有参数
				for (Iterator k = am.elementIterator("forward"); k.hasNext();) {
					Element fo = (Element) k.next();
					forward.put((String) fo.attributeValue("name"), (String) fo
							.attributeValue("path"));
				}
				// 设置forward
				//如果是添加ActionMapping的存储如下;
				/*
				 * actionMapping{ path="/servlet/addUser";
				 * type="com.liang.action.AddUserAction"
<span style="white-space:pre">				</span> *forwardMap{
				 * <span style="white-space:pre">	</span>key="success",value="/add_success.jsp"
				 * <span style="white-space:pre">	</span>key="error",value="/add_error.jsp" }
<span style="white-space:pre">				</span> *}
				 */
				actionMapping.setForward(forward);
				/*
				 * 上面Mappings.actions的存储结构相当于将配置信息与映射一一对应
				 * map.put("/servlet/delUser", actionMapping);
				 * map.put("/servlet/addUser", actionMapping);
				 * map.put("/servlet/modifyUser", actionMapping);
				 * map.put("/servlet/queryUser", actionMapping);
				 */
				Mappings.actions.put((String) am.attributeValue("path"),
						actionMapping);

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

我们的TestServlet只需要增加一句话,如下所示:

TestServlet

package com.liang.servlet;

import java.io.IOException;

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

import com.liang.action.Action;
import com.liang.action.ActionMapping;
import com.liang.action.Mappings;

/**
 * 使用servlet做相关的控制,转向多个(V)视图
 * @author liang
 *
 */
public class TestServlet extends HttpServlet {

	//需要读取的文件名
	protected static String config = "/WEB-INF/struts-config.xml";

	public void init() throws ServletException {
		//获得文件的路径
		//initialize();
		//根据web.xml中映射的目录获得文件在对应服务器中的真实路径
		config = getServletContext().getRealPath("/")+ getInitParameter("config");
		//解析struts-config.xml配置文件
		ConfigInit.init(config);
	}

	//根据web.xml中映射的目录获得文件在对应服务器中的真实路径
//	private void initialize() {
//		try {
//			config = getServletContext().getRealPath("/")
//					+ getInitParameter("config");
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//	}
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		//取得访问的URI
		String reqeuestURI = request.getRequestURI();
		//截取URI,获得路径
		String path = reqeuestURI.substring(reqeuestURI.indexOf("/",1), reqeuestURI.indexOf("."));

		Mappings mapings = new Mappings();
		// 根据截取的URL请求,到Map中取得本次请求对应的Action类
		ActionMapping actionMapping = (ActionMapping)mapings.actions.get(path);
		//取得本请求对应的Action类的完整路径
		String type = actionMapping.getType(); //com.liang.action.DelUserAction
		//采用反射,动态实例化Action
		try {
			Action action = (Action)Class.forName(type).newInstance();
			// 采用多态的机制,动态调用Action中的execute方法,返回转向路径
			String result = action.execute(request, response);

			//获得真实转向页面
			String forward =(String)actionMapping.getForward().get(result);

			//根据转向路径完成转向
			request.getRequestDispatcher(forward).forward(request, response);
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request,response);
	}

}

最后,我们看一下AddUserAction已经变得非常灵活了。

package com.liang.action;

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

import com.liang.manager.UserManager;

public class AddUserAction implements Action {

	@Override
	public String execute(HttpServletRequest req, HttpServletResponse resp)
			throws Exception {
		//获取参数
		String username = req.getParameter("username");

		//调用业务逻辑
		UserManager userManager = new UserManager();
		try{
			//添加的业务逻辑
			userManager.add(username);
		}catch(Exception e){
			//返回添加失败的界面
			return "error";//和配置文件的配置一致
		}
		//返回添加成功的界面
		return "success";//和配置文件的配置一致

	}

}

大功告成,如果我们想换一个视图显示,我们只需要修改一个配置文件即可。我们用一张类图回顾一下我们重构和封装的历程。

到此刻为止,我们重构MVC实现Struts框架的所有步骤都做完了。不难发现,其实框架并不难,只是咋一看特别神秘,当我们一步步重构,不断封装,不断完善,Struts的雏形已经展现在我们的面前了。框架就是封装的高度化,抽象的高度化。

当然,它既然是一个雏形就绝对还有不完美的地方,比如,我们没有像Struts一样封装ActionForm,自动完成数据类型的转化,当然我们也可以从现在的基础上进一步完善,但是我们就不再往下做了,我们了解它的基本思想就好,况且我们后面还有更加艰巨的任务。

经过几篇博客的重构,我们实现了一个Struts的雏形,它可以让我们认识mvc和struts的异同点,以及struts的封装过程,对我们更加深入struts埋下了伏笔。下篇博客【SSH进阶之路】Struts详细实现流程,深入Struts(七),通过学习Struts的流程,进一步深入Struts。下篇博客见!

时间: 2024-07-30 13:35:48

【SSH进阶之路】一步步重构MVC实现Struts框架——完善转向页面,大功告成(六)的相关文章

【SSH进阶之路】一步步重构MVC实现Struts框架——彻底去掉逻辑判断(五)

目录: [SSH进阶之路]Struts基本原理 + 实现简单登录(二) [SSH进阶之路]一步步重构MVC实现Struts框架--从一个简单MVC开始(三) [SSH进阶之路]一步步重构MVC实现Struts框架--封装业务逻辑和跳转路径(四) [SSH进阶之路]一步步重构MVC实现Struts框架--彻底去掉逻辑判断(五) [SSH进阶之路]一步步重构MVC实现Struts框架--完善转向页面,大功告成(六) Struts的第二篇博客[SSH进阶之路]Struts基本原理 + 实现简单登录(二

【SSH进阶之路】一步步重构MVC实现Struts框架——从一个简单MVC开始(三)

目录: [SSH进阶之路]Struts基本原理 + 实现简单登录(二) [SSH进阶之路]一步步重构MVC实现Struts框架--从一个简单MVC开始(三) [SSH进阶之路]一步步重构MVC实现Struts框架--封装业务逻辑和跳转路径(四) [SSH进阶之路]一步步重构MVC实现Struts框架--彻底去掉逻辑判断(五) [SSH进阶之路]一步步重构MVC实现Struts框架--完善转向页面,大功告成(六) 上篇[SSH进阶之路]Struts基本原理 + 实现简单登录(二),我们介绍MVC和

【SSH进阶之路】一步步重构MVC实现Struts框架——封装业务逻辑和跳转路径(四)

目录: [SSH进阶之路]Struts基本原理 + 实现简单登录(二) [SSH进阶之路]一步步重构MVC实现Struts框架--从一个简单MVC开始(三) [SSH进阶之路]一步步重构MVC实现Struts框架--封装业务逻辑和跳转路径(四) [SSH进阶之路]一步步重构MVC实现Struts框架--彻底去掉逻辑判断(五) [SSH进阶之路]一步步重构MVC实现Struts框架--完善转向页面,大功告成(六) Struts的第二篇博客[SSH进阶之路]Struts基本原理 + 实现简单登录(二

【SSH进阶之路】深入源码,详解Struts基本实现流程

通过一步步的封装我们实现了Struts的基本雏形,我们解决了Struts怎么实现MVC的问题,我们现在仅仅有了Struts的基础,对Struts的学习才刚刚开始,这篇我们要通过对比MVC来理解Struts的执行流程,最后深入Struts的源码,一看究竟. MVC M:业务逻辑,业务数据可以重复使用,我们经常说的javabean(其实struts没有实现业务层,也无法实现) V:显示逻辑,同一份数据,对应多中显示方法,JSP代码实现 C:控制流程器,Servlet代码实现. 我们通过时序图看一下M

【SSH进阶之路】Struts基本原理 + 实现简单登录(二)

上面博文,主要简单的介绍了一下SSH的基本概念,比較宏观.作为刚開始学习的人可以有一个总体上的认识,个人觉得对学习有非常好的辅助功能,它不不过一个"瞭望塔".更是检验是否真正掌握全部内容的一个前提. Struts是基于MVC的框架,它进一步的对MVC进行了封装,它是怎么封装的,我们从先回想一下MVC再到Struts.再用Struts给大家实现一个简单登录的实例.我们開始吧. MVC 概念 MVC全名是Model View Controller,是模型(model)-视图(view)-控

【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)

目录 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器开始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入式"管理的两种方案--主动查找和控制反转(九) [SSH进阶之路]一步步重构容器实现Spring框架--配置文件+反射实现IoC容器(十) [SSH进阶之路]一步步重构容器实现Spring框架--彻底封装,实现简单灵活的Spring框架(十一) 博文[SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器

【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九)

目录 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器开始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入式"管理的两种方案--主动查找和控制反转(九) [SSH进阶之路]一步步重构容器实现Spring框架--配置文件+反射实现IoC容器(十)(未更新) [SSH进阶之路]一步步重构容器实现Spring框架--彻底封装,实现简单灵活的Spring框架(十一)(未更新) 对于IOC的原理,我们曾经写过一篇博文,[SSH进阶之路

【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)

目录 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器开始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入式"管理的两种方案--主动查找和控制反转(九) [SSH进阶之路]一步步重构容器实现Spring框架--配置文件+反射实现IoC容器(十) [SSH进阶之路]一步步重构容器实现Spring框架--彻底封装,实现简单灵活的Spring框架(十一)(未更新) 上上篇博文[SSH进阶之路]一步步重构容器实现Spring框架--

【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八)

目录 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器开始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入式"管理的两种方案--主动查找和控制反转(九)(未更新) [SSH进阶之路]一步步重构容器实现Spring框架--配置文件+反射实现IoC容器(十)(未更新) [SSH进阶之路]一步步重构容器实现Spring框架--彻底封装,实现简单灵活的Spring框架(十一)(未更新) 最近一直在和容器打交道,甚至前面的博文,我们也