zoukankan      html  css  js  c++  java
  • Strurts(四)——从Struts原型模拟看大道至简(含实例下载)

    首先,需要再次声明的是:struts是web层的框架。在介绍struts的第一篇文章就已经有了论述,如果不使用struts框架同样可以进行开发,但是需要在Servlet里面写大量的“if……else……”语句,在每个条件下分别去new相应的Action,以及做相应的转向。


    在学习设计模式中设计原则的时候学到开闭原则:对扩展开放,多修改封闭。这里如果要变动(增加、删除、修改)转向页面,我们就需要在Servlet里面的“if……else”功能块儿里面进行变动。而且,这个Servlet里面拥有了太多的职责,不符合单一职责。此外,MartinFowler在《重构》中写过一个很重要的代码坏味道,叫做‘Long Method’:方法如果过长其实极有可能是有坏味道了


    在这里,我想到了设计模式中学过的“状态模式”。大家都知道,在机房收费系统中,上下机的逻辑是比较复杂的,我们需要写大量的“if……else……”语句进行判断,这里如果日后需要维护的话,将是一件非常糟糕的事情。这里,就可以用到状态模式将职责进行分解,将判断的每一种条件都看作是一种状态,进而达到类职责的分离。


    反过来看我们前面说的设计,经过上面的分析,我们知道这样存在大量“if……else……”语句,而且经常会进行增删的设计是非常糟糕的。所以,那些聪明的“懒人”们就设计了web层的开源框架Struts,是他们的不将就,给现在现在的开发人员带来了大大的便利。


    Struts框架中,将Servlet进行了封装。用户在编码的时候,无须像之前一样编写大量的Servlet,以及Servlet中冗长的“if……else……”语句,只需要在配置文件里面进行配置,就能够轻松完成转向,为开发人员带来了极大的方便。

    为了深入学习Struts框架,我们不仅要对它的作用了然于胸,更需要深入剖析它的实现原理(因为Struts框架相对简单,所以我们可以直接看它的代码,较复杂的框架千万不要一猛子扎进去)。


    配置文件action_config.xml:

     

    <?xml version="1.0" encoding="UTF-8"?>
    <action-config>
    	<action path="/servlet/delUser" type="com.lzq.servlet.DelUserAction">
    		<forward name="success">/del_success.jsp</forward>
    		<forward name="error">/del_error.jsp</forward>
    	</action>
    	
    	<action path="/servlet/addUser" type="com.lzq.servlet.AddUserAction">
    		<forward name="success">/add_success.jsp</forward>
    		<forward name="error">/add_error.jsp</forward>
    	</action>
    </action-config>

    ActionMapping,主要用于存放Action信息。

     

    package com.lzq.servlet;
    
    import java.util.Map;
    public class ActionMapping {
    	private String path;
    	private Object type;
    	private Map forwardMap;
    	
    	public String getPath() {
    		return path;
    	}
    	
    	public void setPath(String path) {
    		this.path = path;
    	}
    
    	public Object getType() {
    		return type;
    	}
    
    	public void setType(Object type) {
    		this.type = type;
    	}
    
    	public Map getForwardMap() {
    		return forwardMap;
    	}
    
    	public void setForwardMap(Map forwardMap) {
    		this.forwardMap = forwardMap;
    	}
    }
    

    读取action_config.xml配置文件,并动态实例化配置文件中的Action,并将Action、转向信息都放在ActionMapping里返回。


     

    package com.lzq.servlet;
    
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    public class XmlConfigReader {
    	private static XmlConfigReader instance=new XmlConfigReader();
    	
    	ActionMapping actionMapping=new ActionMapping();
    	private Document doc;
    	private Map actionMap=new HashMap();
    	private XmlConfigReader(){
    		try {
    			SAXReader reader=new SAXReader();
    			InputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream("action_config.xml");
    			doc=reader.read(in);
    		} catch (DocumentException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public ActionMapping getActionMapping(String path){
    		synchronized(this){
    			Object type=null;
    			/*if(action.containsKey(path)){
    				type=action.get(path);
    			}*/
    			Element eltAction = (Element)doc.selectObject("//action[@path="" + path + ""]");
    			try{
    				type=Class.forName(eltAction.attributeValue("type")).newInstance();
    			}catch(Exception e){
    				e.printStackTrace();
    			}
    			 Element eltForwards = eltAction.element("forward");
    	            for (Iterator iter = eltForwards.elementIterator(); iter.hasNext();) {
    	                Element eltForward = (Element) iter.next();
    	                actionMap.put(eltForward.attributeValue("name"),eltForward.getTextTrim()); 
    	            } 
    			actionMapping.setPath(path);
    			actionMapping.setType(type);
    			actionMapping.setForwardMap(actionMap);
    			return actionMapping;
    		}
    	}
    	public static synchronized XmlConfigReader getInstance(){
    		return instance;
    	}
    	/**
    	 * 测试读取
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		ActionMapping actionMapping=XmlConfigReader.getInstance().getActionMapping("/servlet/delUser");
    		System.out.println(actionMapping.getPath());
    		System.out.println(actionMapping.getType());
    		System.out.println(actionMapping.getForwardMap().toString());
    	}
    }
     
    

    这时的Servlet就没有了冗长的“if……else……”:

     

    package com.lzq.servlet;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class TestServlet extends HttpServlet {
    	protected void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		String requestURI=request.getRequestURI();
    		System.out.println("request="+requestURI);
    		String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
    		System.out.println("path="+path);
    
    		String forward="";
    		ActionMapping actionMapping=XmlConfigReader.getInstance().getActionMapping(path);
    		Action action=(Action)actionMapping.getType();
    		try {
    			forward=action.execute(request, response);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		request.getRequestDispatcher(forward).forward(request, response);
    	}
    }
    

    Struts框架尽管相对简单些,但是它的真正实现却比这里复杂的多。而我们这里的实现尽管很简单,但是却涵盖了框架的核心思想。对于一个初学者,经过一边笼统的学习,能够总结出它原型也是很重要的。正所谓:大道至简。


    下面提供源码下载Struts原型解析实例

  • 相关阅读:
    vsftp 虚拟用户测试
    RHEL7 MariaDB测试
    安装xenapp后,非管理员连接RDP出现桌面当前不可用的解决方法
    sqrt函数的实现
    O2O、C2C、B2B、B2C
    libsvm使用说明
    如何确定最适合数据集的机器学习算法
    知乎日报:她把全世界的学术期刊都黑了
    逻辑回归应用之Kaggle泰坦尼克之灾
    非均衡数据分布的分类问题
  • 原文地址:https://www.cnblogs.com/riskyer/p/3243854.html
Copyright © 2011-2022 走看看