zoukankan      html  css  js  c++  java
  • JAVA常用编程代码块

    转Map时要考虑Map的key是否重复

    List<Entity>转为Map<keyField, valueField>

    将一个List实体集合转换为以Entity某一个字段为key,另一字段为value映射的Map

        /**
         * List转换为Map<key字段,val字段/实体>
         */
        public Map<String,Object> getMapByList(List list){
            Map<String,Object> resultMap= new HashMap<String,Object>();  //结果,字段/值的映射map
    
            if (CollectionUtil.isNotEmpty(list)){   //先判断list是否为空
                for (Entity entity:list){     //遍历List
                    String keyField= entity.getKeyField();   //
                    Object valueField = entity.getValField();   //值,值也可以为其他字段或者整个对象
    /********遍历list的key字段不能直接放入Map中,因为可能有重复的,这样发现不了问题*********/ if (resultMap.containsKey(keyField)){ //如果key字段的值是有重复的 valueField = resultMap.get(keyField) + StringUtil.SEPARATOR + valueField; //value字段的值为: 旧的数据<-->新的数据作为value }
    /**********处理可能重复key的情况结束************/ resultMap.put(keyField,valueField); //最后在将处理后的keyField和valueField放入到Map中去 } }
    return resultMap; }

    List<Entity>转为Map<keyField,List<Entity>>

    将List中的实体根据keyField字段分类成Map<keyField,List>

         public Map<String,List<Entity>> getMapByList(List<Entity> list){
            Map<String,List<Entity>> resultMap = new HashMap<String,List<Entity>>();   //目标结果Map
    
            if (CollectionUtil.isNotEmpty(list)){    //判断是否为空
                for (Entity entity:list){    //遍历List集合
                    String keyField = entity.getKeyField();    //获取key字段值
                  
                    /****************************考虑Map中key值重复的情况*****************************/
                    List<Entity> list;   //根据keyField分组的list
                    if (resultMap.containsKey(keyField)){    //如果之前有keyField字段对一个的实体已经放入过List,即已经存在在结果Map中
                        list = resultMap.get(keyField);   //根据keyFiedl获取Map中对应的List集合
                    }else{
                        list = new ArrayList<Entity>();  //这个字段之前没有放入过实体,没有List,新建一个List
                    }
                    list.add(entity);   //放入到keyField对应的List中去
                    /*************************考虑Map中key值重复的情况结束********************************/
                    
                    resultMap.put(keyField,list);   //放入到Map<keyField,List<Entity>>的映射中
                }
            }
            return resultMap;
        }

    动态代理实现代理链

    即当一个class执行某个method方法时,要先执行一系列Proxy(接口)子类的doProxy()方法。

    思路:

    根据isAssiginFrom获取Proxy所有的实现类,然后根据Proxy子类上的注解获取要拦截哪些类(切点),根据注解获取目标类集合,生成Map<Proxy,Set<targetClass>>

    然后转换为Map<targetClass,List<ProxyInstance>>,然后用代理链ProxyChain生成代理链,每当方法执行时,会先执行ProxyChain中的doProxy方法。doProxy方法执行会执行Proxy代理集合(把自己作为参数带进去),然后在Proxy代理实例中继续执行ProxyChain中的doProxy方法,直到所有代理链执行完毕,ProxyChain执行了目标函数,然后依次返回Proxy中执行后续代码。

    实现步骤:

    获取所有的代理类

        /**
         * 获取应用包名下某父类(接口)的所有子类(或实现类)
         * @param superClass 父类/接口/类本身(基本数据类型)
         * @return
         */
        public static Set<Class<?>> getClassSetBySuper(Class<?> superClass){
            Set<Class<?>> classSet = new HashSet<Class<?>>();
            for (Class<?> cls:CLASS_SET){
                /*!!!!!!!!!!重点!!!!!!!!!!获取某个基类的子类(这样可以获取AOP的所有切面)*/
                if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)){  //superClass是cls的父类或接口(superClass为cls的父类/接口/本身 && superClass不等于cls)
                    classSet.add(cls);
                }
            }
            return classSet;
        }

    获取所有目标类

        /**
         * 获取应用包名下带有指定注解的所有类
         * @param annotationClass 注解
         * @return
         */
        public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotationClass){
            Set<Class<?>> classSet = new HashSet<Class<?>>();
            for (Class<?> cls : CLASS_SET){
                if (cls.isAnnotationPresent(annotationClass)){  //如果此类带有annotationClass注解
                    classSet.add(cls);
                }
            }
            return classSet;
        }

    生成Map<Proxy,Set<targetClass>>

            /**
         * 创建所有Map<代理类,Set<代理目标类>>的映射关系
         * @return Map<代理类,Set<代理目标类>>
         * @throws Exception
         */
        private static Map<Class<?>,Set<Class<?>>> createProxyMap() throws Exception{
            Map<Class<?>,Set<Class<?>>> proxyMap = new HashMap<Class<?>, Set<Class<?>>>();   //结果集<代理类,Set<代理目标类>>
            addAspectProxy(proxyMap);   //添加普通切面
            addTransactionProxy(proxyMap);   //添加事务代理
            return proxyMap;
        }
    
      /**
         * 添加切面代理
         * @param proxyMap
         */
        private static void addAspectProxy(Map<Class<?>,Set<Class<?>>> proxyMap){
            //获取所有的AspectProxy的子类(代理类集合),即切面,
            /*这个是入口,根据基类来查找所有的切面(代理类),获取所有的切面!!!*/
            Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
            for (Class<?> proxyClass : proxyClassSet){   //遍历代理类(切面),如ControllerAspect
                if (proxyClass.isAnnotationPresent(Aspect.class)){    //验证基类为AspectProxy且要有Aspect注解的才能为切面。如果代理类的的注解为Aspect(也就是说代理类一定要都切点(注解)才能是切面),例如ControllerAspect代理类的注解为@Aspect(Controller.class)
                    Aspect aspect = proxyClass.getAnnotation(Aspect.class);   //获取代理类(切面)的注解
                    /*根据注解获取所有的目标类*/
                    Set<Class<?>> targetClassSet = createTargetClassSet(aspect);   //获取所有的代理目标类集合
                    proxyMap.put(proxyClass,targetClassSet);   //加入到结果集Map<代理类,Set<代理目标类>>中
                }
            }
        }
    
        /**
         * 根据Aspect注解(切点)获取所有的代理目标类集合(目标类为Controller等注解的类)
         * @param aspect 代理类注解,用来指定目标类的注解 例如:@Aspect(Controller.class)
         * @return 返回Aspect注解中指定value注解的目标类  例如:带Controller注解的所有类
         * 例如Aspect(Controller.class)是指获取所有Controller注解的类
         */
        private static Set<Class<?>> createTargetClassSet(Aspect aspect){
            Set<Class<?>> targetClassSet = new HashSet<Class<?>>();
            Class<? extends Annotation> annotation = aspect.value();   //获取值(也是注解)
            if (annotation!=null && !annotation.equals(Aspect.class)){   //获取的value注解不为null,且注解不为Aspect
                targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));   //加入所有value(切点)指定的注解的类
            }
            return targetClassSet;   //返回所有目标类
        }

    然后把Map<Proxy,Set<targetClass>>转成Map<targetClass,List<ProxyInstance>>

        /**
         * 将Map<代理类,Set<目标类>> proxyMap转为Map<目标类,List<代理类>> targetMap
         * @param proxyMap Map<代理类,Set<目标类>>
         * @return Map<目标类,List<代理类实例>>
         * @throws Exception
         */
        private static Map<Class<?>,List<Proxy>> createTargetMap(Map<Class<?>,Set<Class<?>>> proxyMap) throws Exception{
            Map<Class<?>,List<Proxy>> targetMap = new HashMap<Class<?>,List<Proxy>>();   //class - list键值对的map
            for (Map.Entry<Class<?>,Set<Class<?>>> proxyEntry:proxyMap.entrySet()){   //遍历cls - set键值对的map
                Class<?> proxyClass = proxyEntry.getKey();   //获取代理cls
                Set<Class<?>> targetClassSet = proxyEntry.getValue();   //获取目标Set
                for (Class<?> targetClass:targetClassSet){    //遍历目标Set
                    Proxy proxy = (Proxy) proxyClass.newInstance();   //实例化代理类
                    if (targetMap.containsKey(targetClass)){    //如果Map<Class<?>,List<Proxy>>包含该目标类
                        targetMap.get(targetClass).add(proxy);   //直接将代理类添加到对应目标类的Map中
                    }else{
                        List<Proxy> proxyList = new ArrayList<Proxy>();   //如果没有
                        proxyList.add(proxy);
                        targetMap.put(targetClass,proxyList);
                    }
                }
            }
            return targetMap;
        }

    将Map<targetClass,List<ProxyInstance>>生成代理连

        static{
            try{
                Map<Class<?>,Set<Class<?>>> proxyMap = createProxyMap();   //获取Map<代理类,Set<目标类>>
                Map<Class<?>,List<Proxy>> targetMap = createTargetMap(proxyMap);  //获取Map<目标类,List<代理实例>>
                for (Map.Entry<Class<?>,List<Proxy>> targetEntry:targetMap.entrySet()){   //遍历Map<目标类,List<代理实例>>
                    Class<?> targetClass = targetEntry.getKey();   //目标类
                    List<Proxy> proxyList = targetEntry.getValue();    //代理类
    //生成代理链!!! Object proxy = ProxyManager.createProxy(targetClass,proxyList); //根据目标类和代理集合创建一个代理 BeanHelper.setBean(targetClass,proxy); //将Bean容器中目标类对应的实体替换成代理 } }catch (Exception e){ LOGGER.error("aop failure",e); } }

    代理链实现如下:

    Proxy接口及其实现,这里用到模板方法模式

    /**
     * 代理接口
     */
    public interface Proxy {
    
        /**
         * 执行链式代理
         * @param proxyChain 这个链式代理参数中含有所有的代理类,和目标类的参数(类、方法、方法参数)
         * @return
         * @throws Throwable
         */
        Object doProxy(ProxyChain proxyChain) throws Throwable;
    }
    
    /**
     * 切面代理
     */
    public abstract class AspectProxy implements Proxy{
        private static final Logger logger = LoggerFactory.getLogger(AspectProxy.class);
    
        /**
         * 执行链式代理
         */
        @Override
        public Object doProxy(ProxyChain proxyChain) throws Throwable {
            Object result = null;
            //获取目标类、方法、方法参数
            Class<?> cls = proxyChain.getTargetClass();
            Method method = proxyChain.getTargetMethod();
            Object[] params = proxyChain.getMethodParams();
    
            begin();    //代理开始时执行begin方法
            try {
                if (intercept(cls,method,params)){    //判断是否拦截此方法
                    before(cls,method,params);     //目标方法执行前代理方法before执行
                    result = proxyChain.doProxyChain();   //执行下一个代理
                    after(cls,method,result);    //目标方法执行后代理方法after执行
                }else {
                    result = proxyChain.doProxyChain();    //执行下一个代理
                }
            }catch(Exception e){
                logger.error("proxy failure",e);
                error(cls,method,params,e);    //抛出异常时代理方法error执行
                throw e;
            }finally{
                end();    //代理结束时执行方法end
            }
            return result;
        }
        /*方法开始前执行*/
        public void begin(){
        }
    
        /**
         * 拦截
         * @param cls 目标类
         * @param method 目标方法
         * @param params 目标方法参数
         * @return 返回是否拦截
         */
        public boolean intercept(Class<?> cls, Method method, Object[] params) throws Throwable {
            return true;
        }
    
        /**
         * 前置增强
         * @param cls 目标类
         * @param method 目标方法
         * @param params 目标方法参数
         */
        public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
        }
        /**
         * 后置增强
         * @param cls 目标类
         * @param method 目标方法
         * @param result 目标方法返回结果
         */
        public void after(Class<?> cls, Method method, Object result) throws Throwable {
        }
    
        /**
         * 抛出增强
         * @param cls 目标类
         * @param method 目标方法
         * @param params 目标方法参数
         * @param e 异常
         * @throws Throwable
         */
        public void error(Class<?> cls, Method method, Object[] params, Exception e) throws Throwable {
        }
        /*方法结束后执行*/
        public void end(){
        }
    }
    
    /**
     * 拦截所有Controller方法
     * 这个切面写在框架里用不了,因为不会加载这个类到CLASS_SET
     */
    @Aspect(Controller.class)
    public class ControllerAspect extends AspectProxy{
        private static final Logger LOGGER = LoggerFactory.getLogger(ControllerAspect.class);
        private long begin;    //方法开始时间
    
        /**
         * 前置增强
         * @param cls    目标类
         * @param method 目标方法
         * @param params 目标方法参数
         */
        @Override
        public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
            LOGGER.debug("---------begin---------");
            LOGGER.debug(String.format("class: %s",cls.getName()));
            LOGGER.debug(String.format("method: %s",method.getName()));
            begin = System.currentTimeMillis();
        }
    
        /**
         * 后置增强
         * @param cls    目标类
         * @param method 目标方法
         * @param result 目标方法返回结果
         */
        @Override
        public void after(Class<?> cls, Method method, Object result) throws Throwable {
            LOGGER.debug(String.format("time: %ds", System.currentTimeMillis()-begin));
            LOGGER.debug("---------end---------");
        }
    }

    用到的注解

    /**
     * 切面注解
     * 用来指定切点为哪些注解
     * Controller这类注解
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Aspect {
        /*值为注解,也就是说切点为指定的注解 -  值为Controller或者Service等注解*/
        Class<? extends Annotation> value();
    }

    代理链类

    /**
     * 代理链
     */
    public class ProxyChain {
        private final Class<?> targetClass;    //代理类
        private final Object targetObject;    //目标对象
        private final Method targetMethod;    //目标方法
        private final MethodProxy methodProxy;    //代理方法 - CGLib中参数
        private final Object[] methodParams;    //方法参数
    
        private List<Proxy> proxyList = new ArrayList<Proxy>();   //代理列表 - 各种代理类 例如ControllerAspect等类
        private int proxyIndex = 0;    //代理索引
    
        public ProxyChain(Class<?> targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List<Proxy> proxyList) {
            this.targetClass = targetClass;
            this.targetObject = targetObject;
            this.targetMethod = targetMethod;
            this.methodProxy = methodProxy;
            this.methodParams = methodParams;
            this.proxyList = proxyList;
        }
    
        public Class<?> getTargetClass() {
            return targetClass;
        }
    
        public Method getTargetMethod() {
            return targetMethod;
        }
    
        public Object[] getMethodParams() {
            return methodParams;
        }
    
        /**
         * 调用代理类及目标类
         * 这个比较有意思,通过代理链的实例proxyChain不断调用此方法,每次调用都会拿出list中的一个代理执行doProxy方法(doProxy方法中再用proxyChain实例调用此方法)
         * @return 返回目标类执行的结果
         * @throws Throwable
         */
        public Object doProxyChain() throws Throwable {
            Object methodResult;
            if (proxyIndex<proxyList.size()){   //如果代理索引小于代理列表大小
                //从列表中取出Proxy对象,调用器doProxy方法
                methodResult = proxyList.get(proxyIndex++).doProxy(this);
            }else {    //所有代理遍历完后
                methodResult = methodProxy.invokeSuper(targetObject,methodParams);  //执行目标对象业务
            }
            return methodResult;
        }
    }

    代理链管理器(生成代理链)

    /**
     * 代理管理器
     */
    public class ProxyManager {
        /**
         * 根据目标类和代理列表创建一个代理链
         * @param targetClass  目标类
         * @param proxyList  代理列表
         * @param <T> 返回一个代理链执行的返回结果
         * @return
         */
        public static <T> T createProxy(final Class<T> targetClass, final List<Proxy> proxyList){
            return (T) Enhancer.create(targetClass, new MethodInterceptor() {   //方法执行时才会执行此代码块
                @Override
                public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable {
                    //每个方法执行都会执行性代理链的doProxyChain方法(这里每执行一个目标类的方法,都会new一个代理链并执行该代理链)
                    return new ProxyChain(targetClass,targetObject,targetMethod,methodProxy,methodParams,proxyList).doProxyChain();
                }
            });
        }
    }

    这里Proxy用到了模板方法模式,代理链生成及运行时CGLib起作用的精华。每运行一个方法,都会去调用代理链的doProxy方法,而代理链的doProxy方法中又会根据代理类集合的下标依次调用doProxy方法。

    Java对象转Json 

    目标Json

    var data = [
                ['2016/12/18 6:38:08', 80],
                ['2016/12/18 16:18:18', 60],
                ['2016/12/18 19:18:18', 90]
               ];

    Java实现

    List<Object[]> data = new LinkedList<Object[]>();
    //如果需要多个这样的数据
    Map<String, List> resultMap = new HashedMap();
    resultMap.put("data", data);
    Gson gson = new Gson();
    String result = gson.toJson(data);
  • 相关阅读:
    第一次使用博客,有点小激动
    oracle中的分区表基本介绍
    【转】Apache Common HttpClient使用之七种武器
    利用Iterator删除List里相近或相同的对象
    [转]给开发维护大型项目的Java开发者的建议
    JavaScript中String对象的一些方法
    [转] ORA00913: 值过多
    [转]HTTP协议详解
    DOM解析xml
    C# 中的 == 和 .Equals()
  • 原文地址:https://www.cnblogs.com/aeolian/p/10120635.html
Copyright © 2011-2022 走看看