swagger-ui 使用控制器的接口和实现复制端点
swagger-ui duplicating endpoints with interface and implementation of controller
我有一个 spring 启动应用程序。我选择将我的控制器实现为定义端点及其各自实现的接口(即 EndpointX、EndpointXController w/ EndpointXController 是实现)。我在接口文件中有所有关于 swagger 的注释,以防止实现混乱class;但是,我在 swagger UI 上看到了重复的端点,如下所示:
这是我的摘要设置:
@Bean
public Docket customImplementation() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(RequestMapping.class))
.paths(PathSelectors.ant("/consent/*"))
.build()
.directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class)
.directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class)
.apiInfo(apiInfo());
}
如何让 swagger/swagger-ui 只显示其余服务的一个端点?即 consent-api-controller 不会被 swagger 显示或拾取。
编辑:发布的控制器和接口代码
@Controller
public class ConsentApiController implements ConsentApi {
@Autowired
private IConsentApiService consentApiService;
private final ObjectMapper objectMapper;
private final HttpServletRequest request;
@Autowired
public ConsentApiController(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
@Override
public Optional<ObjectMapper> getObjectMapper() {
return Optional.ofNullable(objectMapper);
}
@Override
public Optional<HttpServletRequest> getRequest() {
return Optional.ofNullable(request);
}
public ResponseEntity getConsent(@ApiParam(value = "Identifier for the consent object to be retrieved", required = true) @Valid @RequestBody ConsentReadRequestParent consentReadRequestParent) {
return consentApiService.getConsent(consentReadRequestParent);
}
public ResponseEntity postConsent(@ApiParam(value = "Populated consent object") @Valid @RequestBody ConsentParentRequest consentObj) {
// Pass request to service where it will be split into DTOs and passed to DAOs and get response
return consentApiService.postConsent(consentObj);
}
public ResponseEntity searchConsent(@Valid @RequestBody SearchParentRequest spr){
return consentApiService.searchConsent(spr);
}
}
@Api(value = "consent")
public interface ConsentApi {
default Optional<ObjectMapper> getObjectMapper() {
return Optional.empty();
}
default Optional<HttpServletRequest> getRequest() {
return Optional.empty();
}
default Optional<String> getAcceptHeader() {
return getRequest().map(r -> r.getHeader("Accept"));
}
@ApiOperation(value = "The Read Consent API is a resource that conforms to a RESTful syntax to retrieve the details of a single consent record.", nickname = "getConsent", notes = "Cannot read without parameters. Minimum of 2 characters in each field. Maximum of 50 characters in each field. Should be able to handle special characters.", response = Consent.class, tags = {"consent",})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = Consent.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 405, message = "Method Not Allowed"),
@ApiResponse(code = 500, message = "Internal Server Error"),
@ApiResponse(code = 604, message = "Could Not Retrieve Data for Consent"),
@ApiResponse(code = 714, message = "Consent Not Found Matching Input Values")})
@RequestMapping(value = "/consent/read",
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> getConsent(@ApiParam(value = "Identifier for the consent object to be retrieved.", required = true) @Valid @RequestBody ConsentReadRequestParent consentReadRequestParent);
@ApiOperation(value = "The Create Consent API is a resource that conforms to a RESTful syntax to persist a single consent record.", nickname = "postConsent", notes = "<business and backend logic/requirements>", response = ConsentResponseParent.class, tags = {"consent",})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = ConsentResponseParent.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 405, message = "Method Not Allowed"),
@ApiResponse(code = 500, message = "Internal Server Error")})
@RequestMapping(value = "/consent/create",
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> postConsent(@ApiParam(value = "filled-out consent object") @Valid @RequestBody ConsentParentRequest consentObj);
@ApiOperation(value = "The Search Consent API is a resource that conforms to a RESTful syntax to query consent records.", response = SearchParentResponse.class, tags = {"consent",})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = SearchParentResponse.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 405, message = "Method Not Allowed"),
@ApiResponse(code = 500, message = "Internal Server Error")})
@RequestMapping(value = "/consent/search",
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> searchConsent(@Valid @RequestBody SearchParentRequest spr);
}
您可以明确排除不应显示的控制器,方法是将接口移动到不同的包并使用
.apis(RequestHandlerSelectors.basePackage("my.impl.package"))
或者编写您自己的自定义谓词集并将它们传递到 .apis()。
不过,这更像是一种解决方法。您确定在实现 类 时没有使用 @RequestMapping 注释吗?我无法在本地复制此行为。
从 @ApiOperation
注释中删除属性 "tags"
。添加标签将使 api 出现在上下文菜单下以及它自己的单独菜单下。
另一种方法是控制器的@Api class:
@Controller
@Api(tags = "consent")
public class ConsentApiController implements ConsentApi {
或进入界面:
@Api(value = "consent", tags = "consent")
public interface ConsentApi {
我有一个 spring 启动应用程序。我选择将我的控制器实现为定义端点及其各自实现的接口(即 EndpointX、EndpointXController w/ EndpointXController 是实现)。我在接口文件中有所有关于 swagger 的注释,以防止实现混乱class;但是,我在 swagger UI 上看到了重复的端点,如下所示:
这是我的摘要设置:
@Bean
public Docket customImplementation() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(RequestMapping.class))
.paths(PathSelectors.ant("/consent/*"))
.build()
.directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class)
.directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class)
.apiInfo(apiInfo());
}
如何让 swagger/swagger-ui 只显示其余服务的一个端点?即 consent-api-controller 不会被 swagger 显示或拾取。
编辑:发布的控制器和接口代码
@Controller
public class ConsentApiController implements ConsentApi {
@Autowired
private IConsentApiService consentApiService;
private final ObjectMapper objectMapper;
private final HttpServletRequest request;
@Autowired
public ConsentApiController(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
@Override
public Optional<ObjectMapper> getObjectMapper() {
return Optional.ofNullable(objectMapper);
}
@Override
public Optional<HttpServletRequest> getRequest() {
return Optional.ofNullable(request);
}
public ResponseEntity getConsent(@ApiParam(value = "Identifier for the consent object to be retrieved", required = true) @Valid @RequestBody ConsentReadRequestParent consentReadRequestParent) {
return consentApiService.getConsent(consentReadRequestParent);
}
public ResponseEntity postConsent(@ApiParam(value = "Populated consent object") @Valid @RequestBody ConsentParentRequest consentObj) {
// Pass request to service where it will be split into DTOs and passed to DAOs and get response
return consentApiService.postConsent(consentObj);
}
public ResponseEntity searchConsent(@Valid @RequestBody SearchParentRequest spr){
return consentApiService.searchConsent(spr);
}
}
@Api(value = "consent")
public interface ConsentApi {
default Optional<ObjectMapper> getObjectMapper() {
return Optional.empty();
}
default Optional<HttpServletRequest> getRequest() {
return Optional.empty();
}
default Optional<String> getAcceptHeader() {
return getRequest().map(r -> r.getHeader("Accept"));
}
@ApiOperation(value = "The Read Consent API is a resource that conforms to a RESTful syntax to retrieve the details of a single consent record.", nickname = "getConsent", notes = "Cannot read without parameters. Minimum of 2 characters in each field. Maximum of 50 characters in each field. Should be able to handle special characters.", response = Consent.class, tags = {"consent",})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = Consent.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 405, message = "Method Not Allowed"),
@ApiResponse(code = 500, message = "Internal Server Error"),
@ApiResponse(code = 604, message = "Could Not Retrieve Data for Consent"),
@ApiResponse(code = 714, message = "Consent Not Found Matching Input Values")})
@RequestMapping(value = "/consent/read",
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> getConsent(@ApiParam(value = "Identifier for the consent object to be retrieved.", required = true) @Valid @RequestBody ConsentReadRequestParent consentReadRequestParent);
@ApiOperation(value = "The Create Consent API is a resource that conforms to a RESTful syntax to persist a single consent record.", nickname = "postConsent", notes = "<business and backend logic/requirements>", response = ConsentResponseParent.class, tags = {"consent",})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = ConsentResponseParent.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 405, message = "Method Not Allowed"),
@ApiResponse(code = 500, message = "Internal Server Error")})
@RequestMapping(value = "/consent/create",
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> postConsent(@ApiParam(value = "filled-out consent object") @Valid @RequestBody ConsentParentRequest consentObj);
@ApiOperation(value = "The Search Consent API is a resource that conforms to a RESTful syntax to query consent records.", response = SearchParentResponse.class, tags = {"consent",})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = SearchParentResponse.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 405, message = "Method Not Allowed"),
@ApiResponse(code = 500, message = "Internal Server Error")})
@RequestMapping(value = "/consent/search",
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> searchConsent(@Valid @RequestBody SearchParentRequest spr);
}
您可以明确排除不应显示的控制器,方法是将接口移动到不同的包并使用
.apis(RequestHandlerSelectors.basePackage("my.impl.package"))
或者编写您自己的自定义谓词集并将它们传递到 .apis()。
不过,这更像是一种解决方法。您确定在实现 类 时没有使用 @RequestMapping 注释吗?我无法在本地复制此行为。
从 @ApiOperation
注释中删除属性 "tags"
。添加标签将使 api 出现在上下文菜单下以及它自己的单独菜单下。
另一种方法是控制器的@Api class:
@Controller
@Api(tags = "consent")
public class ConsentApiController implements ConsentApi {
或进入界面:
@Api(value = "consent", tags = "consent")
public interface ConsentApi {