zoukankan      html  css  js  c++  java
  • 【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。下篇博客见!


    源码下载


  • 相关阅读:
    05.迪米特原则 (LOD)
    04.接口隔离原则 (ISP)
    03.依赖倒置原则 (DIP)
    02.里氏替换原则 (LSP)
    01.单一职责原则 (SRP)
    Flutter点击事件的穿透,父元素点击事件覆盖了子元素点击的问题
    flutter dart语法判断 0/0==Nan 1/0==Infinity的问题
    vue项目引入三方字体
    vue echart图表打包后 图片不显示
    vue设置页面的高度100%
  • 原文地址:https://www.cnblogs.com/ainima/p/6330993.html
Copyright © 2011-2022 走看看