博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《设计模式之禅》--MVC框架
阅读量:6306 次
发布时间:2019-06-22

本文共 9574 字,大约阅读时间需要 31 分钟。

需求:设计一个MVC框架

(以下可能摘要不全,后期整理)

架构图:

* 核心控制器:MVC框架入口,负责接收和反馈HTTP请求

* 过滤器:Servlet容器内的过滤器,实现对数据的过滤处理

* 拦截器:对进出模型的数据进行过滤,不依赖系统容器,只过滤MVC框架内的业务数据

* 模型管理器:提供一个模型框架,内部所有业务操作应该无状态,不关心容器对象

* 视图管理器:管理所有的视图

* 辅助工具:比如文件管理、对象管理

【核心控制器】

public class FilterDispatcher implements Filter {    //定义一个值栈辅助类    private ValueStackHelper valueStackHelper = new ValueStackHelper();    //应用IActionDispatcher    IActionDispather actionDispatcher = new ActionDispatcher();    //servlet销毁时要做的事情    public void destroy() {    }    //过滤器必须实现的方法    public void doFilter(ServletRequest request, ServletResponse response,                         FilterChain chain) throws IOException, ServletException {        //转换为HttpServletRequest        HttpServletRequest req = (HttpServletRequest) request;        HttpServletResponse res = (HttpServletResponse) response;        //传递到其他过滤器处理        chain.doFilter(req, res);        //获得从HTTP请求的ACTION名称        String actionName = getActionNameFromURI(req);        //对ViewManager的应用        ViewManager viewManager = new ViewManager(actionName);        //所有参数放入值栈        ValueStack valueStack = valueStackHelper.putIntoStack(req);        //把所有的请求传递给ActionDispatcher处理        String result = actionDispatcher.actionInvoke(actionName);        String viewPath = viewManager.getViewPath(result);        //直接转向        RequestDispatcher rd = req.getRequestDispatcher(viewPath);        rd.forward(req, res);    }    public void init(FilterConfig arg0) throws ServletException {    /*    * 1、检查XML配置文件是否正确    * 2、启动监控程序,观察配置文件是否正确    */    }    //通过url获得actionName    private String getActionNameFromURI(HttpServletRequest req) {        String path = (String) req.getRequestURI();        String actionName = path.substring(path.lastIndexOf("/") + 1,                path.lastIndexOf("."));        return actionName;    }}

核心控制器的配置

  
    
FilterDispatcher
    
FilterDispatcher
    
{包名}.FilterDispatcher
  
  
    
FilterDispatcher
    
*.do
  
/index2.jsp
/index.jsp

框架逻辑校验

public class LogicXmlValidate implements IXmlValidate {    //检查xmlPath是否符合逻辑,比如不会出现一个类中没有的方法    public boolean validate(String xmlPath) {        return false;    }}

逻辑校验流程:

1)读取XML文件

2)使用反射技术初始化一个对象(配置文件中的class属性值)

3)检查是否存在配置文件中配置的方法

4)检查方法的返回值是否是String,并且无输入参数,同时必须继承指定类或接口

策略场景类

public class Checker {    //使用哪一个策略    private IXmlValidate validate;    //xml配置文件的路径    String xmlPath;    //构造函数传递    public Checker(IXmlValidate _validate) {        this.validate = _validate;    }    public void setXmlPath(String _xmlPath) {        this.xmlPath = _xmlPath;    }    //检查    public boolean check() {        return validate.validate(xmlPath);    }}

监听接口

public interface Watchable {    //监听    public void watch();}

文件监听者

public class FileWatcher extends Observable implements Watchable {    //是否要重新加载XML文件    private boolean isReload = false;    //启动监视    public void watch() {        //启动一个线程,每隔15秒扫描一下文件,发现文件日期被修改,立刻通知观察者        super.addObserver(new Checker());        super.setChanged();        super.notifyObservers(isReload);    }}

修正后的检查者

public class Checker implements Observer {    public void update(Observable arg0, Object arg1) {        //检查是否符合条件        arg1 = check();    }}

【模型管理器】

public interface IActionDispather {    //根据Action的名字,返回处理结果    public String actionInvoke(String actionName);}
public class ActionDispather implements IActionDispather {    //需要执行的Action    private ActionManager actionManager = new ActionManager();    //拦截器链    private ArrayList
listInterceptors = InterceptorFactory.createInterceptors(); public String actionInvoke(String actionName) { //前置拦截器 return actionManager.execAction(actionName); //后置拦截器 }}
public abstract class ActionSupport {    public final static String SUCCESS = "success";    public final static String FAIL = "fail";    //默认的执行方法    public String execute() {        return SUCCESS;    }}

 

public class ActionManager {    //执行Action的指定方法    public String execAction(String actionName) {        return null;    }}
public abstract class AbstractInterceptor {    //获得当前的值栈    private ValueStack valueStack = ValueStackHelper.getValueStack();    //拦截器类型:前置、后置、环绕    private int type = 0;    //当前的值栈    protected ValueStack getValueStack() {        return valueStack;    }    //拦截处理    public final void exec() {        //根据type不同,处理方式也不同    }    //拦截器类型    protected abstract void setType(int type);    //子类实现的拦截器    protected abstract void intercept();}
public class Interceptors implements Iterable
{ //根据拦截器列表建立一个拦截器链 public Interceptors(ArrayList
list) { } //列出所有的拦截器 public Iterator
iterator() { return null; } //拦截器链的执行方法 public void intercept() { //委托拦截器执行 }}
public class InterceptorFactory {    public static ArrayList
createInterceptors() { //根据配置文件创建出所有的拦截器链 return null; }}

【视图管理器】

public class GBLangData extends AbsLangData {    @Override    public Map
getItems() { /* * Map 的结构为: * key='title', value='标题' * key='menu', value='菜单' */ return null; }}public class ENLangData extends AbsLangData { @Override public Map
getItems() { /* * Map结构为: * key='title',value='title'; * key='menu', value='menu' */ return null; }}
public abstract class AbsView {    private AbsLangData langData;    //必须有一个语言文件    public AbsView(AbsLangData _langData) {        this.langData = _langData;    }    //获得当前的语言    public AbsLangData getLangData() {        return langData;    }    //页面的URL路径    public String getURI() {        return null;    }    //组装一个页面    public abstract void assemble();}
public class JspView extends AbsView {    //传递语言配置    public JspView(AbsLangData _langData) {        super(_langData);    }    @Override    public void assemble() {        Map
langMap = getLangData().getItems(); for (String key : langMap.keySet()) { /* * 直接替换文件中的语言条目 * */ } }}
public class SwfView extends AbsView {    public SwfView(AbsLangData _langData) {        super(_langData);    }    @Override    public void assemble() {        Map
langMap = getLangData().getItems(); for (String key : langMap.keySet()) { /* * 组装一个HTTP的请求格式: * http://abc.com/xxx.swf?key1=value&key2=value */ } }}
public class ViewManager {    //Action的名称    private String actionName;    //当前的值栈    private ValueStack valueStack = ValueStackHelper.getValueStack();    //接收一个ActionName    public ViewManager(String _actionName) {        this.actionName = _actionName;    }    //根据模型的返回结果提供视图    public String getViewPath(String result) {        //根据值栈查找到需要提供的语言        AbsLangData langData = new GBLangData();        //根据action和result查找到指定的视图,并加载语言        AbsView view = new JspView(langData);        //返回视图的地址        return view.getURI();    }}

【工具类】

  
/index2.jsp
  
/index.jsp
public abstract class ActionNode {    //Action的名称    private String actionName;    //Action的类名    private String actionClass;    //方法名,默认是execute    private String methodName = "excuete";    //视图路径    private String view;    public String getActionName() {        return actionName;    }    public String getActionClass() {        return actionClass;    }    public String getMethodName() {        return methodName;    }    public abstract String getView(String Result);}
public class XmlActionNode extends ActionNode {    //需要转换的element    private Element el;    //通过构造函数传递    public XmlActionNode(Element _el) {        this.el = _el;    }    @Override    public String getActionName() {        return getAttValue("name");    }    @Override    public String getActionClass() {        return getAttValue("class");    }    @Override    public String getMethodName() {        return getAttValue("method");    }    public String getView(String result) {        ViewPathVisitor visitor = new ViewPathVisitor("success");        el.accept(visitor);        return visitor.getViewPath();    }    //获得指定属性值    private String getAttValue(String attName) {        Attribute att = el.attribute(attName);        return att.getText();    }}
public class ViewPathVisitor extends VisitorSupport {    //获得指定的路径    private String viewPath;    private String result;    //传递模型结果    public ViewPathVisitor(String _result) {        result = _result;    }    @Override    public void visit(Element el) {        Attribute att = el.attribute("name");        if (att != null) {            if (att.getName().equals("name") && att.getText().equals(result)) {                viewPath = el.getText();            }        }    }    public String getViewPath() {        return viewPath;    }}

MVC用到了哪些框架:

● 工厂方法模式:通过工厂方法模式把所有的拦截器链实现出来,方便在系统初始化时直接处理。

● 单例模式:Action的默认配置都是单例模式,在一般的应用中单例已经足够了,在复杂情况下可以使用享元模式提供应用性能,减少单例模式的性能隐患。

● 责任链模式:建立拦截器链以及过滤器链,实现任务的链条化处理。

● 迭代器模式:非常方便地遍历拦截器链内的拦截器,而不用再自己写遍历拦截器链的方法。

● 中介者模式:以核心控制器为核心,其他同事类都负责为核心控制器“打工”,保证核心控制器瘦小、稳定。

● 观察者模式:配置文件修改时,不用重启应用可以即刻生效,提供使用者的体验。

● 桥梁模式:使不同的视图配合不同的语言文件,为终端用户展示不同的界面。

● 策略模式:对XML文件的检查可以使用两种不同的策略,而且可以在测试机和开发机中使用不同的检查策略,方便系统间自由切换。

● 访问者模式:在解析XML文件时,使用访问者非常方便地访问到需要的对象。

● 适配器模式:把一个开发者不熟悉的对象转换为熟悉的对象,避免工具或框架对开发者的影响。

● 门面模式:Action分发器负责所有的Action的分发工作,它提供了一个调用Action的唯一入口,避免外部模块深入到模型模块内部。

● 代理模式:大量使用动态代理,确保了框架的智能化。

转载地址:http://lwixa.baihongyu.com/

你可能感兴趣的文章
为什么要跟别人比?
查看>>
app启动白屏
查看>>
Oracle 提高查询性能(基础)
查看>>
学习知识应该像织网一样去学习——“网状学习法”
查看>>
Hadoop集群完全分布式安装
查看>>
QString,char,string之间赋值
查看>>
我的友情链接
查看>>
Nginx+mysql+php-fpm负载均衡配置实例
查看>>
shell脚本操作mysql数据库 (部份参考)
查看>>
MySql之基于ssl安全连接的主从复制
查看>>
informix的逻辑日志和物理日志分析
查看>>
VMware.Workstation Linux与windows实现文件夹共享
查看>>
ARM inlinehook小结
查看>>
wordpress admin https + nginx反向代理配置
查看>>
管理/var/spool/clientmqueue/下的大文件
查看>>
HTML学习笔记1—HTML基础
查看>>
mysql dba系统学习(20)mysql存储引擎MyISAM
查看>>
centos 5.5 64 php imagick 模块错误处理记录
查看>>
apache中文url日志分析--php十六进制字符串转换
查看>>
Ansible--playbook介绍
查看>>