博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
35、最简单的mvc框架tiny,V2版原理图、设计
阅读量:6978 次
发布时间:2019-06-27

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

hot3.png

在前面的v1版,由于我们临时起意,存在不少问题,我重新设计框架v2版chen(重名问题改名为chen)。

原理图如下:

先说下chen框架的功能:

  1. restful地址支持(chen中叫路由)。
  2. mvc功能,使用简单。
  3. 多视图支持,支持自定义扩展。
  4. action支持同步和异步请求。
  5. 充血模型。
  6. aop功能。
Ioc为容器,管理这所有action和mo
del,框架使用者同样可以使用ioc。
  1. 多数据库支持,通过工厂支持多数据库实现,支持自定义扩展。
  2. orm功能,使用简单,无需定义xml、注解等。
  3. 简单,核心类只有10几个。

设计思路如下:

  1. 以前置控制器接受用户特定请求,如果为action请求,则将请求地址转化为路由(/类/方法/)。
  2. 根据用户的请求类型(同步或异步),创建执行环境,交给不同的handler来处理。
  3. handler以初始化、执行、渲染视图、销毁资源4个步骤一次执行。
  4. handler执行:从执行环境(执行环境从ioc容器中取出action和aop)中取出action、aop等信息,调用aop和action。
  5. handler渲染视图:根据action返回的类型,渲染视图和保存数据。
  6. handler销毁资源:销毁执行环境。
  7. action中使用的model模型,是从ioc容器中取出。
  8. model模型通过工具类获得合适数据库操作。工具类通过工厂类获得。
  9. 工厂类会初始化数据库、数据库连接池等。

视图实现:

  1. 定义抽象类Renderer,定义render方法渲染视图,然后实现不同的视图渲染,如JspRendererFileRenderer等jsp和文件视图。
  2. 实现同步和异步视图。如JspRenderer、JspAsyncRenderer(异步)。

控制器实现:

  1. 已servlet 3.0注解方式实现Filter,接受特定的同步/异步请求的前置控制器。
  2. 约定以Action结尾的类,为action类。
  3. 从1和2我们能实现彻底0配置。

模型实现:

  1. 约定以Model结尾的类,为model模型类。
  2. 一个model类的名字(去掉model,小写后)对应一张数据表。实现orm功能。

Aop实现:

  1. 定义aop接口,定义action执行前后拦截方法。
  2. 绑定自定义的aop类和路由关系。如:/TinyTest/hello/=web.TestAop

Ioc实现:

  1. 定义接口IChen,定义方法,如添加类、取出类、接口实现等。
  2. 在前置控制器启动时,初始化ioc。(自动将action和model放入ioc容器)

仓储实现:

  1. 定义接口IRepository定义同数据库交互方法。
  2. 实现oracle、mysql等实现。
  3. 定义工厂类,用户使用dao工具类时,自动适应数据库类型。
  4. 实现数据库连接池,有工厂类初始化。

整体处理流程如下:

用户在页面发起了一个action的请求,前置控制器截获了这个请求,验证之后,将请求地址转化为路由,根据请求类型同步或异步,生成执行环境(包括:Request、路由、action实例、方法、参数等),将执行环境放入handler中(同步或异步请求,有不同的handler,也可以自定义扩展),handler依次执行:初始化、执行、渲染视图、销毁资源4个步骤处理请求,在执行时先执行aop before,然后执行action,action中调用的model,从ioc容器获得,model使用dao工具类,操作数据库。再执行aop after。渲染视图是根据action返回结果,渲染特定视图或保存数据。最后销毁资源。

代码

前置控制器FrontControl.java

package chen;import java.io.IOException;import java.util.concurrent.atomic.AtomicBoolean;import javax.servlet.AsyncContext;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import chen.aop.Binder;import chen.ioc.Chen;import chen.util.ContextUtil;@WebFilter(urlPatterns = { "/ty/*" }, asyncSupported = true)public class FrontControl implements Filter{		private AtomicBoolean initialized = new AtomicBoolean();	private ServletContext servletContext;	@Override    public void init(final FilterConfig config) throws ServletException{        try {            if (initialized.compareAndSet(false, true)) {            	long time1 = System.currentTimeMillis();            	this.servletContext = config.getServletContext();                Scaner.run();                Binder.load();                System.out.println(">>> chen 已经启动,用时"+(System.currentTimeMillis()-time1)/1000+"秒");            }        }        catch (Exception e) {            throw new ChenException(" >>> chen 启动失败",e);        }    }    @Override    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws ServletException, IOException{        HttpServletRequest req = (HttpServletRequest) request;        HttpServletResponse res = (HttpServletResponse) response;        String[] routes = valid(req);        if(routes == null){        	chain.doFilter(request, response);        	return;        }        try {        	long time1 = System.currentTimeMillis();            Context context = null;            IHandler handler = null;            if(routes[0].endsWith("Async")){            	AsyncContext async = req.startAsync();  		        async.setTimeout(30*1000);		        context = new Context(routes,Scaner.getCls(),Binder.getAop(routes),req,res,servletContext,async);		        async.start(new AsynHandler(context));            }else{            	context = new Context(routes,Scaner.getCls(),Binder.getAop(routes),req,res,servletContext);            	handler = new ChenHandler(context);            	handler.init();            }            System.out.println(">>> chen 处理路由/"+routes[0]+"/"+routes[1]+"/完成,用时"+(System.currentTimeMillis()-time1)/1000+"秒");        }        catch (Exception e) {        	throw new ChenException(" >>> chen 处理路由/"+routes[0]+"/"+routes[1]+"/失败",e);        }    }    private String[] valid(HttpServletRequest req){        String uri = req.getRequestURI();        String path = req.getContextPath();        if (path != null){        	uri = uri.substring(path.length());        }else{        	return null;        }        String[] routes = uri.substring(uri.indexOf("/ty/")+4).split("/");        if(routes == null || routes.length<2){        	return null;        }        return routes;    }    @Override    public void destroy() {    }}

执行环境Context.java

package chen;import java.lang.reflect.Method;import java.util.Arrays;import java.util.Map;import javax.servlet.AsyncContext;import javax.servlet.ServletContext;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import chen.aop.Aop;import chen.ioc.Chen;import chen.util.ChenMap;public class Context {	public final Map
cls; public final Object[] aops; public final String[] routes; public final HttpServletRequest reqs; public final HttpServletResponse resp; public final ServletContext servletContext; public final AsyncContext async; public final Object instance; public final Method method; public final Map
args; public Context(String[] routes,Map
cls,String[] aops,HttpServletRequest reqs,HttpServletResponse resp,ServletContext servletContext) throws ClassNotFoundException, SecurityException, NoSuchMethodException{ this.cls = cls; this.aops = this.converter(aops); this.routes = routes; this.reqs = reqs; this.resp = resp; this.servletContext = servletContext; this.instance = Chen.container.get(Class.forName(this.cls.get(this.routes[0]+"Action"))); this.method = this.instance.getClass().getMethod(routes[1],Map.class); this.args = this.converter(this.reqs.getParameterMap()); this.async = null; } public Context(String[] routes,Map
cls,String[] aops,HttpServletRequest reqs,HttpServletResponse resp,ServletContext servletContext,AsyncContext async) throws ClassNotFoundException, SecurityException, NoSuchMethodException{ this.cls = cls; this.aops = this.converter(aops); this.routes = routes; this.reqs = reqs; this.resp = resp; this.servletContext = servletContext; this.instance = Chen.container.get(Class.forName(this.cls.get(this.routes[0]+"Action"))); this.method = this.instance.getClass().getMethod(routes[1],Map.class); this.args = this.converter(this.reqs.getParameterMap()); this.async = async;} private Object[] converter(String[] aops) throws ClassNotFoundException{ Object[] aopIns = null; if(aops !=null && aops.length>0){ aopIns = new Object[aops.length]; for(int a=0;a
converter(Map
args){ if(args == null){ return null; } Map
params = new ChenMap(); for(String key : args.keySet()){ params.put(key, Arrays.toString(args.get(key)).replaceAll("[\\[\\]\\s,]", "")); } return params; }}

转载于:https://my.oschina.net/eternal/blog/227074

你可能感兴趣的文章
UITextField的代理方法
查看>>
无人驾驶相关数据集
查看>>
C 的大致运行原理。
查看>>
关于jsp和eclipse服务器端的相关配置和JS的区别
查看>>
JavaScript - 数据类型和变量
查看>>
TCP/IP:IP选项处理
查看>>
【网摘】检测 iframe 是否加载完成
查看>>
cocos2dx 3.x(动态改变精灵的背景图片)
查看>>
cocos2d-x JS 获取当前系统时间(解决屏幕双击点击事件)
查看>>
支付宝接入参考博客
查看>>
学习Spring中遇到关于BeanFactory及测试类的问题
查看>>
现实迷途 第七章 特殊客户
查看>>
找水王
查看>>
fgets()用法笔记
查看>>
mysql以及mysql bench安装教程
查看>>
Linear Regression with machine learning methods
查看>>
在 Azure 网站上使用 Memcached 改进 WordPress
查看>>
数据库备份定期删除程序的开发。
查看>>
启动Genymotion时报错Failed to initialize backend EGL display
查看>>
BZOJ 1040 ZJOI2008 骑士 树形DP
查看>>