我的MVC框架————GothaMVC(4)GothamDispatcher的实现和Model层的封装
2016-02-25 11:17
375 查看
前面三章介绍的都是准备工作,当一切完好之后,dispatcher就可以静静地等待HTTP请求的到来了
任何MVC框架的核心都是Dispatcher,它起到一个中央处理器分发HTTP请求的作用,在我的框架中使用了动态代理模式,这点与springMVC所不同的是,它实现了dispatcher与拦截器的充分解耦,将拦截器和handler做成切片,然后通过调用代理对象的方式去触发拦截器和handler。
这样做当然也是为了今后万一我想要扩展或者修改handler,可以使得代码更灵活方便。
为了方便理解,这里将GothaMVC的流程图放上来。
首先我们定义一个handler的接口出来
然后去实现这个接口
这里是要入参前面所表述过的一个handlerWrapper,这样可以将开发者配置的处理方法和参数以及其所在的类三个信息提供给handler让他执行。
接下来,我们要做的是把拦截器和对handler的调用做成一个切片,代码如下
切片做好了之后,我们可以在dispatcher中创建其代理类并通过调用其代理对象达到在调用handler之前和之后触发拦截器的效果,下面是dispatcher的代码
值得一提的是,dispatcher本身也是门面模式的一种体现。
接着,我们来看看model层的实现,其实这个非常简单,只是把视图名称和一个hashmap封装起来就好了,下面是代码
最后说一下,有一些类似于自定义的注释我就没放上来了,只需要告诉大家@Controller是基于类的注解,@Url是基于方法的注解以及二者都是运行时生效。
好了,我的框架到这里就全部介绍完了。其实独立开发感觉还是挺辛苦的,也看了不少源码和博客,尤其是《spring技术内幕》这本书非常不错,给大家推荐一下。
另外,我不保证我的框架可以跑起来啊,哈哈~
还有,本人才疏学浅,在这里也感觉挺献丑的。如果大家发现了什么不足或者错误,一定要帮我指出来哈~
任何MVC框架的核心都是Dispatcher,它起到一个中央处理器分发HTTP请求的作用,在我的框架中使用了动态代理模式,这点与springMVC所不同的是,它实现了dispatcher与拦截器的充分解耦,将拦截器和handler做成切片,然后通过调用代理对象的方式去触发拦截器和handler。
这样做当然也是为了今后万一我想要扩展或者修改handler,可以使得代码更灵活方便。
为了方便理解,这里将GothaMVC的流程图放上来。
首先我们定义一个handler的接口出来
package frontController; import java.lang.reflect.InvocationTargetException; import modelWrapper.Model; import webAppContext.HandlerWrapper; public interface IHandler { Model doHandler(HandlerWrapper hw) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; }
然后去实现这个接口
package frontController; import java.lang.reflect.InvocationTargetException; import modelWrapper.Model; import webAppContext.HandlerWrapper; public class FixHandler implements IHandler { @Override public Model doHandler(HandlerWrapper hw) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Model model=(Model) hw.getM().invoke(hw.getObj(), hw.getArgs()); return model; } }
这里是要入参前面所表述过的一个handlerWrapper,这样可以将开发者配置的处理方法和参数以及其所在的类三个信息提供给handler让他执行。
接下来,我们要做的是把拦截器和对handler的调用做成一个切片,代码如下
package frontController; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.LinkedList; import java.util.ListIterator; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import handlerExecutionChain.HandlerInterceptor; import modelWrapper.Model; import webAppContext.ContextLoader; public class MethodHandler implements InvocationHandler { private Object target; private ServletContext sc; private LinkedList<HandlerInterceptor> chain; private HandlerInterceptor hi; private ListIterator<HandlerInterceptor> iter; private HttpServletRequest req; private HttpServletResponse resp; @SuppressWarnings("unchecked") public MethodHandler(Object target,HttpServletRequest req,HttpServletResponse resp){ this.target=target; this.req=req; this.resp=resp; try { sc=ContextLoader.createContext(); } catch (Exception e) { e.printStackTrace(); } chain=(LinkedList<HandlerInterceptor>) sc.getAttribute("chain"); iter=chain.listIterator(); } @Override public Model invoke(Object object, Method method, Object[] arg0) throws Throwable { if(iter!=null){ while(iter.hasNext()){ hi=iter.next(); if(hi.preHandler(req, resp)){ hi.afterCompletion(req, resp); } } } Model obj=(Model) method.invoke(target, arg0); if(iter!=null){ while(iter.hasPrevious()){ hi=iter.previous(); if(hi.postHandler(req, resp)){ hi.afterCompletion(req, resp); } } } return obj; } }
切片做好了之后,我们可以在dispatcher中创建其代理类并通过调用其代理对象达到在调用handler之前和之后触发拦截器的效果,下面是dispatcher的代码
package frontController; import java.lang.reflect.Proxy; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import modelWrapper.Model; import viewTemplate.ViewContext; import viewTemplate.ViewFactory; import webAppContext.ContextLoader; import webAppContext.HandlerWrapper; public class GothamDispatcher { @SuppressWarnings({ "unchecked" }) protected void doDispatcher(HttpServletRequest doReq,HttpServletResponse doResp) throws Exception{ HttpServletRequest req=doReq; HandlerWrapper hw=null; ServletContext sc=ContextLoader.createContext(); ViewContext viewContext=null; Map<String,HandlerWrapper> urlHandlerMap=(Map<String, HandlerWrapper>) sc.getAttribute("handlers"); String path=req.getServletPath(); if(urlHandlerMap.containsKey(path)){ hw=urlHandlerMap.get(path); }else{ throw new Exception("no matched handlers!"); } IHandler handler=new FixHandler(); MethodHandler mh=new MethodHandler(handler,req,doResp); IHandler proxy=(IHandler) Proxy.newProxyInstance(handler.getClass().getClassLoader(), handler.getClass().getInterfaces(), mh); //调用代理类对象,拦截器被依次执行 Model model=proxy.doHandler(hw); if(model!=null&&model.getView()!=null){ String viewName=model.getView(); String viewSuffix=viewName.substring(viewName.length()-3, viewName.length()-1); switch(viewSuffix){ case "jsp": viewContext=ViewFactory.getView(ViewFactory.getJsp()); viewContext.render(model, req, doResp); case "ftl": viewContext=ViewFactory.getView(ViewFactory.getFreeMarker()); viewContext.render(model, req, doResp); case ".vm": viewContext=ViewFactory.getView(ViewFactory.getVelocity()); viewContext.render(model, req, doResp); } } } }
值得一提的是,dispatcher本身也是门面模式的一种体现。
接着,我们来看看model层的实现,其实这个非常简单,只是把视图名称和一个hashmap封装起来就好了,下面是代码
package modelWrapper; import java.util.Map; public class Model { private String view; private Map<String,Object> model; public Model(String view){ this(null,view); } public Model(Map<String,Object> model,String view){ this.model=model; this.view=view; } public String getView(){ return view; } public Map<String,Object> getModel(){ return model; } }
最后说一下,有一些类似于自定义的注释我就没放上来了,只需要告诉大家@Controller是基于类的注解,@Url是基于方法的注解以及二者都是运行时生效。
好了,我的框架到这里就全部介绍完了。其实独立开发感觉还是挺辛苦的,也看了不少源码和博客,尤其是《spring技术内幕》这本书非常不错,给大家推荐一下。
另外,我不保证我的框架可以跑起来啊,哈哈~
还有,本人才疏学浅,在这里也感觉挺献丑的。如果大家发现了什么不足或者错误,一定要帮我指出来哈~
相关文章推荐
- sublime搭建基于GoSublime+gocode+MarGo的下载SublimeGO开发环境
- 我的MVC框架————GothaMVC(3)view层的实现
- [转]ionic $state.go passed $stateParams
- 我的MVC框架————GothaMVC(2)拦截器的实现
- hill descent algorithm
- this guy gonna be a daddy
- 我的MVC框架————GothaMVC(1)web容器和handler包装类
- POJ1389[Area of Simple Polygons]
- Algorithm 算法
- go 语言的了解
- VIEWGOOD(远古)校园网多媒体系统的搭建
- 在VertrigoSev中搭建Testlink全过程
- golang 的 channel 实现 生产者/消费者 模型
- GO语言下载、安装、配置
- Golang(Go语言)读取文件基本用法
- Golang(Go语言)代码技巧之数组(array)和切片(slice)
- Golang(Go语言)代码技巧之字符串(string)
- Golang(Go语言)内置函数之copy用法
- SAE 环境 django 配置
- 设计模式-单例模式(Go语言描述)