2017-05-30 374 views
1

在我的Spring(4.3.2)项目中,我使用Swagger(2.7.0)为我的项目自动生成文档和swagger-ui。迄今为止这很有效。如何确认swagger来处理自定义Controller级别的PathVariable注释?

但是现在我确定我需要能够在控制器级别(而不是方法级别)声明路径变量。我需要教大家发现这些路径变量并将它们添加到文档和swagger-ui中。

我创建定制标注

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface HasCommonPathVariable { 
    /** 
    * The URI template variable to bind to. 
    */ 
    String name(); 
    Class<?> type(); 
    String defaultValue() default ""; 
} 

而我使用它是这样的:

@RestController 
@Secured(SecurityConstants.ROLE_USER) 
@RequestMapping(path = "/rest/api/v1/env/{envId}/asset-type") 
@HasCommonPathVariable(name = "envId", type = Long.class) 
public class AssetTypeRestController extends CustomRestControllerBase<Long, AssetTypeRow, AssetTypeService> { 
// ... contorller code 
} 

我没有与Spring的PathVariable注释中提到的参数控制方法,和点我不允许这么做(这是因为我正在构建微观框架)。

所以问题是:如何教大摇大摆发现路径变量描述使用自定义注释HasCommonPathVariable在控制器级应用?

回答

0

好的,我已经知道了。这是解决方案。这个bean需要在上下文中注册。 Swagger会发现这个豆,并将其用作丰富操作的插件之一。

import java.util.ArrayList; 
import java.util.List; 
import org.apache.log4j.Logger; 
import org.springframework.core.annotation.Order; 
import com.fasterxml.classmate.TypeResolver; 
import com.google.common.base.Optional; 
import springfox.documentation.builders.ParameterBuilder; 
import springfox.documentation.schema.ModelRef; 
import springfox.documentation.service.Parameter; 
import springfox.documentation.spi.DocumentationType; 
import springfox.documentation.spi.service.OperationBuilderPlugin; 
import springfox.documentation.spi.service.contexts.OperationContext; 
import springfox.documentation.swagger.common.SwaggerPluginSupport; 

@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) 
public class CommonPathVariableOperationBuilderPlugin implements OperationBuilderPlugin { 
    protected Logger log = Logger.getLogger(getClass()); 

    private TypeResolver typeResolver; 

    public CommonPathVariableOperationBuilderPlugin(TypeResolver typeResolver) { 
     this.typeResolver = typeResolver; 
    } 

    @Override 
    public boolean supports(DocumentationType delimiter) { 
     return true; 
    } 

    @Override 
    public void apply(OperationContext opCtx) { 
     List<Parameter> ret = new ArrayList<Parameter>(); 
     Optional<HasCommonPathVariable> annSingle = opCtx.findControllerAnnotation(HasCommonPathVariable.class); 
     if (annSingle.isPresent()) { 
      ret.add(addParameter(annSingle.get())); 
     } 

     Optional<HasCommonPathVariables> annPlural = opCtx.findControllerAnnotation(HasCommonPathVariables.class); 
     if (annPlural.isPresent()) { 
      for (HasCommonPathVariable ann : annPlural.get().value()) { 
       ret.add(addParameter(ann)); 
      } 
     } 
     opCtx.operationBuilder().parameters(ret); 
    } 

    private Parameter addParameter(HasCommonPathVariable ann) { 
     ParameterBuilder pb = new ParameterBuilder(); 
     pb.parameterType("path").name(ann.name()).type(typeResolver.resolve(ann.type())); 
     pb.modelRef(new ModelRef("string")); 
     pb.required(true); 
     if (!"".equals(ann.defaultValue())) { 
      pb.defaultValue(ann.defaultValue()); 
     } 
     return pb.build(); 
    } 
}