`

【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。下篇博客见!


源码下载

 

分享到:
评论

相关推荐

    Spring框架的简单实现

    我们从一个简单的容器开始,一步步的重构,最后实现一个基本的Spring框架的雏形,为了帮助我们更加深入的理解Spring的IoC...【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)

    SpringIoC的简单实现

    【SSH进阶之路】一步步重构容器实现Spring的IoC——从一个简单的容器开始(八) 【SSH进阶之路】一步步重构容器实现Spring的IoC——解决容器对组件的“侵入式”管理的两种方案--服务定位器和IoC容器(九) 【SSH进阶之路...

    SSH框架与MVC架构之间的关系

    SSH框架,全称为Struts2、Hibernate和Spring的组合,是一种常见的Java Web开发框架,用于构建高效、可扩展的企业级应用程序。MVC(Model-View-Controller)架构模式则是SSH框架设计的基础,它将应用程序分为三个主要...

    ssh框架用struts2 hibernate实现图片的上传源码

    SSH框架,全称为Struts2、Spring和Hibernate的组合,是Java Web开发中常见的MVC架构。本项目涉及的核心知识点是使用Struts2处理表单提交,Hibernate进行数据持久化,以及图片上传的相关技术。下面将详细介绍这些内容...

    1003————自动搭建SSH框架 1004————SSH框架手动搭建

    SSH是Spring、Struts和Hibernate三个开源框架的首字母缩写,它们分别负责应用的依赖注入、MVC模式实现以及对象关系映射。这里我们将深入探讨SSH框架的自动搭建与手动搭建。 首先,让我们了解SSH框架的核心组件: 1...

    struts spring hibernate ssh 三大框架集成详细步骤 手把手教你搭框架

    SSH(Struts + Spring + Hibernate)框架集成旨在实现MVC(Model-View-Controller)设计模式,为业务逻辑、数据访问以及用户交互提供了高效的解决方案。 **Struts框架**: Struts是一个开源的MVC框架,负责处理用户...

    SSH框架——注册登录

    SSH框架,全称为Struts2、Spring和Hibernate的组合,是Java Web开发中常见的三大开源框架集成。这个小例子主要展示了如何使用SSH框架实现一个基本的注册登录功能,非常适合初学者进行学习和实践。 首先,Struts2是...

    JSPssh物流便利店管理系统采用STRUTS框架、HIBERNATE框架ssh框架 MVC模式

    JSPssh物流便利店管理系统 是一套完善的WEB设计系统,对理解JSP java 编程开发语言有帮助,系统采用ssh框架 MVC模式进行开发,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。本系统运用MVC设计模式,采用...

    javaSSH框架——学生学籍管理系统.pdf

    在"javaSSH框架——学生学籍管理系统"中,我们可以看到一个典型的SSH框架应用,主要用于实现学生学籍的管理。 一、设计目的 该设计旨在让学生通过实际操作加深对J2EE框架技术的理解,特别是在Struts2、Spring和...

    SSH(springmvc)环境

    Struts2提供了一种基于MVC模式的解决方案,它的配置文件通常为`struts.xml`,在这里定义了Action、结果类型、拦截器等元素,实现请求到Action的映射,并控制视图的跳转。 Hibernate是SSH中的持久层框架,它简化了...

    SSH框架搭建——登录、注册实例

    SSH框架是Struts、Spring和Hibernate三个开源框架的组合,分别用于MVC模式的实现、依赖注入和持久层操作,使得开发者能够快速高效地开发企业级应用。 首先,需要强调的是数据库表名的选择问题。在SQL Server 2000中...

    SSH框架搭建——测试

    SSH框架,全称为Struts2 + Spring + Hibernate,是Java Web开发中常用的一种技术栈,它结合了三个强大的开源框架,用于构建高效、灵活且可扩展的企业级应用程序。本教程将带你逐步了解如何搭建SSH框架,并实现登录和...

    JavaWeb初级实例日志管理系统MVC,Struts,SSH

    JavaWeb初级实例中的日志管理系统是一个基于MVC(Model-View-Controller)设计模式的Web应用,它结合了Struts和SSH(Spring、Struts、Hibernate)两大主流框架,为开发者提供了一个简单但完整的日志记录和管理平台。...

    SSH框架整合包/SSH框架jar包集合/Spring/Struts2/Hibernate

    SSH框架是Java开发中常用的三大开源框架——Spring、Struts2和Hibernate的组合,它们各自在应用程序的不同层次上提供服务,以实现一个高效且灵活的开发环境。下面将详细介绍这三个框架以及它们的整合。 **Spring...

    SSH框架概述——适用得很!

    SSH框架,全称为Struts+Hibernate+Spring,是Java Web开发中的一个流行组合,用于构建高效、可扩展的多层Web应用程序。这三个组件分别负责不同的职责,共同构成了强大的MVC(Model-View-Controller)架构。 Struts...

    ssh框架练习页面框架

    这个“ssh框架练习页面框架”项目,显然是一个针对SSH框架的实践练习,重点在于使用JSP进行前端页面设计,实现客户信息管理系统的增删改查功能。 Struts2是MVC(Model-View-Controller)架构的一部分,主要负责处理...

    MVC框架的实现原理,

    在本篇中,我们将重点探讨MVC框架的实现原理,并结合SSH(Struts、Spring、Hibernate)框架进行讲解。 在MVC模式中,`Model`代表模型层,负责处理业务逻辑和数据操作。`View`是视图层,主要用于展示数据,而`...

    (进阶)SSH框架实现员工部门管理系统

    这个项目“(进阶)SSH框架实现员工部门管理系统”旨在利用SSH的优势,构建一个能够管理员工及其所在部门的高效应用。下面将详细阐述SSH框架的核心组件以及在系统中的应用。 1. **Struts2**:Struts2作为MVC(模型-...

    ssh框架整合详细步骤(spring+struts2+hibernate)

    ### SSH框架整合详细步骤(spring+struts2+hibernate) #### 一、整合概述 在现代Web应用开发中,SSH(Struts2、Spring、Hibernate)框架因其各自独特的功能和优势,常被组合使用以构建高效、稳定且易于维护的系统...

Global site tag (gtag.js) - Google Analytics