|
@@ -0,0 +1,191 @@
|
|
|
+package com.ygj.yuemum.component;
|
|
|
+
|
|
|
+import com.fasterxml.classmate.TypeResolver;
|
|
|
+import com.google.common.collect.Multimap;
|
|
|
+import com.ygj.yuemum.dao.swagger.SwaggerDao;
|
|
|
+import com.ygj.yuemum.domain.swagger.ColumnInfo;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.boot.ApplicationArguments;
|
|
|
+import org.springframework.boot.ApplicationRunner;
|
|
|
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
|
+import org.springframework.context.annotation.Bean;
|
|
|
+import org.springframework.context.annotation.Configuration;
|
|
|
+import org.springframework.http.ResponseEntity;
|
|
|
+import org.springframework.web.context.request.async.DeferredResult;
|
|
|
+import springfox.documentation.builders.ParameterBuilder;
|
|
|
+import springfox.documentation.builders.PathSelectors;
|
|
|
+import springfox.documentation.builders.RequestHandlerSelectors;
|
|
|
+import springfox.documentation.schema.Model;
|
|
|
+import springfox.documentation.schema.ModelProperty;
|
|
|
+import springfox.documentation.schema.ModelRef;
|
|
|
+import springfox.documentation.schema.WildcardType;
|
|
|
+import springfox.documentation.service.*;
|
|
|
+import springfox.documentation.spi.DocumentationType;
|
|
|
+import springfox.documentation.spi.service.contexts.SecurityContext;
|
|
|
+import springfox.documentation.spring.web.DocumentationCache;
|
|
|
+import springfox.documentation.spring.web.plugins.Docket;
|
|
|
+import springfox.documentation.swagger.web.ApiKeyVehicle;
|
|
|
+import springfox.documentation.swagger.web.SecurityConfiguration;
|
|
|
+import springfox.documentation.swagger.web.UiConfiguration;
|
|
|
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
|
|
+
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.lang.reflect.Modifier;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+import static com.google.common.collect.Lists.newArrayList;
|
|
|
+import static springfox.documentation.schema.AlternateTypeRules.newRule;
|
|
|
+
|
|
|
+@Configuration
|
|
|
+@EnableSwagger2
|
|
|
+@ConditionalOnProperty(name = "swagger.enable", havingValue = "true")
|
|
|
+public class SwaggerConfigure implements ApplicationRunner {
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ public Docket petApi() {
|
|
|
+ return new Docket(DocumentationType.SWAGGER_2)
|
|
|
+ .select()
|
|
|
+ .apis(RequestHandlerSelectors.basePackage("com.ygj.yuemum.controller"))
|
|
|
+ .paths(PathSelectors.any())
|
|
|
+ .build()
|
|
|
+ .pathMapping("/")
|
|
|
+ .directModelSubstitute(LocalDate.class,
|
|
|
+ String.class)
|
|
|
+ .genericModelSubstitutes(ResponseEntity.class)
|
|
|
+ .alternateTypeRules(
|
|
|
+ newRule(typeResolver.resolve(DeferredResult.class,
|
|
|
+ typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
|
|
|
+ typeResolver.resolve(WildcardType.class)))
|
|
|
+ .useDefaultResponseMessages(false)
|
|
|
+// .globalResponseMessage(RequestMethod.GET,
|
|
|
+// newArrayList(new ResponseMessageBuilder()
|
|
|
+// .code(500)
|
|
|
+// .message("500 message")
|
|
|
+// .responseModel(new ModelRef("Error"))
|
|
|
+// .build()))
|
|
|
+ .securitySchemes(newArrayList(apiKey()))
|
|
|
+ .securityContexts(newArrayList(securityContext()))
|
|
|
+ .enableUrlTemplating(false)
|
|
|
+ .globalOperationParameters(
|
|
|
+ newArrayList(new ParameterBuilder()
|
|
|
+ .name("token")
|
|
|
+ .description("请求token")
|
|
|
+ .modelRef(new ModelRef("string"))
|
|
|
+ .parameterType("query")
|
|
|
+ .required(false)
|
|
|
+ .build()))
|
|
|
+ .tags(new Tag("Pet Service", "All apis relating to pets"))
|
|
|
+ ;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TypeResolver typeResolver;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DocumentationCache documentationCache;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SwaggerDao swaggerDao;
|
|
|
+
|
|
|
+ private ApiKey apiKey() {
|
|
|
+ return new ApiKey("Authorization", "token", "header");
|
|
|
+ }
|
|
|
+
|
|
|
+ private SecurityContext securityContext() {
|
|
|
+ return SecurityContext.builder()
|
|
|
+ .securityReferences(defaultAuth())
|
|
|
+ .forPaths(PathSelectors.regex("/anyPath.*"))
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ List<SecurityReference> defaultAuth() {
|
|
|
+ AuthorizationScope authorizationScope
|
|
|
+ = new AuthorizationScope("global", "accessEverything");
|
|
|
+ AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
|
|
+ authorizationScopes[0] = authorizationScope;
|
|
|
+ return newArrayList(
|
|
|
+ new SecurityReference("Authorization", authorizationScopes));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ SecurityConfiguration security() {
|
|
|
+ return new SecurityConfiguration(
|
|
|
+ "test-app-client-id",
|
|
|
+ "test-app-client-secret",
|
|
|
+ "test-app-realm",
|
|
|
+ "test-app",
|
|
|
+ "apiKey",
|
|
|
+ ApiKeyVehicle.HEADER,
|
|
|
+ "api_key",
|
|
|
+ "," /*scope separator*/);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ UiConfiguration uiConfig() {
|
|
|
+ return new UiConfiguration(
|
|
|
+ "validatorUrl",// url
|
|
|
+ "none", // docExpansion => none | list
|
|
|
+ "alpha", // apiSorter => alpha
|
|
|
+ "schema", // defaultModelRendering => schema
|
|
|
+ UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS,
|
|
|
+ true, // enableJsonEditor => true | false
|
|
|
+ true, // showRequestHeaders => true | false
|
|
|
+ 60000L); // requestTimeout => in milliseconds, defaults to null (uses jquery xh timeout)
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void run(ApplicationArguments applicationArguments) throws Exception{
|
|
|
+ Map<String, String> columnInfo = getTableInfo();
|
|
|
+ Documentation documentation = documentationCache.documentationByGroup(Docket.DEFAULT_GROUP_NAME);
|
|
|
+ Multimap<String, ApiListing> apiListings = documentation.getApiListings();
|
|
|
+ Collection<ApiListing> listings = apiListings.values();
|
|
|
+ for (ApiListing apiListing:listings) {
|
|
|
+ //controller
|
|
|
+ for (ApiDescription apiDescription:apiListing.getApis()) {
|
|
|
+ List<Operation> optionals = apiDescription.getOperations();
|
|
|
+ for (Operation operation:optionals) {
|
|
|
+ List<Parameter> parameters = operation.getParameters();
|
|
|
+ for (Parameter parameter:parameters) {
|
|
|
+ String comment = columnInfo.get(parameter.getName());
|
|
|
+ if (StringUtils.isNotBlank(comment)) {
|
|
|
+ Field nameField = Parameter.class.getDeclaredField("description");
|
|
|
+
|
|
|
+ Field modifiersField = Field.class.getDeclaredField("modifiers"); //①
|
|
|
+ modifiersField.setAccessible(true);
|
|
|
+ modifiersField.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL); //②
|
|
|
+
|
|
|
+ nameField.setAccessible(true);
|
|
|
+ nameField.set(parameter, comment);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //model
|
|
|
+ for (Model model:apiListing.getModels().values()) {
|
|
|
+ for (ModelProperty modelProperty:model.getProperties().values()) {
|
|
|
+ String comment = columnInfo.get(modelProperty.getName());
|
|
|
+ if (StringUtils.isNotBlank(comment)) {
|
|
|
+ Field nameField = ModelProperty.class.getDeclaredField("description");
|
|
|
+
|
|
|
+ Field modifiersField = Field.class.getDeclaredField("modifiers"); //①
|
|
|
+ modifiersField.setAccessible(true);
|
|
|
+ modifiersField.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL); //②
|
|
|
+
|
|
|
+ nameField.setAccessible(true);
|
|
|
+ nameField.set(modelProperty, comment);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String ,String> getTableInfo() {
|
|
|
+ List<String> tableNames = swaggerDao.getTablesName();
|
|
|
+ List<ColumnInfo> columnInfos = swaggerDao.getColumns(tableNames);
|
|
|
+ Map<String, String> columnInfoMap = new HashMap<>();
|
|
|
+ columnInfos.forEach(columnInfo -> columnInfoMap.put(columnInfo.getName(),columnInfo.getComment()));
|
|
|
+ return columnInfoMap;
|
|
|
+ }
|
|
|
+}
|