• SpringBoot通过注解获取接口信息


    TOC

    SpringBoot通过注解获取接口信息

    获取Spring框架的ApplicationContext

    需要修改Application主类

    @ComponentScan(basePackages = "com.example.demo.**.**")
    @SpringBootApplication
    public class DemoApplication implements CommandLineRunner, ApplicationContextAware {//实现接口 CommandLineRunner, ApplicationContextAware
    
        /**
         * 获取Spring框架的上下文
         */
        private ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext arg0) {
            this.applicationContext = arg0;
        }
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
    
        }
    
        /**
         * 调用 applicationContext(不能在main中使用,main是static的,不能调用)
         * @param args
         */
        @Override
        public void run(String... args) {
            //在这里可以调用applicationContext了
            Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RequestMapping.class);
        }
    }
    

    相关的方法

    • getBeansWithAnnotation(注解的class) 获取spring中拥有这个注解的所有类

      定义:Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;

    比如,通过上面的applicationContext,获取项目中所有的RestController

    //获取使用RestController注解的所有类
    Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RestController.class);
    • 根据对象获取class:AopUtils.getTargetClass(Object对象)

    上面获取的是Map 的对象,获取每一个map对应的class;

    获取了class,就可以使用反射的方法了,比如

    getDeclaredMethods:获取当前类的所有方法(包括public、private、protected、默认)

    getMethods:获取当前类和父类的所有的public方法

    for (Map.Entry<String, Object> entry : controllers.entrySet()) {//遍历每个controller层
         //   entry.getValue() 获取的是 Object对象
        AopUtils.getTargetClass(entry.getValue())
    }  
    • 判断一个class/方法中有没有这个注解isAnnotationPresent

      定义:public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

    判断的是class的注解,所以需要使用上面的AopUtils.getTargetClass(Object对象)获取到class

    AopUtils.getTargetClass(entry.getValue()).isAnnotationPresent(RequestMapping.class) //判断这个class中有没有RequestMapping这个注解
    • 获取一个class/方法的某个注解的对象信息getAnnotationgetDeclaredAnnotation

      getAnnotation返回的是"直接修饰"注解和继承的注解的合集,不包括容器注解里包含的注解;

      getDeclaredAnnotation仅仅返回"直接修饰"注解。

    RequestMapping annotation = AopUtils.getTargetClass(entry.getValue()).getAnnotation(RequestMapping.class);
    或
    RequestMapping methodAnno = method.getDeclaredAnnotation(RequestMapping.class);

    案例

    案例1 :项目启动,获取controller层的接口

    • controller
    @RestController
    @RequestMapping(name = "demo1con",value = {"/demo/demo1","/url111"})
    public class Demo1Controller {
    
        @RequestMapping(name = "方法1",value = "/m1")
        public String testDemo1(){
            return "";
        }
    }
    
    • 主类设置
    @ComponentScan(basePackages = "com.example.demo.**.**")
    @SpringBootApplication
    public class DemoApplication implements CommandLineRunner, ApplicationContextAware {//实现接口 CommandLineRunner, ApplicationContextAware
    
        /**
         * 获取Spring框架的上下文
         */
        private ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext arg0) {
            this.applicationContext = arg0;
        }
    
        public static void main(String[] args) {
    //        SpringApplication app = new SpringApplication(DemoApplication.class);
    //        //程序部署在linux环境,若需要配置成系统服务,使用systemctl(CentOS7系统服务命令)进行程序的启动、停止、重启等操作,则需要在程序启动后,生成一个pid文件,其内容则是该进程的pid。
    //        //SpringBoot已经提供了pid文件的生成方式,只需要做简单的配置即可。
    //        //配置文件application.properties文件内容如下,该配置指定了pid文件的位置: 比如 spring.pid.file=/xxx/syb.pid
    //        app.addListeners(new ApplicationPidFileWriter());
    //        app.run(args);
    
            SpringApplication.run(DemoApplication.class, args);
    
        }
    
        /**
         * 调用 applicationContext(不能在main中使用,main是static的,不能调用)
         * @param args
         */
        @Override
        public void run(String... args) {
            //获取使用RestController注解的所有controller层类
            Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RestController.class);//获取到 demo1Controller -> {Demo1Controller@5595}
            for (Map.Entry<String, Object> entry : controllers.entrySet()) {//遍历每个controller层
                System.out.println(entry.getKey());//demo1Controller
                Object value = entry.getValue();
                Class<?> aClass = AopUtils.getTargetClass(value);//获取class
                System.out.println(aClass.isAnnotationPresent(RequestMapping.class));//true
                RequestMapping annotation = aClass.getAnnotation(RequestMapping.class);//获取注解详情
                RequestMapping declaredAnnotation = aClass.getDeclaredAnnotation(RequestMapping.class);
                //注解的详情可以直接调用了
                System.out.println(JSON.toJSONString(annotation));//{"path":[],"headers":[],"method":[],"name":"demo1con","produces":[],"params":[],"value":["/demo/demo1","/url111"],"consumes":[]}
                List<Method> methods = Arrays.asList(aClass.getMethods());//获取方法
                List<Method> declaredMethods = Arrays.asList(aClass.getDeclaredMethods());//获取方法
                System.out.println(declaredMethods.get(0).isAnnotationPresent(RequestMapping.class));//判断这个方法有没有这个注解
                RequestMapping annotation1 = declaredMethods.get(0).getAnnotation(RequestMapping.class);//获取方法的注解
                RequestMapping annotation2 = declaredMethods.get(0).getDeclaredAnnotation(RequestMapping.class);
                System.out.println(JSON.toJSONString(annotation1));//{"path":[],"headers":[],"method":[],"name":"方法1","produces":[],"params":[],"value":["/m1"],"consumes":[]}
            }
        }
    }
    

    案例2:项目启动,接口写入数据库

    项目启动的时候,检测所有的controller层,将接口信息写入数据库

    接口

    public class DemoApplication implements CommandLineRunner, ApplicationContextAware {//1.实现了接口CommandLineRunner, ApplicationContextAware
    
        /**
         * 2.获取Spring框架的上下文
         */
        private ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext arg0) {
            this.applicationContext = arg0;
        }
    
        /**
        后台接口自动导入
        */
        @Autowired
        private BackApiAutoImportInter backApiAutoImportInter;
    
        public static void main(String[] args) {
            SpringApplication app = new SpringApplication(DemoApplication.class);
            app.addListeners(new ApplicationPidFileWriter());
            app.run(args);
        }
    
        @Override
        public void run(String... args) {
            try {
                if (backApiAutoImportInter != null) {
                    backApiAutoImportInter.setApplicationContext(applicationContext);
                    backApiAutoImportInter.setIsLocal(false);
                    backApiAutoImportInter.setIsOpen(false);
    
                    backApiAutoImportInter.run(BackApiDataSource.UCENTER);
                } else {
                    log.error("backApiAutoImportInter is empty", "backApiAutoImportInter inject failed");
                }
            } catch (Exception ex) {
                log.error("error:", ex);
            }
        }
    
    }
    

    监听后台接口

    项目启动的时候,自动识别项目的所有接口

    • 接口层
    /**
    * 后台接口自动导入
    *
    * @author huangyutao
    * @date 2019-08-16 10:13:54
    */
    public interface BackApiAutoImportInter {
    
        /**
         * 上下文赋值
            *
         * @param applicationContext 参数
         * @return
         * @author huangyutao
         * @date 2019-08-16 10:34:35
            */
          void setApplicationContext(ApplicationContext applicationContext);
    
        /**
         * 本地录入标识
            *
         * @param isLocal 参数
         * @return
         * @author huangyutao
         * @date 2019-09-05 18:01:24
            */
          void setIsLocal(boolean isLocal);
    
        /**
         * 开放标识
            *
         * @param isOpen 参数
         * @return
         * @author huangyutao
         * @date 2019-09-18 11:09:36
            */
          void setIsOpen(boolean isOpen);
    
        /**
         * 执行导入(用户中心中url以"/back/"开头的接口不录入数据库)
            *
         * @param dataSource 数据来源
         * @return
         * @author huangyutao
         * @date 2019-08-20 10:13:28
            */
          void run(String dataSource);
    
    }
    • 实现层
    package net.cc.ucenter.modules.backapi.service;
    
    import com.alibaba.fastjson.JSON;
    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import net.cc.commons.IdGen;
    import net.cc.commons.annotation.User;
    import net.cc.commons.web.base.BaseHttpResult;
    import net.cc.ucenter.modules.backapi.dto.BackApiAnnoDTO;
    import net.cc.ucenter.modules.backapi.entity.BackApiInfo;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.aop.support.AopUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.SpringApplication;
    import org.springframework.context.ApplicationContext;
    import org.springframework.stereotype.Service;
    import org.springframework.web.bind.annotation.*;
    
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.*;
    import java.util.stream.Collectors;
    
    /**
    * 后台接口自动导入--将项目中的controller接口写入数据库
    */
    @Slf4j
    @Service
    public class BackApiAutoImportImpl implements BackApiAutoImportInter {
    
        @Autowired
        private BackApiInfoService backApiInfoService;
    
        /**Spring框架的上下文*/
        private ApplicationContext applicationContext;
        /**本地录入标识*/
        private boolean isLocal;
        /**开放标识*/
        private boolean isOpen;
    
        /**
         * 上下文赋值
         */
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }
    
        /**
         * 本地录入标识
         */
        @Override
        public void setIsLocal(boolean isLocal) {
            this.isLocal = isLocal;
        }
    
        /**
         * 开放标识
         */
        @Override
        public void setIsOpen(boolean isOpen) {
            this.isOpen = isOpen;
        }
    
        /**
         * 执行导入(用户中心中url以"/back/"开头的接口不录入数据库)
         */
        @Override
        public void run(String dataSource) {
            List<String> invalidControllers = new ArrayList<>();//没有注解RequestMapping或RequestMapping注解没有设置name的所有的类的集合
            List<String> invalidMethods = new ArrayList<>();
            List<String> invalidMethodAnnos = new ArrayList<>();
            List<BackApiInfo> insertParams = new ArrayList<>();
            List<BackApiInfo> updateParams = new ArrayList<>();
            // 获取数据库中的接口
            BackApiInfo backApiInfoParam = new BackApiInfo();
            backApiInfoParam.setDataSource(dataSource);
            List<BackApiInfo> backApiInfos = backApiInfoService.findList(backApiInfoParam);//查询当前数据库汇总记录的所有的接口
            // 获取代码中所有的controller
            Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RestController.class);//获取使用RestController注解的所有controller层类
            // 加工数据
            List<String> apiUrls = backApiInfos.stream().map(p -> p.getApiUrl()).collect(Collectors.toList());//获取数据库中所有的接口的路由url
            for (Map.Entry<String, Object> entry : controllers.entrySet()) {//遍历每个controller层
                //AopUtils.getTargetClass(entry.getValue())  获取controller的真实的class 比如  com.demo1.controller.Demo1Controller
                //isAnnotationPresent 判断class的类注解中有没有这个注解
                //此处为判断这个controller类有没有RequestMapping注解(否则是普通的方法)
                if (!AopUtils.getTargetClass(entry.getValue()).isAnnotationPresent(RequestMapping.class)
                        //getAnnotation 返回这个class的这个注解的所有信息
                        //此处判断的是,给这个controller类设置了name
                        || StringUtils.isBlank(AopUtils.getTargetClass(entry.getValue()).getAnnotation(RequestMapping.class).name())) {
                    invalidControllers.add(entry.getKey());
                } else {
                    RequestMapping controllerAnno = AopUtils.getTargetClass(entry.getValue()).getAnnotation(RequestMapping.class);//获取这个controller的RequestMapping注解的信息
                    for (String controllerUrl : controllerAnno.value()) {//遍历controller的接口(value是数组,一个RequestMapping可以设置多个url)
                        // 过滤/back/开头的接口
                        if (StringUtils.isNotBlank(controllerUrl) && !procPath(controllerUrl).toLowerCase().startsWith("/back/")) {
                            List<String> methodUrls = new ArrayList<>();//这个类的所有的url接口
                            List<Method> methods = Arrays.stream(AopUtils.getTargetClass(entry.getValue()).getDeclaredMethods())//获取本类的所有的方法(包括public、private、protected、默认)
                                    .filter(p -> Modifier.isPublic(p.getModifiers()))//过滤掉public的
                                    .collect(Collectors.toList());
                            for (Method method : methods) {
                                //若是这个方法没有RequestMapping及相关注解,或者注解没有设置name值
                                if ((!method.isAnnotationPresent(RequestMapping.class) || StringUtils.isBlank(method.getDeclaredAnnotation(RequestMapping.class).name()))
                                        && (!method.isAnnotationPresent(GetMapping.class) || StringUtils.isBlank(method.getDeclaredAnnotation(GetMapping.class).name()))
                                        && (!method.isAnnotationPresent(PostMapping.class) || StringUtils.isBlank(method.getDeclaredAnnotation(PostMapping.class).name()))
                                        && (!method.isAnnotationPresent(PutMapping.class) || StringUtils.isBlank(method.getDeclaredAnnotation(PutMapping.class).name()))
                                        && (!method.isAnnotationPresent(DeleteMapping.class) || StringUtils.isBlank(method.getDeclaredAnnotation(DeleteMapping.class).name()))
                                        && (!method.isAnnotationPresent(PatchMapping.class) || StringUtils.isBlank(method.getDeclaredAnnotation(PatchMapping.class).name()))
                                ) {
                                    invalidMethods.add(method.getDeclaringClass().getName() + "." + method.getName());//不需要解析的方法
                                } else {
                                    List<BackApiAnnoDTO> backApiAnnoDTOS = getAnnos(method);
                                    if (CollectionUtils.isNotEmpty(backApiAnnoDTOS)) {
                                        methodUrls.addAll(backApiAnnoDTOS.stream()
                                                .map(p -> p.getValue())
                                                .collect(Collectors.toList()));
                                    }
                                }
                            }
                            List<String> dupliUrls = getDuplicateElements(methodUrls);//获取url重复的元素列表
                            if (CollectionUtils.isNotEmpty(dupliUrls)) {
                                invalidMethodAnnos.addAll(dupliUrls.stream()
                                        .map(p -> "url:"" + p + ""[" + AopUtils.getTargetClass(entry.getValue()).getName() + "]")
                                        .collect(Collectors.toList()));//记录重复的url
                            }
                            for (Method method : methods) {
                                if (method.isAnnotationPresent(RequestMapping.class)
                                        || method.isAnnotationPresent(GetMapping.class)
                                        || method.isAnnotationPresent(PostMapping.class)
                                        || method.isAnnotationPresent(PutMapping.class)
                                        || method.isAnnotationPresent(DeleteMapping.class)
                                        || method.isAnnotationPresent(PatchMapping.class)
                                ) {//若是这个方法有接口的注解
                                    List<BackApiAnnoDTO> backApiAnnoDTOS = getAnnos(method);//获取所有的接口信息
                                    if (CollectionUtils.isNotEmpty(backApiAnnoDTOS)) {
                                        backApiAnnoDTOS.forEach(backApiAnnoDTO -> {
                                            if (!dupliUrls.contains(backApiAnnoDTO.getValue())) {//不是重复的url(spring不允许重复的url,有重复的就该报异常了)
                                                String apiUrl = new StringBuilder() //拼接controller和方法的url
                                                        .append(procPath(controllerUrl))
                                                        .append(procPath(backApiAnnoDTO.getValue()))
                                                        .toString();
                                                if (StringUtils.isNotBlank(apiUrl)) {
                                                    if (!apiUrls.contains(apiUrl)) {//数据库在中不存在这个url
                                                        BackApiInfo backApiInfo = new BackApiInfo();
                                                        backApiInfo.setApiId(IdGen.snowflakeId());
                                                        try {
                                                            Thread.sleep(5);
                                                        } catch (Exception ex) {
                                                            throw new RuntimeException(ex);
                                                        }
                                                        backApiInfo.setApiName(backApiAnnoDTO.getName());
                                                        backApiInfo.setApiUrl(apiUrl);
                                                        backApiInfo.setModuleName(controllerAnno.name());
                                                        backApiInfo.setDataSource(dataSource);
                                                        backApiInfo.setIsOpen(isOpen ? "1" : "0");
                                                        backApiInfo.setIsCheckToken(method.isAnnotationPresent(User.class) ?
                                                                "1" : "0");//是否需要登录
                                                        backApiInfo.setIsUse("1");
                                                        backApiInfo.setIsSync("1");
                                                        backApiInfo.setCreateBy(-1L);
                                                        backApiInfo.setRemarks("system");
                                                        insertParams.add(backApiInfo); //记录为插入的url
                                                    } else {
                                                        // delete from apiUrls
                                                        apiUrls.remove(apiUrl);
                                                        // update 数据库中已经存在这个url了,那就更新这个接口的信息
                                                        BackApiInfo backApiInfo = backApiInfos.stream() //获取数据库中的信息
                                                                .filter(p -> p.getApiUrl().equals(apiUrl))
                                                                .findFirst().orElse(null);
                                                        if (backApiInfo.getIsSync().equals("1")) {
                                                            if (!backApiInfo.getApiName().equals(backApiAnnoDTO.getName())
                                                                    || !backApiInfo.getModuleName().equals(controllerAnno.name())
                                                                    || !backApiInfo.getIsCheckToken().equals(
                                                                    method.isAnnotationPresent(User.class) ? "1" : "0")) {
                                                                backApiInfo.setApiName(backApiAnnoDTO.getName());
                                                                backApiInfo.setModuleName(controllerAnno.name());
                                                                backApiInfo.setIsCheckToken(method.isAnnotationPresent(User.class) ?
                                                                        "1" : "0");
                                                                updateParams.add(backApiInfo);//记录为更新的url
                                                            } else {
                                                                // nothing to update
                                                            }
                                                        } else {
                                                            // no sync
                                                        }
                                                    }
                                                }
                                            }
                                        });
                                    }
                                }
                            }
                        } else {
                            // controller value is empty
                        }
                    }
                }
            }
            Map<String, List<Object>> data = new HashMap<>(8);
            data.put("invalidControllers", invalidControllers.stream().map(p -> (Object) p).collect(Collectors.toList()));
            data.put("invalidMethods", invalidMethods.stream().map(p -> (Object) p).collect(Collectors.toList()));
            data.put("invalidMethodAnnos", invalidMethodAnnos.stream().map(p -> (Object) p).collect(Collectors.toList()));
            data.put("insertParams", insertParams.stream().map(p -> (Object) p).collect(Collectors.toList()));
            data.put("updateParams", updateParams.stream().map(p -> (Object) p).collect(Collectors.toList()));
            data.put("deleteParams", apiUrls.stream().map(p -> (Object) p).collect(Collectors.toList()));
            BaseHttpResult<Map<String, List<String>>> result = backApiInfoService.proceedData(data
                    , applicationContext.getEnvironment().getActiveProfiles()[0], isLocal);//applicationContext.getEnvironment().getActiveProfiles()[0] 是启动环境,是application的-之后的环境.
            if (!result.isSuccess()) {
                Map<String, List<String>> resultData = result.getData();
                resultData.forEach((key, value) -> log.error(key + "{}", JSON.toJSONString(value)));
                SpringApplication.exit(applicationContext);
            }
        }
    
        /**
         * 获取注解信息列表
         *
         * @param method 方法
         * @return
         * @author huangyutao
         * @date 2019-08-15 17:26:35
         */
        private List<BackApiAnnoDTO> getAnnos(Method method) {
            List<BackApiAnnoDTO> backApiAnnoDTOs = new ArrayList<>();
            String name = "";
            List<String> values = new ArrayList<>();
            if (method.isAnnotationPresent(RequestMapping.class)) {//判断方法有没有这个注解
                RequestMapping methodAnno = method.getDeclaredAnnotation(RequestMapping.class);
                name = methodAnno.name();//获取方法名
                values = Arrays.asList(methodAnno.value());//获取这个方法的所有的路由url
            } else if (method.isAnnotationPresent(GetMapping.class)) {
                GetMapping methodAnno = method.getDeclaredAnnotation(GetMapping.class);
                name = methodAnno.name();
                values = Arrays.asList(methodAnno.value());
            } else if (method.isAnnotationPresent(PostMapping.class)) {
                PostMapping methodAnno = method.getDeclaredAnnotation(PostMapping.class);
                name = methodAnno.name();
                values = Arrays.asList(methodAnno.value());
            } else if (method.isAnnotationPresent(PutMapping.class)) {
                PutMapping methodAnno = method.getDeclaredAnnotation(PutMapping.class);
                name = methodAnno.name();
                values = Arrays.asList(methodAnno.value());
            } else if (method.isAnnotationPresent(DeleteMapping.class)) {
                DeleteMapping methodAnno = method.getDeclaredAnnotation(DeleteMapping.class);
                name = methodAnno.name();
                values = Arrays.asList(methodAnno.value());
            } else if (method.isAnnotationPresent(PatchMapping.class)) {
                PatchMapping methodAnno = method.getDeclaredAnnotation(PatchMapping.class);
                name = methodAnno.name();
                values = Arrays.asList(methodAnno.value());
            }
            for (String value : values) {//遍历每一个路由,创建详情
                BackApiAnnoDTO backApiAnnoDTO = new BackApiAnnoDTO();
                backApiAnnoDTO.setName(name);
                backApiAnnoDTO.setValue(value);
                backApiAnnoDTOs.add(backApiAnnoDTO);
            }
            return backApiAnnoDTOs;
        }
    
        /**
         * 处理path
         *
         * @param path path
         * @return path
         * @author huangyutao
         * @date 2019-08-12 11:22:59
         */
        private String procPath(String path) {
            path = path.trim();
            if (!path.startsWith("/")) {
                path = "/" + path;
            }
            while (path.endsWith("/")) {
                path = path.substring(0, path.length() - 1);
            }
            return path;
        }
    
        /**
         * 获取重复的元素列表
         *
         * @param list 数据源
         * @return
         * @author huangyutao
         * @date 2019-08-19 10:59:29
         */
        private <T> List<T> getDuplicateElements(List<T> list) {
            return list.stream()
                    // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
                    .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
                    // 所有 entry 对应的 Stream
                    .entrySet().stream()
                    // 过滤出元素出现次数大于 1 的 entry
                    .filter(entry -> entry.getValue() > 1)
                    // 获得 entry 的键(重复元素)对应的 Stream
                    .map(entry -> entry.getKey())
                    .collect(Collectors.toList());
        }
    
    }
    

    backApiInfoService

        /**
         * 处理数据
         *
         * @param data    参数
         * @param profile 启动配置文件
         * @param isLocal profile=local时是否同步数据
         * @return
         * @author huangyutao
         * @date 2019-09-05 10:14:03
         */
        @Transactional(rollbackFor = Exception.class, readOnly = false)
        public BaseHttpResult<Map<String, List<String>>> proceedData(Map<String, List<Object>> data
                , String profile, Boolean isLocal) {
            // 从参数中抽离数据
            List<String> invalidControllers = data.get("invalidControllers").stream()
                    .map(p -> objectMapper.convertValue(p, String.class)).collect(Collectors.toList());
            List<String> invalidMethods = data.get("invalidMethods").stream()
                    .map(p -> objectMapper.convertValue(p, String.class)).collect(Collectors.toList());
            List<String> invalidMethodAnnos = data.get("invalidMethodAnnos").stream()
                    .map(p -> objectMapper.convertValue(p, String.class)).collect(Collectors.toList());
            List<BackApiInfo> insertParams = data.get("insertParams").stream()
                    .map(p -> objectMapper.convertValue(p, BackApiInfo.class)).collect(Collectors.toList());
            List<BackApiInfo> updateParams = data.get("updateParams").stream()
                    .map(p -> objectMapper.convertValue(p, BackApiInfo.class)).collect(Collectors.toList());
            List<String> deleteParams = data.get("deleteParams").stream()
                    .map(p -> objectMapper.convertValue(p, String.class)).collect(Collectors.toList());
    
            Map<String, List<String>> resultData = new HashMap<>(3);
            if (CollectionUtils.isNotEmpty(invalidControllers)) {
                resultData.put("controllers missing anno: ", invalidControllers);
            }
            if (CollectionUtils.isNotEmpty(invalidMethods)) {
                resultData.put("methods missing anno: ", invalidMethods);
            }
            if (CollectionUtils.isNotEmpty(invalidMethodAnnos)) {
                resultData.put("methods duplicate anno: ", invalidMethodAnnos);
            }
            if (MapUtils.isEmpty(resultData)) {
                // 数据操作
                List<SysParameterInfo> sysParameterInfos = SysParamUtils.getSysParamList("BackApiIgnoreUrl");
                if (CollectionUtils.isNotEmpty(sysParameterInfos) && CollectionUtils.isNotEmpty(insertParams)) {
                    List<String> ignoreUrls = sysParameterInfos.stream()
                            .map(p -> p.getParameterKey())
                            .collect(Collectors.toList());
                    // 去掉忽略的
                    insertParams = insertParams.stream()
                            .filter(p -> !ignoreUrls.contains(p.getApiUrl()))
                            .collect(Collectors.toList());
                }
                switch (profile) {
                    case ProfileType.LOCAL:
                        if (isLocal) {
                            if (CollectionUtils.isNotEmpty(insertParams)) {
                                dao.insertBatch(insertParams);
                            }
                            if (CollectionUtils.isNotEmpty(updateParams)) {
                                dao.updateBatch(updateParams);
                            }
                            if (CollectionUtils.isNotEmpty(deleteParams)) {
                                List<BackApiInfo> backApiInfos = dao.selectBatch(deleteParams);
                                // 删除后台接口信息
                                dao.deleteBatch(deleteParams);
                                // 删除关联关系
                                backApiInFuncDao.deleteBatch(backApiInfos.stream().map(p -> p.getApiId())
                                        .collect(Collectors.toList()));
                            }
                        }
                        break;
                    case ProfileType.TEST:
                    case ProfileType.TEST_STABLE:
                        if (CollectionUtils.isNotEmpty(insertParams)) {
                            dao.insertBatch(insertParams);
                        }
                        if (CollectionUtils.isNotEmpty(updateParams)) {
                            dao.updateBatch(updateParams);
                        }
                        if (CollectionUtils.isNotEmpty(deleteParams)) {
                            List<BackApiInfo> backApiInfos = dao.selectBatch(deleteParams);
                            // 删除后台接口信息
                            dao.deleteBatch(deleteParams);
                            // 删除关联关系
                            backApiInFuncDao.deleteBatch(backApiInfos.stream().map(p -> p.getApiId())
                                    .collect(Collectors.toList()));
                        }
                        break;
                    case ProfileType.PROD:
                        if (CollectionUtils.isNotEmpty(insertParams)) {
                            dao.insertBatch(insertParams);
                        }
                        break;
                    default:
                        break;
                }
    
                // 清除缓存
                List<String> keys = new ArrayList<>();
                keys.addAll(new ArrayList<>(redisTemplate.keys(CfgProperties.BASEINFO + "*")));
                keys.addAll(new ArrayList<>(redisTemplate.keys(CfgProperties.ACCOUNTURL + "*")));
                keys.add(CfgProperties.NOEXISTURL);
                redisTemplate.delete(keys);
    
                return success(resultData);
            } else {
                return error(resultData);
            }
        }




  • 相关阅读:
    Myeclipse10 + JBPM4.4 环境搭建图文教程
    关于ztree异步加载的问题(二)
    ztree学习之异步加载节点(一)
    【LeetCode】Search a 2D Matrix
    【LeetCode】Merge Sorted Array
    【LeetCode】Search for a Range
    一位阿里导师给大学生的忠告
    Java 基础
    java XML-RPC
    java web service
  • 原文地址:https://www.cnblogs.com/ziyue7575/p/fda93464ccee630b63d91035bef74396.html
Copyright © 2020-2023  润新知