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原型解析实例
Strurts(四)——从Struts原型模拟看大道至简(含实例下载)的更多相关文章
- [转载]大道至简!!!从SAP HANA作为SAP加速器的方式,看ERP on HANA的春天
I AM A ABAPER! 科技的进步,一定会使一些东西变得越来越精简! 大道至简!!! 文章很好!!!!!!!!!!! -------------------------------------- ...
- JavaScript夯实基础系列(四):原型
在JavaScript中有六种数据类型:number.string.boolean.null.undefined以及对象,ES6加入了一种新的数据类型symbol.其中对象称为引用类型,其他数据类 ...
- JavaScript学习总结(四)——this、原型链、javascript面向对象
一.this 在JavaScript中this表示:谁调用当前函数this就指向谁,不知道调用者时this指向window. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是 ...
- 从原型链看DOM--Comment,CDATASection,DocumentType,DocumentFragment,Attr类型
这次总结的是剩下的这些DOM类型节点,可能你见过却不经常使用但是了解一下总是好的,可以加深对DOM体系的整体理解~.本篇要介绍的是Comment,CDATASection,DocumentType,D ...
- 轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)
轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)(国家级奖项获奖作品升级版,四版累计印刷27次发行量超10万册的轻量级Jav ...
- 《大道至简》第一章读后感Java伪代码
在<大道至简>第一章中,周爱民先生引用一则<愚公移山>的寓言,引出了编程的根本:顺序.选择.循环.“愚公移山”的工程虽然庞大,但是可以通过极其简单的变成来完成.我身边的有一些人 ...
- 《大道至简》第三章读后感+ppt课后作业
大道至简读后感 ——第三章团队 古人云“三人为众”,众则是指团体或团队.对于一个团队而言,重要的是凝聚力,大家能在一起把拳头握紧那么产生的力量就不紧紧是能以1+1=2 来 ...
- 大道至简第一章读后感Java伪代码
//一.愚公移山 /*原始需求 惩山北直塞,出入之迁也. 项目沟通的方式 聚室而谋 项目目标 毕力平险,指通豫南,达于汉阴 人员组成 愚公,子孙荷担者三夫,邻人遗男 技术方案 叩石垦壤 簸萁运与渤海之 ...
- 大道至简第一章Java伪代码读后感
import.java.大道至简.*; //周爱民 import.java.读后感*; public class shawanyia { //1. 编程的精义 while(山没有消失) {if(愚公没 ...
随机推荐
- poj2739
Sum of Consec ...
- 高精度快速幂(Java版)
import java.io.*; import java.math.*; import java.util.*; import java.text.*; public class Main { pu ...
- JAX-WS 可运行项目
该项目是通过JAX-WS实现的WebService服务,其中包括了1.关于最简单的WebService服务的创建2.关于文件交互的WebService的创建 代码中包括了服务端代码和客户端代码(客户端 ...
- JSTL解析——003——core标签库02
上一节主要讲解了<c:if/><c:choose/><c:when/><c:otherwise><c:out/>标签的使用,下面继续讲解其它 ...
- android-sdk-windows版本号下载
Android SDK 4.0.3 开发环境配置及执行 近期又装了一次最新版本号的ADK环境 眼下最新版是Android SDK 4.0.3 本文的插图和文本尽管是Android2.2的 步骤都是一样 ...
- [HeadFirst-HTMLCSS入门][第十章div,span]
新元素 <div>逻辑容器 能进行分组,等于用一个大的盒子进行包装 <span> 内联字符的逻辑分组 text-align 改变所有内联元素位置. 属性 center 居中 行 ...
- undefined和null的区别
在javascript中undefined和null几乎是没有区别的 undefined==null;//true; 区别: null是一个表示“无”的对象,转为数值为0:或者说没有对象,此处 ...
- LinearLayout使用简单实例
1.代码 import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActionB ...
- 疯狂安卓Android自学笔记
开发者必备自学工具: 谷歌搜索:www.yundou.info Android原版开发文档 (英文) Doc http://www.phoned.cn/docs/reference/android/v ...
- [Python][MachineLeaning]Python Scikit-learn学习笔记1-Datasets&Estimators
Scikit-learn官网:http://scikit-learn.org/stable/index.html Datasets 标准的数据集格式为一组多维特征向量组成的集合.数据集的标准形状(sh ...