需求:设计一个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; ???}}核心控制器的配置
<?xml version="1.0" encoding="UTF-8"?><web-app> <filter> <display-name>FilterDispatcher</display-name> <filter-name>FilterDispatcher</filter-name> <filter-class>{包名}.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>FilterDispatcher</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping></web-app><?xml version="1.0" encoding="UTF-8"?><mvc><action name="loginAction" class="{类名全路径}" method="execute"><result name="success">/index2.jsp</result><result name="fail">/index.jsp</result></action></mvc>框架逻辑校验
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<Interceptors> 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<AbstractInterceptor> { ???//根据拦截器列表建立一个拦截器链 ???public Interceptors(ArrayList<AbstractInterceptor> list) { ???} ???//列出所有的拦截器 ???public Iterator<AbstractInterceptor> iterator() { ???????return null; ???} ???//拦截器链的执行方法 ???public void intercept() { ???????//委托拦截器执行 ???}}public class InterceptorFactory { ???public static ArrayList<Interceptors> createInterceptors() { ???????//根据配置文件创建出所有的拦截器链 ???????return null; ???}}【视图管理器】
public class GBLangData extends AbsLangData { ???@Override ???public Map<String, String> getItems() { ???/* ???* Map 的结构为: ???* key=‘title‘, value=‘标题‘ ???* key=‘menu‘, value=‘菜单‘ ???*/ ???????return null; ???}}public class ENLangData extends AbsLangData { ???@Override ???public Map<String, String> 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<String, String> langMap = getLangData().getItems(); ???????for (String key : langMap.keySet()) { ???/* ???* 直接替换文件中的语言条目 ???* ???*/ ???????} ???}}public class SwfView extends AbsView { ???public SwfView(AbsLangData _langData) { ???????super(_langData); ???} ???@Override ???public void assemble() { ???????Map<String, String> 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(); ???}}【工具类】
<action name="loginAction" class="{类名全路径}" method="execute"> <result name="success">/index2.jsp</result> <result name="fail">/index.jsp</result></action>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的唯一入口,避免外部模块深入到模型模块内部。
● 代理模式:大量使用动态代理,确保了框架的智能化。
《设计模式之禅》--MVC框架
原文地址:https://www.cnblogs.com/anni-qianqian/p/8447983.html