3五、最簡單的mvc框架tiny,V2版原理圖、設計

在前面的v1版,因爲咱們臨時起意,存在很多問題,我從新設計框架v2版chen(重名問題更名爲chen)。 java

原理圖以下: mysql

先說下chen框架的功能: web

  1. restful地址支持(chen中叫路由)。
  2. mvc功能,使用簡單。
  3. 多視圖支持,支持自定義擴展。
  4. action支持同步和異步請求。
  5. 充血模型。
  6. aop功能。
Ioc爲容器,管理這全部action和mo del,框架使用者一樣可使用ioc。
  1. 多數據庫支持,經過工廠支持多數據庫實現,支持自定義擴展。
  2. orm功能,使用簡單,無需定義xml、註解等。
  3. 簡單,核心類只有10幾個。

設計思路以下: sql

  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(異步)。


控制器實現: restful


  1. 已servlet 3.0註解方式實現Filter,接受特定的同步/異步請求的前置控制器。
  2. 約定以Action結尾的類,爲action類。
  3. 從1和2咱們能實現完全0配置。


模型實現: mvc


  1. 約定以Model結尾的類,爲model模型類。
  2. 一個model類的名字(去掉model,小寫後)對應一張數據表。實現orm功能。

Aop實現: oracle


  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<String,String> 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<String,Object> args; public Context(String[] routes,Map<String,String> 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<String,String> 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<aops.length;a++){ aopIns[a] = Chen.container.get(Class.forName(aops[a])); } } return aopIns; } private Map<String,Object> converter(Map<String,String[]> args){ if(args == null){ return null; } Map<String, Object> params = new ChenMap(); for(String key : args.keySet()){ params.put(key, Arrays.toString(args.get(key)).replaceAll("[\\[\\]\\s,]", "")); } return params; } }
相關文章
相關標籤/搜索