最简单的mvc框架tiny,增长Aop功能。 css
增长Aop接口,使用是实现便可。 java
而后设置路由(访问的action)和aop的绑定信息,相似以下: web
下面的意思是把路由"/TinyTest/hello/"和TestAop.class作绑定,这样执行类TinyTestAction的hello方法时,就会自动执行TestAop的before和after方法。 mvc
下面的BindingAop 的init方法,须要本身设置。系统启动时会自动读取。 框架
public class BindingAop { public static void init(){ BindingUtil.binding("/TinyTest/hello/", new Class[]{TestAop.class}); BindingUtil.binding("/TinyTest/*", new Class[]{TestAop2.class}); } }
Aop.java dom
package tiny; import java.util.Map; public interface Aop { void before(Map<String,String> args); void after(Map<String,String> args); }
BindingAop.java async
package tiny; import web.servlet.async_request_war.TestAop; import web.servlet.async_request_war.TestAop2; public class BindingAop { public static void init(){ //BindingUtil.binding("/TinyTest/hello/", new Class[]{TestAop.class}); //BindingUtil.binding("/TinyTest/*", new Class[]{TestAop2.class}); //本身绑定 } }
BindingUtil.java ide
package tiny; public final class BindingUtil { public static void binding(String route,Class[] cls){ if(Container.aops.get(route) != null){ new Exception(route+" 重复"); }else{ Container.aops.put(route,cls); } } }
修改后的Container.java 测试
package tiny; import static java.lang.System.out; import java.io.File; import java.net.URL; import java.util.HashMap; import java.util.Map; public class Container { private static Map<String,Object> clsMap = new HashMap<String,Object>(); static Map<String,Class[]> aops =new HashMap<String,Class[]>(); private static Map<String,Aop[]> reqAops =new HashMap<String,Aop[]>(); public static void init() throws ClassNotFoundException, InstantiationException, IllegalAccessException{ ClassLoader cld = Thread.currentThread().getContextClassLoader(); URL resource = cld.getResource("/"); File dirs = new File(resource.getFile()); findAction(dirs,""); } private static void findAction(File dirs,String basePack) throws ClassNotFoundException, InstantiationException, IllegalAccessException { File[] childs = dirs.listFiles(); for (int i = 0; i < childs.length; i++) { String packPath =basePack+childs[i].getName()+"."; if (childs[i].isDirectory()) { findAction(childs[i],packPath); } else { String className = childs[i].getName(); if (className.endsWith("Action.class")) { packPath=packPath.replace(".class.", ""); Object o = Class.forName(packPath).newInstance(); String clsName = o.getClass().getSimpleName().substring(0,o.getClass().getSimpleName().lastIndexOf("Action")); if(clsMap.get(clsName) != null){ new IllegalAccessException(clsName+" class 重复"); }else{ clsMap.put(clsName, o); } } } } } public static Aop[] getBeforeBinding(String[] route,String key) throws InstantiationException, IllegalAccessException{ Aop[] reqAop = null; Class[] aops1 = aops.get("/"+route[0]+"/"+route[1]+"/"); Class[] aops2 = aops.get("/"+route[0]+"/*"); Class[] aops3 = aops.get("/*"); int aopNum1 = aops1 !=null?aops1.length:0; int aopNum2 = aops2 != null?aops2.length:0; int aopNum3 = aops3 !=null?aops3.length:0; if(aopNum3+aopNum2+aopNum1 !=0){ Class[] allAop = new Class[aopNum3+aopNum2+aopNum1]; if(aopNum3>0){ System.arraycopy(aops3,0,allAop,0,aops3.length); } if(aopNum2>0){ System.arraycopy(aops2,0,allAop,aopNum3,aops2.length); } if(aopNum1>0){ System.arraycopy(aops1,0,allAop,aopNum2+aopNum3,aops1.length); } reqAop = new Aop[allAop.length]; for(int a=0;a<allAop.length;a++){ reqAop[a] = (Aop)allAop[a].newInstance(); } reqAops.put(key, reqAop); } return reqAop; } public static Aop[] getAfterBinding(String key){ return reqAops.get(key); } public static void clearReqAops(String key){ reqAops.remove(key); } public static Object getCls(String name){ return clsMap.get(name); } }
修稿后的FrontControl.java this
package tiny; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; 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; //@WebFilter(urlPatterns = { "/demoAsyncLink" }, asyncSupported = true) @WebFilter(urlPatterns = { "/ty/*" }) 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)) { this.servletContext = config.getServletContext(); Container.init(); BindingAop.init(); } } catch (Exception e) { throw new ServletException("FrontControl init failed.", e); } } @Override public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws ServletException, IOException{ HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; ContextUtil.setActionContext(servletContext, req, res); try { String[] routes = valid(req); if(routes == null){ chain.doFilter(request, response); return; } Object o = Container.getCls(routes[0]); if(o == null){ chain.doFilter(request, response); return; } Map<String,String> args = this.converter(req.getParameterMap()); String key = UUID.randomUUID().toString(); this.before(routes,args,key); Object result = o.getClass().getMethod(routes[1],Map.class).invoke(o,args); this.after(args,key); Container.clearReqAops(key); if (result==null){ return; } if (result instanceof Renderer) { Renderer r = (Renderer) result; r.render(this.servletContext, req, res); return; } if (result instanceof String) { String s = (String) result; if (s.startsWith("/")) { request.getRequestDispatcher(s).forward(request, response); return; }else{ response.getWriter().print(result); } } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } private Map<String,String> converter(Map<String,String[]> args){ if(args == null){ return null; } Map<String,String> params = new HashMap<String,String>(); for(String key : args.keySet()){ params.put(key, Arrays.toString(args.get(key)).replaceAll("[\\[\\]\\s,]", "")); } return params; } 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; } //aop before private void before(String[] route,Map<String,String> args,String key) throws InstantiationException, IllegalAccessException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{ Aop[] aops = Container.getBeforeBinding(route, key); if(aops != null){ for(int a=0;a<aops.length;a++){ aops[a].getClass().getMethod("before",Map.class).invoke(aops[a],args); } } } //aop after private void after(Map<String,String> args,String key) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException{ Aop[] aops = Container.getAfterBinding(key); if(aops != null){ for(int a=0;a<aops.length;a++){ aops[a].getClass().getMethod("after",Map.class).invoke(aops[a],args); } } } @Override public void destroy() { } }
测试类代码
TinyTestAction.java
package web.servlet.async_request_war; import java.util.Map; import tiny.ContextUtil; public class TinyTestAction { public void hello(Map<String,String> args){ System.out.println("aa:"+args.get("aa")); System.out.println("访问时间1:"+System.currentTimeMillis()); //ContextUtil.getContext().getXXX; } }
TestAop.java
package web.servlet.async_request_war; import java.util.Map; import tiny.Aop; public class TestAop implements Aop { @Override public void before(Map<String,String> args){ System.out.println(this.getClass().getName()+".before"); } @Override public void after(Map<String,String> args){ System.out.println(this.getClass().getName()+".after"); } }
TestAop2.java
package web.servlet.async_request_war; import java.util.Map; import tiny.Aop; public class TestAop2 implements Aop { @Override public void before(Map<String,String> args){ System.out.println(this.getClass().getName()+".before"); } @Override public void after(Map<String,String> args){ System.out.println(this.getClass().getName()+".after"); } }
测试执行结果截图:
总结
咱们用最少的类实现了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天时间,作的比较粗糙,欢迎你们指导一下。提升下我本身。