前面我说的实现一个自动转型功能的TinyMap,实现思路前面已经说过,我引用下
解决思路: 重写一个TinyMap类继承HashMap。我们实现getInt,getString等方法,调用这些方法可以对类型自动转换,当使用get方法时,其实是调用HashMap的get方法,放回object类型,代码如下: TinyMap tMap = new TinyMap(参); tMap.getInt(key); tMap.getString(key); tMap.get(key);//Ojbect 然后由前置控制器中将页面的参数转换为TinyMap类型(现在转换为HashMap),最后放入action参数中。由于action中参数为map接口,所有对原设计无影响,用户可同时使用HashMap和TinyMap的方法。TinyMap.java
package tiny; import java.util.Date; import java.util.HashMap; public class TinyMap extends HashMap<String, Object> { public TinyMap() { super(); } public TinyMap(HashMap<String, Object> map) { super(); this.putAll(map); } public int getInt(String key) { Object value = super.get(key); return value != null ? this.converter(value,int.class):null; } public float getFloat(String key) { Object value = super.get(key); return value != null ? this.converter(value,float.class):null; } public long getLong(String key) { Object value = super.get(key); return value != null ? this.converter(value,long.class):null; } public double getDouble(String key) { Object value = super.get(key); return value != null ? this.converter(value,double.class):null; } public boolean getBoolean(String key) { Object value = super.get(key); return value != null ? this.converter(value,boolean.class):null; } public String getString(String key) { Object value = super.get(key); return value != null ? this.converter(value,String.class):null; } public Date getTime(String key) { Object value = super.get(key); return value != null ? this.converter(value,Date.class):null; } public <T> T getAs(String key, Class<T> custom) { Object value = super.get(key); return value != null ? this.converter(value,custom):null; } private <T> T converter(Object value, Class<T> t){ return (T) value; } }
思路,上面的代码大家一看就明白了,我在补充几句,TinyMap可以接受 HashMap类型的参数,然后putAll。转型的实现我写了一个泛型方法,通过返回泛型T,来自动转型,泛型T就是传入想要转型的具体类型,然后把value转化为T类型,呵呵。
测试代码
public static void main(String[] args){ TinyMap tm = new TinyMap(); tm.put("a", 1); tm.put("b","a2"); tm.put("c",0.12f); int a = tm.getInt("a"); String b = tm.getString("b"); float c = tm.getFloat("c"); String d = tm.getAs("b", String.class); System.out.println(a); System.out.println(b); System.out.println(c); System.out.println(d); }
FrontControl.java修改后
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 = { "/ty" }, 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,Object> args = this.converter(req.getParameterMap()); String key = UUID.randomUUID().toString(); Container.inject(o); 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,Object> converter(Map<String,String[]> args){ if(args == null){ return null; } Map<String, Object> params = new TinyMap(); 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,Object> 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,Object> 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() { } }
Aop.java
package tiny; import java.util.Map; public interface Aop { void before(Map<String,Object> args); void after(Map<String,Object> args); //void before(TinyMap args); //void after(TinyMap args); }
写Action时同样选择是否使用TinyMap,如下Action中hello方法是用来TinyMap,其他则为Map接口
package web; import java.util.Map; import tiny.ContextUtil; import tiny.JspRenderer; import tiny.Renderer; import tiny.TinyMap; public class TinyTestAction { public UserModel user; public void hello(TinyMap args){ System.out.println("aa:"+args.getString("aa")); System.out.println("访问时间1:"+System.currentTimeMillis()); //ContextUtil.getContext().getXXX; } public String hello2(Map<String,String> args){ return "/index.jsp"; } public Renderer hello3(Map<String,String> args){ //数据库 Map<String,Object> data = user.outStr(args); return new JspRenderer("/index.jsp",data); } }