扫描指定注解获取其相关属性

JAVA学习网 2021-01-14 16:21:01

扫描指定注解获取其相关属性

由来

      整个中台,连个权限菜单管理都没有,迁移数据 制造测试数据都要手动制造假数据存到数据库,
每次有更改还要手动改,实在是太慢了,依赖关系和外键还容易搞错,为啥不搞个菜单和权限管理呢?
项目经理说:没必要我们的菜单就这些不改,就前期加麻烦点剩了很多事,你搞个excel表格维护一下好了。。。
于是就没有了,懒嘛 不想每次都加一堆按钮 于是自定义一个 设置几个属性 
@AnnotationAction(actionValue="查询",url="api/quer/manager/details",readme="查询管理后台某数据详情") 
嗯!就这样可以根据自已的需求随意加

javaCode

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* author: 夕阳
* date: 2021/1/13
* Description: 扫描指定包下面的 所有指定的注解值
*/
@Component
public class AnnotationUtil {

    @Autowired
    private ResourceLoader resourceLoader;

    private static final String VALUE = "value";

    /**
     * 获取指定包下所有添加了执行注解的方法信息
     * @param classPath 包名
     * @param tagAnnotationClass 指定注解类型
     * @param <T>
     * @return
     * @throws Exception
     */
    public  <T> Map<String, Map<String, Object>> getAllAddTagAnnotationUrl(String classPath, Class<T> tagAnnotationClass) throws Exception {
        Map<String, Map<String, Object>> resMap = new HashMap<>();
        ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
        MetadataReaderFactory metaReader = new CachingMetadataReaderFactory(resourceLoader);
        Resource[] resources = resolver.getResources(classPath);

        for (Resource r : resources) {
            MetadataReader reader = metaReader.getMetadataReader(r);
            resMap = resolveClass(reader, resMap, tagAnnotationClass);
        }


        return resMap;
    }

    private <T> Map<String, Map<String, Object>> resolveClass(
            MetadataReader reader, Map<String, Map<String, Object>> resMap, Class<T> tagAnnotationClass)
            throws Exception {
        String tagAnnotationClassCanonicalName = tagAnnotationClass.getCanonicalName();
        //获取注解元数据
        AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
        //获取类中RequestMapping注解的属性
        Map<String, Object> annotationAttributes =
                annotationMetadata.getAnnotationAttributes(RequestMapping.class.getCanonicalName());

        //若类无RequestMapping注解
        if (annotationAttributes == null){ return resMap;}

        //获取RequestMapping注解的value
        String[] pathParents = (String[]) annotationAttributes.get(VALUE);
        if (0 == pathParents.length){ return resMap;}

        //获取RequestMapping注解的value
        String pathParent = pathParents[0];

        //获取当前类中已添加要扫描注解的方法
        Set<MethodMetadata> annotatedMethods = annotationMetadata.getAnnotatedMethods(tagAnnotationClassCanonicalName);

        for (MethodMetadata annotatedMethod : annotatedMethods) {
            //获取当前方法中要扫描注解的属性
            Map<String, Object> targetAttr = annotatedMethod.getAnnotationAttributes(tagAnnotationClassCanonicalName);
            //获取当前方法中要xxxMapping注解的属性
            Map<String, Object> mappingAttr = getPathByMethod(annotatedMethod);
            if (mappingAttr == null){
                continue;
            }

            String[] childPath = (String[]) mappingAttr.get(VALUE);
            if (targetAttr == null || childPath == null || childPath.length == 0) {
                continue;
            }
            // 组装路径
            String assembledToBePathStr =pathParent.replace("/"," ")+" "+ childPath[0].replace("/"," ");
            String finalPath = assembledToBePathStr.replaceAll("\\s+","/");
            boolean isHas = resMap.containsKey(finalPath);
            if (isHas){
                throw new Exception("重复定义了相同的映射关系");
            }

            resMap.put(finalPath, targetAttr);
        }

        return resMap;
    }

    private Map<String, Object> getPathByMethod(MethodMetadata annotatedMethod) {
        Map<String, Object> annotationAttributes = annotatedMethod.getAnnotationAttributes(GetMapping.class.getCanonicalName());
        if (annotationAttributes != null && annotationAttributes.get(VALUE) != null) {
            return annotationAttributes;
        }
        annotationAttributes = annotatedMethod.getAnnotationAttributes(PostMapping.class.getCanonicalName());
        if (annotationAttributes != null && annotationAttributes.get(VALUE) != null) {
            return annotationAttributes;
        }

        annotationAttributes = annotatedMethod.getAnnotationAttributes(DeleteMapping.class.getCanonicalName());
        if (annotationAttributes != null && annotationAttributes.get(VALUE) != null) {
            return annotationAttributes;
        }

        annotationAttributes = annotatedMethod.getAnnotationAttributes(PutMapping.class.getCanonicalName());
        if (annotationAttributes != null && annotationAttributes.get(VALUE) != null) {
            return annotationAttributes;
        }
        annotationAttributes = annotatedMethod.getAnnotationAttributes(RequestMapping.class.getCanonicalName());
        return annotationAttributes;
    }
}

使用示例

     
    @Test
    public void test(){
            // 省略部分代码 。。。
        AnnotationUtil annotationUtil = new AnnotationUtil();
        try {
            Map<String, Map<String,Object>> all = annotationUtil.getAllAddTagAnnotationUrl("classpath*:vip/setsun/controller/**/*.class", AnnotationAction.class);
            all.forEach((k,v)->{
            // 这里的v 就是注解里面的定义的属性  
                System.out.println(k+" :  "+ v.get("actionValue"));
            });
            // 拿到之后就可以做入库操作和其他的操作 
            //。。。 此处省略业务的代码。。。
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

  • 每日一夸:在这个星球上,你很重要,请珍惜你的可贵

聊点其他的,最近准备搞一下es 产品,不知道做点啥 比如 图搜 ,也没个小目标不知道写点啥。前段时间写了一个资源监控中台,有兴趣就写写总结分享一下难点(提不起来兴趣)
es 准备学习以下知识点

  • ES CURD
  • ES 索引优化
  • ES 分页查询
  • ES 多shard 查询优化
  • ES 针对TB级数据处理和查询优化(这个是总结之前做的EB级图搜优化,和服务器方面的优化设置以及相应的配置文件修改,准备入手总结时间暂定)
  • ES 集群健康方面的查询操作
阅读(718) 评论(0)