传统的swagger配置挺麻烦的:
这么多行才配好了一个控制器的文档.
当然我对swagger没什么了解,也不懂这是啥意思,不过项目中控制器十几个了,难道每个控制器都要写这么多东西吗?
尝试了一种新的配置方式,集中配置,一行就是一个控制器,如果用上面哪种方式这几十个控制器配到什么时候:
实现方法:
首先贴上注册springBean的方法:
private static void autoSwagger() {
try {
Map 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 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 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:
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 getBean(String beanName,Class 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 registerBean(String name, Class 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);
}
}
还需要一个工具类:
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 deal(Object from,Class toC) throws Exception {
T to = toC.newInstance();
deal(from,to,false);
return to;
}
}
上面是全部实现方法了,此外,由于注册swagger相关的bean需要ApplicationContextUtil 这个bean先注册
这个解决方案网上很多,我的ApplicationContextUtil 注册在启动主类中,swagger相关的bean是一个单独的配置文件,通过两个文件的排序解决先后问题.
启动主类:
swagger配置类:
结束,对这个工具不感兴趣只是团队需要就用了,简化了下配置,其中手动注册bean的方法来源于网络,忘记哪里看的了.
可以看到用的方法非常差,以后有精力的话会再考虑考虑的.
有更好的方式留言谢谢