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