| package com.zt.core.db.annotation; | 
|   | 
| import cn.hutool.core.collection.CollectionUtil; | 
| import cn.hutool.core.exceptions.UtilException; | 
| import cn.hutool.core.util.ReflectUtil; | 
| import com.google.common.base.Predicates; | 
| import com.zt.common.annotation.DataFilter; | 
| import com.zt.common.annotation.DataFilters; | 
| import com.zt.common.constant.Constant; | 
| import com.zt.common.utils.SpringContextUtils; | 
| import com.zt.core.db.model.DataFilterField; | 
| import com.zt.core.db.model.DataFilterMethod; | 
| import io.swagger.annotations.Api; | 
| import io.swagger.annotations.ApiOperation; | 
| import org.apache.commons.lang3.StringUtils; | 
| 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 springfox.documentation.builders.RequestHandlerSelectors; | 
| import springfox.documentation.spi.service.contexts.ApiSelector; | 
| import springfox.documentation.spring.web.plugins.Docket; | 
|   | 
| import java.util.*; | 
|   | 
| @Component("dataFilterParser") | 
| public class DataFilterParser { | 
|   | 
|     @Autowired | 
|     private ResourceLoader resourceLoader; | 
|   | 
|     private static final String VALUE = "value"; | 
|   | 
|     /** | 
|      * 获取指定包下所有添加了执行注解的方法信息 | 
|      * | 
|      * @return | 
|      * @throws Exception | 
|      */ | 
|     public List<DataFilterMethod> getFilteredMethods() throws Exception { | 
|         List<DataFilterMethod> methods = new ArrayList<>(); | 
|   | 
|         ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader); | 
|         MetadataReaderFactory metaReader = new CachingMetadataReaderFactory(resourceLoader); | 
|         Resource[] resources = resolver.getResources("classpath*:com/zt/**/*.class"); | 
|   | 
|         for (org.springframework.core.io.Resource r : resources) { | 
|             MetadataReader reader = metaReader.getMetadataReader(r); | 
|             methods.addAll(resolveClass(reader)); | 
|         } | 
|         Map<String, String> docetGroupMap = new HashMap<>(); | 
|         try { | 
|             Map<String, Docket> docketMap = SpringContextUtils.getImplInstance(Docket.class); | 
|             for (Docket docket : docketMap.values()) { | 
|                 ApiSelector apiSelector = (ApiSelector) ReflectUtil.getFieldValue(docket, "apiSelector"); | 
|                 List component1s = (List) ReflectUtil.getFieldValue(apiSelector.getRequestHandlerSelector(), | 
|                         "components"); | 
|                 for (Object component1 : component1s) { | 
|                     if (component1.getClass().getName().startsWith(Predicates.class.getName())) { | 
|                         List component2s = (List) ReflectUtil.getFieldValue(component1, "components"); | 
|                         for (Object component2 : component2s) { | 
|                             if (component2.getClass().getName().startsWith(RequestHandlerSelectors.class.getName())) { | 
|                                 Object[] values = ReflectUtil.getFieldsValue(component2); | 
|                                 if (values != null && values.length == 1) { | 
|                                     docetGroupMap.put((String) values[0], docket.getGroupName()); | 
|                                 } | 
|                             } | 
|                         } | 
|                     } | 
|                 } | 
|             } | 
|         } catch (UtilException e) { | 
|             e.printStackTrace(); | 
|         } | 
|         for (DataFilterMethod method : methods) { | 
|             for (String classPath : docetGroupMap.keySet()) { | 
|                 if (method.getClassPath().startsWith(classPath)) { | 
|                     method.setSwagger(docetGroupMap.get(classPath)); | 
|                     break; | 
|                 } | 
|             } | 
|         } | 
|   | 
|         return methods; | 
|     } | 
|   | 
|     private List<DataFilterMethod> resolveClass(MetadataReader reader) { | 
|         List<DataFilterMethod> methods = new ArrayList<>(); | 
|         // 获取注解元数据 | 
|         AnnotationMetadata metadata = reader.getAnnotationMetadata(); | 
|         // 获取类中RequestMapping注解的value属性 | 
|         String classMapping = getAttr(metadata.getAnnotationAttributes(RequestMapping.class.getCanonicalName()), VALUE); | 
|         if (classMapping == null) { | 
|             return methods; | 
|         } | 
|         // 获取DataFilters和单独DataFilter注解的方法 | 
|         Set<MethodMetadata> methodMetadatas = new HashSet<>(); | 
|         methodMetadatas.addAll(metadata.getAnnotatedMethods(DataFilters.class.getCanonicalName())); | 
|         methodMetadatas.addAll(metadata.getAnnotatedMethods(DataFilter.class.getCanonicalName())); | 
|   | 
|         if (CollectionUtil.isNotEmpty(methodMetadatas)) { | 
|             // 获取类中Api注解的tags属性 | 
|             Map<String, Object> apiAttributes = metadata.getAnnotationAttributes(Api.class.getCanonicalName()); | 
|             String apiTags = this.getAttr(apiAttributes, "tags"); | 
|   | 
|             for (MethodMetadata annotatedMethod : methodMetadatas) { | 
|                 // 获取方法的mapping | 
|                 String methodMapping = getAttr( | 
|                         annotatedMethod.getAnnotationAttributes(GetMapping.class.getCanonicalName()), VALUE); | 
|                 if (StringUtils.isBlank(methodMapping)) { | 
|                     continue; | 
|                 } | 
|                 String url = classMapping + "/" + methodMapping; | 
|   | 
|                 String methodName = getAttr( | 
|                         annotatedMethod.getAnnotationAttributes(ApiOperation.class.getCanonicalName()), VALUE); | 
|   | 
|                 DataFilterMethod method = new DataFilterMethod(metadata.getClassName(), url, "", apiTags, methodName); | 
|   | 
|                 Map<String, Object> dataFilterAttributes = annotatedMethod.getAnnotationAttributes(DataFilter.class | 
|                         .getCanonicalName()); | 
|                 if (dataFilterAttributes != null) {// DataFilter注解 | 
|                     method.addField(this.getField(dataFilterAttributes)); | 
|                 } else {// DataFilters注解 | 
|                     Map<String, Object> dataFiltersAttributes = annotatedMethod | 
|                             .getAnnotationAttributes(DataFilters.class.getCanonicalName()); | 
|                     if (dataFiltersAttributes != null) { | 
|                         Map<String, Object>[] dataFilterArray = (Map<String, Object>[]) dataFiltersAttributes | 
|                                 .get(VALUE); | 
|                         for (Map<String, Object> attributes : dataFilterArray) { | 
|                             method.addField(this.getField(attributes)); | 
|                         } | 
|                     } | 
|                 } | 
|   | 
|                 methods.add(method); | 
|             } | 
|   | 
|         } | 
|   | 
|         return methods; | 
|     } | 
|   | 
|     private DataFilterField getField(Map<String, Object> attributes) { | 
|         String field = getAttr(attributes, "field"), name = getAttr(attributes, "name"); | 
|         if (Constant.Field.TENANT.equals(field)) { | 
|             name = "租户"; | 
|         } else if (Constant.Field.COMPANY.equals(field)) { | 
|             name = "公司"; | 
|         } else if (Constant.Field.DEPT.equals(field)) { | 
|             name = "部门"; | 
|         } | 
|         return new DataFilterField(name, field, getAttr(attributes, "accept"), getAttr(attributes, "dict"), getAttr( | 
|                 attributes, "op"), getAttr(attributes, "defaul")); | 
|     } | 
|   | 
|     /** | 
|      * 获取注解的属性 | 
|      * | 
|      * @param attributes | 
|      * @param key | 
|      * @return | 
|      */ | 
|     private String getAttr(Map<String, Object> attributes, String key) { | 
|         // 若类无注解 | 
|         if (attributes == null || attributes.get(key) == null) { | 
|             return null; | 
|         } | 
|         // 获取注解的属性值 | 
|         Object value = attributes.get(key); | 
|         if (value instanceof String) { | 
|             return (String) value; | 
|         } else if (value instanceof String[]) { | 
|             String[] values = (String[]) attributes.get(key); | 
|             if (0 == values.length) { | 
|                 return null; | 
|             } | 
|             return values[0]; | 
|         } | 
|         return null; | 
|     } | 
|   | 
|     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; | 
|     } | 
| } |