首先,需要再次声明的是: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原型模拟看大道至简(含实例下载)的更多相关文章

  1. [转载]大道至简!!!从SAP HANA作为SAP加速器的方式,看ERP on HANA的春天

    I AM A ABAPER! 科技的进步,一定会使一些东西变得越来越精简! 大道至简!!! 文章很好!!!!!!!!!!! -------------------------------------- ...

  2. JavaScript夯实基础系列(四):原型

      在JavaScript中有六种数据类型:number.string.boolean.null.undefined以及对象,ES6加入了一种新的数据类型symbol.其中对象称为引用类型,其他数据类 ...

  3. JavaScript学习总结(四)——this、原型链、javascript面向对象

    一.this 在JavaScript中this表示:谁调用当前函数this就指向谁,不知道调用者时this指向window. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是 ...

  4. 从原型链看DOM--Comment,CDATASection,DocumentType,DocumentFragment,Attr类型

    这次总结的是剩下的这些DOM类型节点,可能你见过却不经常使用但是了解一下总是好的,可以加深对DOM体系的整体理解~.本篇要介绍的是Comment,CDATASection,DocumentType,D ...

  5. 轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)

    轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)(国家级奖项获奖作品升级版,四版累计印刷27次发行量超10万册的轻量级Jav ...

  6. 《大道至简》第一章读后感Java伪代码

    在<大道至简>第一章中,周爱民先生引用一则<愚公移山>的寓言,引出了编程的根本:顺序.选择.循环.“愚公移山”的工程虽然庞大,但是可以通过极其简单的变成来完成.我身边的有一些人 ...

  7. 《大道至简》第三章读后感+ppt课后作业

                   大道至简读后感 ——第三章团队 古人云“三人为众”,众则是指团体或团队.对于一个团队而言,重要的是凝聚力,大家能在一起把拳头握紧那么产生的力量就不紧紧是能以1+1=2 来 ...

  8. 大道至简第一章读后感Java伪代码

    //一.愚公移山 /*原始需求 惩山北直塞,出入之迁也. 项目沟通的方式 聚室而谋 项目目标 毕力平险,指通豫南,达于汉阴 人员组成 愚公,子孙荷担者三夫,邻人遗男 技术方案 叩石垦壤 簸萁运与渤海之 ...

  9. 大道至简第一章Java伪代码读后感

    import.java.大道至简.*; //周爱民 import.java.读后感*; public class shawanyia { //1. 编程的精义 while(山没有消失) {if(愚公没 ...

随机推荐

  1. 【转】ffserver用法小结

    我们可以通过ffserver以及ffmpeg做一个简单的视频监控系统,ffserver用于视频的转发调度,ffmpeg用于转码 而对于ffserver最基本也是最重要的就是对它的ffserver.co ...

  2. php5.3 appache phpstudy win7win8win10下 运行速度慢

    php5.3 appache phpstudy win7win8win10下 运行速度慢 最近在部署服务器以及本地测试的时候发现了一个奇怪的现象,运行PHP程序的时候非常慢,起先以为是网速的原因,后经 ...

  3. YYmodel 郭耀源 底层分析

    http://www.tuicool.com/articles/meAzIny         YYModel 简介与使用 http://www.jianshu.com/p/663c7b608ff5 ...

  4. Cookie知识点小结

    问题是什么?有哪些技术?如何解决? 1. Cookie 1)完成回话跟踪的一种机制:采用的是在客户端保存Http状态信息的方案 2)Cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在 ...

  5. LinqToXML~读XML文件

    linq的出现,带给我们的是简结,快速,可读性,它由linq to sql,linq to object,linq to XML组成,我的博客之前有对linq to sql的讲解,而今天,我将讲一个l ...

  6. python实现二叉树和它的七种遍历

    介绍: 树是数据结构中很重要的一种,基本的用途是用来提高查找效率,对于要反复查找的情况效果更佳,如二叉排序树.FP-树. 另外能够用来提高编码效率,如哈弗曼树. 代码: 用python实现树的构造和几 ...

  7. [Immutable.js] Transforming Immutable Data with Reduce

    Immutable.js iterables offer the reduce() method, a powerful and often misunderstood functional oper ...

  8. Git 笔记三 Git的初步使用

    Git 笔记三 Git的初步使用 在上一篇中,学习了如何配置Git环境,这一篇,开始学习Git的初步使用.Git的初步使用还是很简单的.总体上知道git init, git clone, git ad ...

  9. SQLLoader1(简单测试,以控制文件方式导入数据)

    1.创建表:SQL> conn scott/tiger@orcl;已连接. SQL> CREATE TABLE EMP2 AS SELECT * FROM EMP WHERE 1=2; 表 ...

  10. 面试前的准备---C#知识点回顾----02

    经过昨天大量的简历投递,今天陆续收到面试邀约,明日准备大战一场,是死是活一试便知 1.数据库的范式 这算入门问题了吧,但凡是个数据库类的,都得问吧, 但我们在回答的时候开始背书啦 第一范式(1NF)无 ...