简化swagger2配置,swagger2集中配置

传统的swagger配置挺麻烦的:
传统配置方式这么多行才配好了一个控制器的文档.
当然我对swagger没什么了解,也不懂这是啥意思,不过项目中控制器十几个了,难道每个控制器都要写这么多东西吗?
尝试了一种新的配置方式,集中配置,一行就是一个控制器,如果用上面哪种方式这几十个控制器配到什么时候:
新的配置方式实现方法:
首先贴上注册springBean的方法:

private static void autoSwagger() {
        try {
            Map<String, String> map = new HashMap<>(8);
            loadPart(map);
            if(map.size() == 0){
                System.out.println("swagger目录不应为空,至少应该有一个");
                return;
            }
            for (String groupName : map.keySet()) {
                Docket docket = ApplicationContextUtil.registerBean(groupName,Docket.class,DocumentationType.SWAGGER_2);
                Predicate<String> p = PathSelectors.regex(map.get(groupName))::apply;
                Docket dockets = new Docket(DocumentationType.SWAGGER_2).groupName(groupName)
                        .select()
                        .paths(p::test)
                        .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                        .build();
                SameEntityClone.deal(dockets,docket,true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Bean
    public String swaggerStatus(){
        if(Objects.equals("dev",ApplicationContextUtil.getProfiles())){
            SwaggerConfig.autoSwagger();
            return "swagger load!";
        }
        Docket docket = ApplicationContextUtil.registerBean("swagger",Docket.class,DocumentationType.SWAGGER_2);
        Predicate<String> p = PathSelectors.regex("swagger!")::apply;
        Docket dockets = new Docket(DocumentationType.SWAGGER_2).groupName("swagger")
                .select()
                .paths(p::test)
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .build();
        try {
            SameEntityClone.deal(dockets,docket,true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "swagger unload!";
    }

上面的方法需要这个springBean:

package com.guoyicap.micro.common.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;

public class ApplicationContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    public ApplicationContextUtil() {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtil.applicationContext = applicationContext;
    }

    public static Object getBean(String beanName) {
        return applicationContext != null ? applicationContext.getBean(beanName) : null;
    }

    public static <T> T getBean(String beanName,Class<T> c) {
        return applicationContext != null ? applicationContext.getBean(beanName,c) : null;
    }
    /**
     * 获取环境   比如test
     * String
     */
    public static String getProfiles() {
        return applicationContext.getEnvironment().getActiveProfiles()[0];
    }


    /**
     * 主动向Spring容器中注册bean,已经有了的话,返回以前的
     * @param name BeanName
     * @param clazz 注册的bean的类性
     * @param args 构造方法的必要参数,顺序和类型要求和clazz中定义的一致,如果使用空参构造,可以不传
     * @return 返回注册到容器中的bean对象
     */
    public static <T> T registerBean(String name, Class<T> clazz, Object... args) {
        if (applicationContext.containsBean(name)) {
            Object bean = applicationContext.getBean(name);
            if (bean.getClass().isAssignableFrom(clazz)) {
                return (T) bean;
            } else {
                throw new RuntimeException("IOC不同类型的Bean,名字重复:" + name);
            }
        }
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
        for (Object arg : args) {
            beanDefinitionBuilder.addConstructorArgValue(arg);
        }
        BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
        BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) ((ConfigurableApplicationContext)applicationContext).getBeanFactory();
        beanFactory.registerBeanDefinition(name, beanDefinition);
        return applicationContext.getBean(name, clazz);
    }
}

还需要一个工具类:

package com.guoyicap.micro.common.util;


import javax.management.OperationsException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * @author gaoku 相似对象复制
 **/
public class SameEntityClone {

    /**
     * 相同类型,相同名称的字段复制,会直接
     * @param from 原始对象
     * @param to 接收
     * @param cover 是否覆盖原有参数
     * @throws Exception 异常  不支持的操作或者其他
     */
    public static void deal(Object from,Object to,boolean cover) throws Exception {
        if (from == null || to == null){
            return;
        }
        if (from == to) {
            throw new OperationsException("相同的目标");
        }
        Class fromC = from.getClass();
        Class toC = to.getClass();
        Field[] fromFields = fromC.getDeclaredFields();
        Field[] toFields = toC.getDeclaredFields();
        if (fromFields.length == 0 || toFields.length == 0) {
            return;
        }
        for (Field fromField : fromFields) {
            fromField.setAccessible(true);
            for (Field toField : toFields) {
                if (Modifier.isFinal(toField.getModifiers())){
                    continue;
                }
                toField.setAccessible(true);
                if (toField.getType().isAssignableFrom(fromField.getType())  && fromField.getName().equals(toField.getName())) {
                    if (cover && fromField.get(from) != null) {
                        toField.set(to, fromField.get(from));
                    } else {
                        if (toField.get(to) == null) {
                            toField.set(to, fromField.get(from));
                        }
                    }
                }
            }
        }
    }

    /**
     * 相同类型,相同名称的字段复制,不覆盖原有参数
     * @param from 原始对象
     * @param to 接收
     * @throws Exception 异常  不支持的操作或者其他
     */
    public static void deal(Object from,Object to) throws Exception {
        deal(from,to,false);
    }

    /**
     * 相同类型,相同名称的字段复制  这个方法会返回一个新建对象
     * @param from 原始对象
     * @param toC 接收类型
     * @throws Exception 异常  不支持的操作或者其他
     */
    public static <T>T deal(Object from,Class<T> toC) throws Exception {
        T to = toC.newInstance();
        deal(from,to,false);
        return to;
    }

}

上面是全部实现方法了,此外,由于注册swagger相关的bean需要ApplicationContextUtil 这个bean先注册
这个解决方案网上很多,我的ApplicationContextUtil 注册在启动主类中,swagger相关的bean是一个单独的配置文件,通过两个文件的排序解决先后问题.
启动主类:
主类swagger配置类:
swagger

结束,对这个工具不感兴趣只是团队需要就用了,简化了下配置,其中手动注册bean的方法来源于网络,忘记哪里看的了. 可以看到用的方法非常差,以后有精力的话会再考虑考虑的. 有更好的方式留言谢谢