123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- package com.primeton.dgs.kernel.core.configure;
- import com.google.common.collect.Multimap;
- import com.google.common.collect.Sets;
- import com.google.common.net.MediaType;
- import com.primeton.dgs.kernel.core.web.AppBaseDispatchCommand;
- import org.apache.commons.lang.StringUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationListener;
- import org.springframework.context.event.ContextRefreshedEvent;
- import org.springframework.http.HttpMethod;
- import org.springframework.stereotype.Repository;
- import springfox.documentation.builders.ResponseMessageBuilder;
- import springfox.documentation.schema.ModelRef;
- import springfox.documentation.service.ApiDescription;
- import springfox.documentation.service.ApiListing;
- import springfox.documentation.service.Documentation;
- import springfox.documentation.service.Operation;
- import springfox.documentation.service.Parameter;
- import springfox.documentation.service.ResponseMessage;
- import springfox.documentation.service.Tag;
- import springfox.documentation.spring.web.DocumentationCache;
- import springfox.documentation.spring.web.json.JsonSerializer;
- import springfox.documentation.spring.web.plugins.Docket;
- import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Set;
- /**
- *
- *
- * 元数据老结构,支持 Swagger 适配器
- *
- * <pre>
- *
- * Created by zhaopx.
- * User: zhaopx
- * Date: 2020/8/28
- * Time: 14:34
- *
- * </pre>
- *
- * @author zhaopx
- */
- @Repository
- public class SwaggerExtentionSupport implements ApplicationListener<ContextRefreshedEvent> {
- /**
- * 版本
- */
- public final static String API_VER = "7.1.0";
- @Autowired
- DocumentationCache documentationCache;
- @Autowired
- private ServiceModelToSwagger2Mapper mapper;
- @Autowired
- private JsonSerializer jsonSerializer;
- @Value("${swagger.group}")
- private String groupName;
- private static Logger log = LoggerFactory.getLogger(SwaggerExtentionSupport.class);
- /**
- * 扫描 cotext 中 .do 的 bean,扫描 方法
- * @param context
- */
- private void initSwagger(ApplicationContext context) {
- Documentation documentation = documentationCache.documentationByGroup(groupName);
- if(documentation == null) {
- // 如果 groupName 指定的下没有,则挂载 default 上
- documentation = documentationCache.documentationByGroup(Docket.DEFAULT_GROUP_NAME);
- }
- if (documentation != null) {
- // 取得所有的 API 合集
- Multimap<String, ApiListing> apiListings = documentation.getApiListings();
- //Swagger swagger = mapper.mapDocumentation(documentation);
- String[] beanDefinitionNames = context.getBeanDefinitionNames();
- //String[] beanDefinitionNames = new String[]{"test.do", "param.do", "rule.do"};
- for (String name : beanDefinitionNames) {
- if(name.endsWith(".do")) {
- Class<?> aClass = context.getBean(name).getClass();
- if(!AppBaseDispatchCommand.class.isAssignableFrom(aClass)) {
- // 必须是 AppBaseDispatchCommand 的子类,才继续
- continue;
- }
- log.info("add swagger bean {}", name);
- Method[] servletMethods = aClass.getDeclaredMethods();
- for (Method servletMethod : servletMethods) {
- String methodName = servletMethod.getName();
- if(!"init".equals(methodName) && Modifier.isPublic(servletMethod.getModifiers())) {
- // 返回 tags
- Set<Tag> tags = addApi(apiListings, documentation.getBasePath(), name, methodName);
- if(!tags.isEmpty()) {
- documentation.getTags().addAll(tags);
- }
- }
- }
- }
- }
- log.info("swagger apis size: {}", apiListings.size());
- }
- }
- private Set<Tag> addApi(Multimap<String, ApiListing> apiListings,
- String basePath,
- String beanName,
- String methodName) {
- // 获取去除了 .do 的 名称
- String optGroup = getName(beanName);
- String apiId = optGroup + "_" + methodName;
- String optId = methodName;
- // 生成唯一ID
- Collection<ApiListing> apis = apiListings.get(apiId);
- if(apis == null) {
- // 后面只是用 apis 的 size 获取长度
- apis = new HashSet<>();
- }
- ArrayList<ApiDescription> apis1 = new ArrayList<>();
- ArrayList<Operation> operations = new ArrayList<>();
- ResponseMessage v200 = new ResponseMessageBuilder().code(200).message("OK").build();
- ResponseMessage v401 = new ResponseMessageBuilder().code(401).message("Unauthorized").build();
- ResponseMessage v403 = new ResponseMessageBuilder().code(403).message("Forbidden").build();
- ResponseMessage v404 = new ResponseMessageBuilder().code(404).message("Not Found").build();
- // tag
- HashSet<Tag> tags = new HashSet<>();
- // description 是生成 API JS 的文件名
- // optGroup 是生成的函数名
- Tag tag = new Tag(optGroup, optGroup + "Controller");
- tags.add(tag);
- // 注意 position,必须是不重复的值
- ArrayList<Parameter> parameters = new ArrayList<>();
- /*
- 暂时先不要参数
- Parameter parameter = new Parameter(
- "invoke",
- "Invoke Method",
- methodName,
- true,
- false,
- false,
- new ModelRef("string"),
- null, null,
- "string","", false, null, null, 0, null,
- ArrayListMultimap.create(),
- Collections.emptyList()
- );
- parameters.add(parameter);
- */
- /*
- Operation operaGet = new Operation(
- HttpMethod.GET,
- "do exec " + optGroup + "." + methodName,
- "",
- new ModelRef("string"),
- optId+"UsingGET",
- 0,
- Sets.newHashSet(tag.getName()),
- Sets.newHashSet(MediaType.ANY_TYPE.toString()),
- Sets.newHashSet(MediaType.create("application", "json").toString()),
- new HashSet<>(),
- new ArrayList<>(),
- parameters,
- Sets.newHashSet(v200, v401, v403, v404),
- "",
- false,
- new ArrayList<>()
- );
- */
- // Operation 只需要 tag name,他决定了该 api 在 Swagger 上挂载的tag
- Operation operaPost = new Operation(
- HttpMethod.POST,
- "do exec " + optGroup + "." + methodName,
- "",
- new ModelRef("string"),
- optId+"UsingPOST",
- 0,
- Sets.newHashSet(tag.getName()),
- Sets.newHashSet(MediaType.ANY_TYPE.toString()),
- Sets.newHashSet(MediaType.create("application", "json").toString()),
- new HashSet<>(),
- new ArrayList<>(),
- parameters,
- Sets.newHashSet(v200, v401, v403, v404),
- "",
- false,
- new ArrayList<>()
- );
- operations.add(operaPost);
- String url = "/appsapi/" + optGroup + "/" + methodName;
- apis1.add(new ApiDescription(groupName,
- url,
- beanName+"." + methodName,
- operations, false));
- // 注意 position,必须是不重复的值
- ApiListing apiListing = new ApiListing(
- API_VER,
- basePath,
- "/" + beanName,
- new HashSet<>(),new HashSet<>(),"", new HashSet<>(), new ArrayList<>(),
- apis1,
- new HashMap<>(), beanName+"." + methodName, apis.size(), tags);
- // 放到api列表中
- apiListings.put(apiId, apiListing);
- // 返回 tag,tag 会显示到 Swagger Content
- return tags;
- }
- private String getName(String beanName) {
- if(StringUtils.isBlank(beanName)) {
- return beanName;
- }
- int i = beanName.indexOf(".");
- if(i > 0) {
- return beanName.substring(0, i);
- }
- return beanName;
- }
- @Override
- public void onApplicationEvent(ContextRefreshedEvent event) {
- // Spring 框架加载完全后,扫描 bean,获取 servlet
- initSwagger(event.getApplicationContext());
- }
- }
|