30、最简单的mvc框架tiny,增加Aop

最简单的mvc框架tiny,增加Aop功能。

增加Aop接口,使用是实现即可。

然后设置路由(访问的action)和aop的绑定信息,类似如下:

下面的意思是把路由"/TinyTest/hello/"和TestAop.class做绑定,这样执行类TinyTestAction的hello方法时,就会自动执行TestAop的before和after方法。

下面的BindingAop 的init方法,需要自己设置。系统启动时会自动读取。

1public class BindingAop { 2   public static void init(){ 3    BindingUtil.binding("/TinyTest/hello/", new Class[]{TestAop.class}); 4    BindingUtil.binding("/TinyTest/*", new Class[]{TestAop2.class}); 5   } 6}

Aop.java

1package tiny; 2 3import java.util.Map; 4 5public interface Aop { 6    void before(Map<String,String> args); 7    void after(Map<String,String> args); 8}

BindingAop.java

1package tiny; 2 3import web.servlet.async_request_war.TestAop; 4import web.servlet.async_request_war.TestAop2; 5 6public class BindingAop { 7   public static void init(){ 8    //BindingUtil.binding("/TinyTest/hello/", new Class[]{TestAop.class}); 9    //BindingUtil.binding("/TinyTest/*", new Class[]{TestAop2.class}); 10    //自己绑定 11   } 12}

BindingUtil.java

1package tiny; 2 3 4public final class BindingUtil { 5 public static void binding(String route,Class[] cls){ 6 if(Container.aops.get(route) != null){ 7 new Exception(route+" 重复"); 8 }else{ 9 Container.aops.put(route,cls); 10 } 11 } 12}

修改后的Container.java

1package tiny; 2 3import static java.lang.System.out; 4 5import java.io.File; 6import java.net.URL; 7import java.util.HashMap; 8import java.util.Map; 9public class Container { 10    private static Map<String,Object> clsMap = new HashMap<String,Object>(); 11    static Map<String,Class[]> aops =new HashMap<String,Class[]>(); 12    private static Map<String,Aop[]> reqAops =new HashMap<String,Aop[]>(); 13    public static void init() throws ClassNotFoundException, InstantiationException, IllegalAccessException{ 14 ClassLoader cld = Thread.currentThread().getContextClassLoader(); 15 URL resource = cld.getResource("/"); 16 File dirs = new File(resource.getFile()); 17 findAction(dirs,""); 18    } 19 20 private static void findAction(File dirs,String basePack) 21 throws ClassNotFoundException, InstantiationException, IllegalAccessException { 22 File[] childs = dirs.listFiles(); 23 for (int i = 0; i < childs.length; i++) { 24 String packPath =basePack+childs[i].getName()+"."; 25 if (childs[i].isDirectory()) { 26 findAction(childs[i],packPath); 27 } else { 28 String className = childs[i].getName(); 29 if (className.endsWith("Action.class")) { 30 packPath=packPath.replace(".class.", ""); 31 Object o = Class.forName(packPath).newInstance(); 32 String clsName = o.getClass().getSimpleName().substring(0,o.getClass().getSimpleName().lastIndexOf("Action")); 33 if(clsMap.get(clsName) != null){ 34 new IllegalAccessException(clsName+" class 重复"); 35 }else{ 36 clsMap.put(clsName, o); 37 } 38 } 39 } 40 } 41 } 42 43 44 public static Aop[] getBeforeBinding(String[] route,String key) throws InstantiationException, IllegalAccessException{ 45 Aop[] reqAop = null; 46 47 Class[] aops1 = aops.get("/"+route[0]+"/"+route[1]+"/"); 48     Class[] aops2 = aops.get("/"+route[0]+"/*"); 49     Class[] aops3 = aops.get("/*"); 50     int aopNum1 = aops1 !=null?aops1.length:0; 51     int aopNum2 = aops2 != null?aops2.length:0; 52     int aopNum3 = aops3 !=null?aops3.length:0; 53     if(aopNum3+aopNum2+aopNum1 !=0){ 54     Class[] allAop = new Class[aopNum3+aopNum2+aopNum1]; 55 56     if(aopNum3>0){ 57     System.arraycopy(aops3,0,allAop,0,aops3.length); 58     } 59     if(aopNum2>0){ 60     System.arraycopy(aops2,0,allAop,aopNum3,aops2.length); 61     } 62     if(aopNum1>0){ 63     System.arraycopy(aops1,0,allAop,aopNum2+aopNum3,aops1.length); 64     } 65     reqAop = new Aop[allAop.length]; 66     for(int a=0;a<allAop.length;a++){ 67     reqAop[a] = (Aop)allAop[a].newInstance(); 68     } 69     reqAops.put(key, reqAop); 70     } 71     return reqAop; 72 } 73 74 public static Aop[] getAfterBinding(String key){ 75 return reqAops.get(key); 76 } 77 78 public static void clearReqAops(String key){ 79 reqAops.remove(key); 80 } 81 82 public static Object getCls(String name){ 83 return clsMap.get(name); 84 } 85 86}

修稿后的FrontControl.java

1package tiny; 2 3import java.io.IOException; 4import java.lang.reflect.InvocationTargetException; 5import java.util.Arrays; 6import java.util.HashMap; 7import java.util.Map; 8import java.util.UUID; 9import java.util.concurrent.atomic.AtomicBoolean; 10 11import javax.servlet.Filter; 12import javax.servlet.FilterChain; 13import javax.servlet.FilterConfig; 14import javax.servlet.ServletContext; 15import javax.servlet.ServletException; 16import javax.servlet.ServletRequest; 17import javax.servlet.ServletResponse; 18import javax.servlet.annotation.WebFilter; 19import javax.servlet.http.HttpServletRequest; 20import javax.servlet.http.HttpServletResponse; 21 22//@WebFilter(urlPatterns = { "/demoAsyncLink" }, asyncSupported = true) 23@WebFilter(urlPatterns = { "/ty/*" }) 24public class FrontControl implements Filter{ 25 26 private AtomicBoolean initialized = new AtomicBoolean(); 27 private ServletContext servletContext; 28 29 @Override 30    public void init(final FilterConfig config) throws ServletException{ 31        try { 32            if (initialized.compareAndSet(false, true)) { 33             this.servletContext = config.getServletContext(); 34                Container.init(); 35                BindingAop.init(); 36            } 37        } 38        catch (Exception e) { 39            throw new ServletException("FrontControl init failed.", e); 40        } 41    } 42 43    @Override 44    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws ServletException, IOException{ 45        HttpServletRequest req = (HttpServletRequest) request; 46        HttpServletResponse res = (HttpServletResponse) response; 47        ContextUtil.setActionContext(servletContext, req, res); 48        try { 49            String[] routes = valid(req); 50            if(routes == null){ 51             chain.doFilter(request, response); 52             return; 53            } 54            Object o = Container.getCls(routes[0]); 55            if(== null){ 56             chain.doFilter(request, response); 57             return; 58            } 59             60            Map<String,String> args = this.converter(req.getParameterMap()); 61             62            String key = UUID.randomUUID().toString(); 63            this.before(routes,args,key); 64             65 Object result = o.getClass().getMethod(routes[1],Map.class).invoke(o,args); 66 67 this.after(args,key); 68 69 Container.clearReqAops(key); 70 71         if (result==null){ 72             return; 73         } 74         if (result instanceof Renderer) { 75             Renderer r = (Renderer) result; 76             r.render(this.servletContext, req, res); 77             return; 78         } 79         if (result instanceof String) { 80             String s = (String) result; 81             if (s.startsWith("/")) { 82                 request.getRequestDispatcher(s).forward(request, response); 83                 return; 84             }else{ 85              response.getWriter().print(result); 86             } 87         } 88 89 } catch (IllegalAccessException e) { 90 e.printStackTrace(); 91 } catch (IllegalArgumentException e) { 92 e.printStackTrace(); 93 } catch (SecurityException e) { 94 e.printStackTrace(); 95 } catch (InvocationTargetException e) { 96 e.printStackTrace(); 97 } catch (NoSuchMethodException e) { 98 e.printStackTrace(); 99 } catch (Exception e) { 100 e.printStackTrace(); 101 } 102    } 103    private Map<String,String> converter(Map<String,String[]> args){ 104     if(args == null){ 105     return null; 106     } 107        Map<String,String> params = new HashMap<String,String>(); 108        for(String key : args.keySet()){ 109         params.put(key, Arrays.toString(args.get(key)).replaceAll("[\\[\\]\\s,]", "")); 110        } 111        return params; 112    } 113    private String[] valid(HttpServletRequest req){ 114        String uri = req.getRequestURI(); 115        String path = req.getContextPath(); 116        if (path != null){ 117         uri = uri.substring(path.length()); 118        }else{ 119         return null; 120        } 121        String[] routes = uri.substring(uri.indexOf("/ty/")+4).split("/"); 122        if(routes == null || routes.length<2){ 123         return null; 124        } 125        return routes; 126    } 127    //aop before 128    private void before(String[] route,Map<String,String> args,String key) throws InstantiationException, IllegalAccessException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{ 129     Aop[] aops = Container.getBeforeBinding(route, key); 130     if(aops != null){ 131     for(int a=0;a<aops.length;a++){ 132     aops[a].getClass().getMethod("before",Map.class).invoke(aops[a],args); 133     } 134     } 135    } 136    //aop after 137    private void after(Map<String,String> args,String key) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException{ 138     Aop[] aops = Container.getAfterBinding(key); 139     if(aops != null){ 140     for(int a=0;a<aops.length;a++){ 141     aops[a].getClass().getMethod("after",Map.class).invoke(aops[a],args); 142     } 143     } 144    } 145     146    @Override 147    public void destroy() { 148    } 149}

测试类代码

TinyTestAction.java

1package web.servlet.async_request_war; 2 3import java.util.Map; 4 5import tiny.ContextUtil; 6 7public class TinyTestAction { 8 public void hello(Map<String,String> args){ 9 10 System.out.println("aa:"+args.get("aa")); 11 System.out.println("访问时间1:"+System.currentTimeMillis()); 12 //ContextUtil.getContext().getXXX; 13 } 14}

TestAop.java

1package web.servlet.async_request_war; 2 3import java.util.Map; 4 5import tiny.Aop; 6 7public class TestAop implements Aop { 8 9 @Override 10 public void before(Map<String,String> args){ 11 System.out.println(this.getClass().getName()+".before"); 12 } 13 14 @Override 15 public void after(Map<String,String> args){ 16 System.out.println(this.getClass().getName()+".after"); 17 } 18}

TestAop2.java

1package web.servlet.async_request_war; 2 3import java.util.Map; 4 5import tiny.Aop; 6 7public class TestAop2 implements Aop { 8 9 @Override 10 public void before(Map<String,String> args){ 11 System.out.println(this.getClass().getName()+".before"); 12 } 13 14 @Override 15 public void after(Map<String,String> args){ 16 System.out.println(this.getClass().getName()+".after"); 17 } 18}

测试执行结果截图:

总结

我们用最少的类实现了mvc功能,其实应该叫类似mvc功能的模板,更合适。呵呵。

主要用到的就是filter来拦截用户请求,然后统一处理。servlet也可以实现,不过filter有个好处是不用自己处理静态文件的请求。(eternal框架自己处理了静态请求如css、js)。

0配置,0注解,以前0配置必须是使用注解的,咱们使用了servlet3.0的注解方式配置(tiny自身),这样使用者,根本就不用配置。

aop的实现,更简单,就是匹配拦截到的路由和用户自己绑定的,就比较。然后,执行action前置性before,执行action后,执行after,并传递参数。

昨天忘记说了,Renderer渲染器,是可以携带数据的,大家一看就明白了。还有就是得使用jee6,因为用到了servlet3.0。

还有就是要实现一个java调用js的功能,类似dwr的,呵呵,实现这个功能后咱们在增加一个js文件,tiny就是所有的文件了。

花了1天时间,做的比较粗糙,欢迎大家指导一下。提高下我自己。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Java日期时间API系列31

  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前

30、最简单的mvc框架tiny,增加Aop - HelloWorld