现在的位置: 首页 > 综合 > 正文

Strurts(四)——从Struts原型模拟看大道至简(含实例下载)

2013年06月05日 ⁄ 综合 ⁄ 共 4437字 ⁄ 字号 评论关闭

首先,需要再次声明的是: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原型解析实例

抱歉!评论已关闭.