`

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

阅读更多

 

目录:

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

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

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

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

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

 

Struts的第二篇博客【SSH进阶之路】Struts基本原理 + 实现简单登录(二),我们介绍了MVC模型和Struts的基本理论,对比学习了他们之间的联系和区别。从第三篇博客【SSH进阶之路】一步步重构MVC实现Struts框架——从一个简单MVC开始(三)开始,我们实现了一个简单MVC模型,提出了三个重构的问题。

上篇博客【SSH进阶之路】一步步重构MVC实现Struts框架——封装业务逻辑和跳转路径(四),我们解决了第一个问题:封装业务逻辑和跳转路径。这篇博客我们解决第二个问题:彻底去掉Servlet中的逻辑判断。

 

我们先回顾一下上篇博客中的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.AddUserAction;
import com.liang.action.DelUserAction;
import com.liang.action.ModifyUserAction;
import com.liang.action.QueryUserAction;
/**
 * 使用servlet做相关的控制,转向多个(V)视图
 * @author liang
 *
 */
public class TestServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//取得访问的URI
		String reqeuestURI = request.getRequestURI();
		System.out.println(reqeuestURI);
		//截取URI,获得路径
		String path = reqeuestURI.substring(reqeuestURI.indexOf("/",1), reqeuestURI.indexOf("."));
		System.out.println(path);
		
		Action action = null;
		//等于添加,调用AddUserAction
		if ("/servlet/addUser".equals(path)) {
			action = new AddUserAction();
		//等于删除,调用DelUserAction
		}else if ("/servlet/delUser".equals(path)) {
			action = new DelUserAction();
		//等于修改,调用ModifyUserAction
		}else if ("/servlet/modifyUser".equals(path)) {
			action = new ModifyUserAction();
		//等于查询,调用QueryUserAction
		}else if ("/servlet/queryUser".equals(path)) {
			action = new QueryUserAction();
		}else {
			throw new RuntimeException("请求失败");
		}
		String forward = null;
		//返回不同的转向页面
		try {
			forward = action.execute(request, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//根据路径,统一完成转向
		request.getRequestDispatcher(forward).forward(request, response);
	}

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

}

 

我们来分析一下上面TestServlet中的代码,我们发现了多个逻辑判断IF..ELSE,系统不灵活,需求改变时,违背了开发封闭原则,不能满足需求。我们知道我们配置连接数据库信息时,使数据库更加灵活,使用了配置文件。

下面我们也打算把所有的字符串和业务逻辑的实现类都配置到配置文件中,最后通过实现类的方法来返回跳转路径,最终跳转到相应的页面。需求改变时,修改配置文件即可。

所以配置文件不仅要配上Servlet中出现的字符串,还要配置相应的Action接口的实现类(我们可以利用反射来动态的实例化该类的对象,进而使用多态的机制动态这个类的所有属性和方法),另外返回跳转路径字符串。其实此时和Struts的配置文件的道理是一致,我们也只需要自己实现一个配置文件。

 

web.xml,我们将struts-config.xml配置成tomacat启动时就初始化

<?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">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <!-- 配置TestServlet类 -->
  <servlet>
		<servlet-name>TestServlet</servlet-name>
		<!-- 配置成自己写的TestServlet的路径 -->
		<servlet-class>com.liang.servlet.TestServlet</servlet-class>
		<!-- tomacat启动时,初始化struts-config.xml的配置 -->
		<init-param>
			<param-name>config</param-name>
			<param-value>/WEB-INF/struts-config.xml</param-value>
		</init-param>
		<load-on-startup>0</load-on-startup>
	</servlet>

  <!-- 怎么访问与jsp的action的路径一致 -->
  <servlet-mapping>
  	<servlet-name>TestServlet</servlet-name>
  	<!-- 只要是.do请求都会到达servlet -->
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>
  
</web-app>

 

 

com.liang.servlet.TestServlet,就是我们的核心Servlet。

 

struts-config.xml,将path路径和Action的实现类,配置成map结构

 

<?xml version="1.0" encoding="UTF-8"?>

<action-config>
	<action-mappings>
		<!--根据不同的path路径,访问各自的Action  -->
		<action path="/servlet/delUser" type="com.liang.action.DelUserAction"></action>
		<action path="/servlet/addUser" type="com.liang.action.AddUserAction"></action>
		<action path="/servlet/modifyUser" type="com.liang.action.ModifyUserAction"></action>
		<action path="/servlet/queryUser" type="com.liang.action.QueryUserAction"></action>
	</action-mappings>
</action-config>

 

 

下面我们只需要读取配置文件,实现相应的功能。读取xml,非常流行的一种方式就是使用dom4j,我们曾经也实现过了dom4j读取xml的例子,但是使用dom4j读取配置文件之后,我们需要将信息放置到哪,毋庸置疑,我们需要一个map结构的类,用于存放路径信息和action实现类(type)的信息,里面最少需要两个参数,如下:

 

ActionMapping

 

package com.liang.action;

public class ActionMapping {

	//路径信息
	private String path;
	//action实现类信息
	private String type;
	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;
	}

}


配置信息,我们已经放到了一个map中,此时一个请求过来,我们需要跟上面TestServlet中的IF语句一样,根据截取的URL请求,到Map中取得本次请求对应的Action拿出来,但是Action有多个, 我们还需要一个map结构,用来区分此时的URL请求对应哪一个Action。所以此时我们还需要一个存储Action的map结构。(如果没有看懂,没事,下面的代码中有注释,可以帮助你)

 

 

Mappings

 

package com.liang.action;

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

public class Mappings {
	public static Map actions = new HashMap();  
}


此时,我们的准备工作已经做完了,我们需要使用dom4j读取配置文件,存储到相应的map结构中。

 

 

ConfigInit

struts-config.xml解析器。把解析后的结点保存到ActionMapping里,MappingAction是我们上面封装的一个类。如何解析看代码:

 

package com.liang.servlet;

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

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"));
				/*
				 * 下面Mappings.actions的存储结构相当于将配置文件struts-config.xml与映射一一对应
				 * 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。

其实它就是普通的Servlet。通过上面web.xml的映射,只要是.do的访问都会先能过这个Servlet过滤到想要访问的Action里。因为这个Servlet的load-on-startup设置为0,所以Tomcat启动时,会执行init方法。ConfigInit类就是我的struts-config.xml解析器。

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 forward = action.execute(request, response);
			
			//根据转向路径完成转向
			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);
	}

}

 

 

Action实现类的代码,我只贴一个添加用户的,其他类都没有改变,代码就不再重复了。

 

AddUserAction

 

package com.liang.action;

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

import com.liang.servlet.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();
		//调用业务逻辑
		userManager.add(username);
		//返回跳转页面
		return "/add_success.jsp";//转向路径可以通过配置文件读取
	}
}

 

现在我们发现TestServlet中所有的IF...ELSE语句都消失了,而且没有了业务逻辑的实现类,更加面向接口开发,此时我们的系统已经非常灵活了,但是我们为了更好的实现Struts框架的雏形,我们提出了第三个问题,如上面代码中显示的一样,所有的转向页面都写死了,我们需要显示和控制分离,如果想换一个视图,要修改Action实现类的代码。

 

到现在为止,我们已经实现了一个Struts框架的雏形,只是还不够完美,下篇博客,我们继续完善所有的转向页面,将显示和控制分离。下篇博客【SSH进阶之路】一步步重构MVC实现Struts框架——完善转向页面,大功告成(六)

 

源码下载

 

 

分享到:
评论

相关推荐

    SSH 框架 struts-2.3.34 spring4.3.12 hibernate5.0.12

    SSH框架,全称为Struts2、Spring和Hibernate的组合,是Java Web开发中常见的三大开源框架集成。这个框架集合提供了一种高效且强大的方式来构建企业级应用,它整合了模型-视图-控制器(MVC)设计模式、依赖注入(DI)...

    ssh实现的校园招聘网站,是学习ssh的入门资料,概括了大部分的ssh框架

    这个“ssh实现的校园招聘网站”项目,是一个理想的学习资源,旨在帮助初学者理解SSH框架的集成与实际应用。 Spring框架作为核心的IoC(Inversion of Control)和AOP(Aspect-Oriented Programming)容器,负责管理...

    SSH框架工作原理.doc

    SSH框架,全称为Spring、Struts和Hibernate,是Java企业级开发中常用的一种开源框架组合。这个框架集合提供了模型-视图-控制器(MVC)的架构模式,用于构建高效、可扩展且易于维护的Web应用程序。以下是SSH框架各...

    精讲SSH框架工作原理

    - **Web层**:采用Struts框架实现MVC模式中的控制器部分,负责接收请求并调度到相应的业务逻辑层处理。 - **Service层**:实现业务逻辑,通常包括数据验证、业务流程控制等功能。 - **DAO层**:数据访问对象层,...

    稍微用SSH重构当当网

    【标题】"稍微用SSH重构当当网"指的是利用SSH(Spring、Struts、Hibernate)这一经典的Java Web开发框架组合来重新设计和实现当当网的某些功能或系统架构。SSH是一个流行的企业级Web应用程序开发框架,它由Spring...

    Struts-Spring-Hibernate框架整合方案

    Struts是一个基于MVC(模型-视图-控制器)设计模式的Java EE框架,主要处理用户请求并调用业务逻辑,然后返回响应给客户端。在整合其他框架时,Struts通常负责前端视图和控制逻辑的协调。 接下来是Spring框架。...

    ssh2+mysql论坛完整代码和数据库文件

    SSH2+MySQL论坛完整代码和数据库文件是一套基于SSH2(Spring、Struts2、Hibernate)框架和MySQL数据库实现的论坛系统。这个资源对于学习Java Web开发,特别是SSH2框架的实战应用非常有价值。SSH2是Java开发中常见的...

    ssh框架开发博客eclipse版

    SSH框架是Java Web开发中常用的三大框架整合,包括Spring、Struts和Hibernate。Spring作为核心容器,负责管理对象和依赖注入;Struts处理MVC模式中的Controller层,负责请求分发;Hibernate则作为持久化层,用于...

    ssh例子带数据库

    SSH框架是Java开发中常用的三大框架整合,包括Struts2、Hibernate和Spring。这个压缩包文件包含了一个已经配置好的SSH框架实例,以及一个数据库脚本和测试文件,非常适合初学者学习和快速上手。 首先,Struts2是MVC...

    idea14+maven+struts+spring+mybatis框架

    标题 "idea14+maven+struts+spring+mybatis框架" 描述的是一个使用IntelliJ IDEA 14集成开发环境,结合Maven构建工具,以及SSH(Struts、Spring、Hibernate)经典企业级开发框架,并融入MyBatis持久层框架的项目。...

    struts2+hibernate+spring三大框架技术

    - **Struts2**:在Struts1的基础上进行了重构,整合了WebWork框架的一些特性。 - **WebWork**:早期的Web框架之一,以其强大的拦截器机制著称。 **为什么要使用Struts2框架** - **易于开发**:Struts2提供了丰富的...

    ssh框架解析

    SSH框架是Java开发中非常经典的一种框架组合,它由Spring、Struts和Hibernate三个框架组成,分别对应业务层、表现层和持久层,提供了一种高效的Java Web应用开发模式。下面我们详细解析SSH框架中的关键知识点。 ###...

    ssh实现实验室设备管理系统

    这个“SSH 实现实验室设备管理系统”项目利用了 SSH 框架的强大功能,构建了一个高效、稳定且功能丰富的系统。以下是关于这个系统及其相关技术的详细说明: **1. Spring 框架** Spring 是一个全面的Java应用框架,...

    基于SSH框架的java CRM客户关系管理系统

    1. Struts2:Struts2作为MVC(Model-View-Controller)设计模式的实现,是Java Web开发中的主流框架之一。它负责处理HTTP请求,提供一套灵活的控制层,使得开发者可以方便地定义请求处理逻辑,实现业务与视图的分离...

    后台框架SSH

    后台框架SSH,全称为Struts2 + Spring + Hibernate,是Java Web开发中广泛采用的一种集成框架,用于构建高效、可扩展的企业级应用。这个框架集合了三个强大的开源组件,分别负责MVC(Model-View-Controller)架构...

    基于Java的商城项目后台(ssh)

    SSH(Spring、Struts、Hibernate)是一个经典的Java Web开发框架,常用于构建企业级应用,如本案例中的商城项目后台。这个项目使用了SSH三大框架的集成,提供了高效、灵活的开发环境。 1. **Spring框架**:作为核心...

    ssh用户管理系统源码

    综上所述,SSH用户管理系统源码是一个典型的企业级Java Web项目,通过Struts2处理用户界面交互,Spring管理对象和业务逻辑,Hibernate实现数据持久化,MyEclipse和Tomcat则提供了开发和运行环境。了解并掌握这些技术...

    java ssh crm项目

    总结,Java SSH CRM项目是一个全面的、基于Java技术的客户关系管理系统,它充分利用Spring、Struts和Hibernate框架的优势,为企业的客户关系管理提供了强大而灵活的解决方案。通过理解并掌握这个项目,开发者可以...

    编程语言JAVASSH框架简介.pdf

    JAVA SSH 框架,全称为Struts + Spring + Hibernate,是Java开发中常见的企业级应用框架组合。这个框架集合了三个独立的组件,分别针对应用程序的不同层面,以实现高效、解耦和可维护的软件架构。 Struts是MVC...

Global site tag (gtag.js) - Google Analytics