在Spring(4.3.2)项目中,我使用Swagger(2.7.0)为项目自动生成文档和swagger-ui。到目前为止效果很好。
但是现在,我确定我需要能够在控制器级别(而不是方法级别)声明路径变量。而且我需要教swagger发现这些路径变量,并将它们添加到docs和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在控制器级别应用的自定义注释描述的路径变量?
HasCommonPathVariable
好的,我知道了。这是解决方案。该bean需要在上下文中注册。Swagger将发现该bean并将其用作丰富操作的插件之一
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(); } }