首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Springfox全局响应头

Springfox全局响应头
EN

Stack Overflow用户
提问于 2018-04-18 06:24:39
回答 3查看 3.6K关注 0票数 4

在我的spring引导rest中,我为每个端点的每个响应(不管方法如何)发送一个唯一的请求id头“x-请求-id”。我可以使用这样的方法来添加这个:

代码语言:javascript
复制
@ApiResponses(value = { 
    @ApiResponse(
            code = 200, 
            message = "Successful status response", 
            responseHeaders = {
                    @ResponseHeader(
                            name = "x-request-id", 
                            description = "auto generated unique request id", 
                            response = String.class)})
})

这很好,我可以在Swagger中看到它。但是,对每个端点执行此操作是一个乏味的+维护问题。我希望在全局范围内这样做,但是Springfox文档只显示使用.globalResponseMessage选项的全局响应消息--我找不到全局响应头的任何内容。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-04-18 08:31:24

最后创建了一个注释来处理这个问题:

代码语言:javascript
复制
package com.abc.xyz.api.docs.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ResponseHeader;

import com.abc.xyz.api.constants.ApiConstants;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ApiResponses(value = { 
    @ApiResponse(
            code = 200, 
            message = "Successful status response",
            responseHeaders = {
                    @ResponseHeader(
                            name = ApiConstants.REQUESTIDHEADER,
                            description = ApiConstants.REQUESTIDDESCRIPTION, 
                            response = String.class)}),
    @ApiResponse(
            code = 401, 
            message = "Successful status response",
            responseHeaders = {
                    @ResponseHeader(
                            name = ApiConstants.REQUESTIDHEADER,
                            description = ApiConstants.REQUESTIDDESCRIPTION, 
                            response = String.class)}),
    @ApiResponse(
            code = 403, 
            message = "Successful status response",
            responseHeaders = {
                    @ResponseHeader(
                            name = ApiConstants.REQUESTIDHEADER,
                            description = ApiConstants.REQUESTIDDESCRIPTION, 
                            response = String.class)}),
    @ApiResponse(
            code = 404, 
            message = "Successful status response",
            responseHeaders = {
                    @ResponseHeader(
                            name = ApiConstants.REQUESTIDHEADER,
                            description = ApiConstants.REQUESTIDDESCRIPTION, 
                            response = String.class)}),
    }
)
public @interface RequestIdMethod {};

有了这个,我可以在我的方法前面添加一个标记注释:

代码语言:javascript
复制
@RequestMapping(value = "/heartbeat", method = RequestMethod.GET)
@RequestIdMethod
public Heartbeat checkHeartbeat() {
    return new Heartbeat(status);
}

这并不好,因为我需要对每个http返回代码重复整个@ApiResponse注释块(显然还有其他返回代码,但我只讨论了Springfox显示的默认代码)。如果有一种方法来参数化整个@ApiResponse块,情况会更好。

票数 3
EN

Stack Overflow用户

发布于 2019-12-30 06:08:48

我知道我在这里的聚会迟到了,但我确实找到了一种方法,在全局范围内使用反射为每个响应添加一个头(可能不是必需的,但对我来说是获取每个响应的最简单的方法。您还可以检查所有ApiResponses注释,但有些注释是隐式添加的,因此该方法忽略了)。

代码语言:javascript
复制
@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 10)
public class RequestIdResponseHeaderPlugin implements OperationBuilderPlugin {

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

  @Override
  public void apply(OperationContext operationContext) {
    try {
      // we use reflection here since the operationBuilder.build() method would lead to different operation ids
      // and we only want to access the private field 'responseMessages' to add the request-id header to it
      Field f = operationContext.operationBuilder().getClass().getDeclaredField("responseMessages");
      f.setAccessible(true);
      Set<ResponseMessage> responseMessages = (Set<ResponseMessage>) f.get(operationContext.operationBuilder());
      responseMessages.forEach(message -> {
        int code = message.getCode();
        Map<String, Header> map = new HashMap<>();
        map.put("my-header-name", new Header(null, null, new ModelRef("string")));
        ResponseMessage responseMessage = new ResponseMessageBuilder().code(code).headersWithDescription(map).build();
        operationContext.operationBuilder().responseMessages(Collections.singleton(responseMessage));
      });
    } catch (NoSuchFieldException | IllegalAccessException e) {
      e.printStackTrace();
    }
  }
}

在查看了操作生成器的responseMessages()方法之后,发现了这种方法。它根据状态代码在内部合并响应头,逻辑本身将简单地将头添加到现有的响应头中。

希望它能帮助别人,因为它不需要你注释每一个端点。

票数 1
EN

Stack Overflow用户

发布于 2019-02-04 15:38:41

我更新了我的文档配置,以便在每个API中包含全局头。希望这能有所帮助。

代码语言:javascript
复制
return new Docket(DocumentationType.SWAGGER_2)
    .apiInfo(new ApiInfoBuilder()
            .contact(new Contact("My Support", null, "My Email"))
            .description("My Description")
            .licenseUrl("My License")
            .title("My Title")
            .termsOfServiceUrl("My Terms and Conditions")
            .version("My Version")
            .build())
    .globalOperationParameters(Collections.singletonList(new ParameterBuilder()
            .name("x-request-id")
            .modelRef(new ModelRef("string"))
            .parameterType("header")
            .required(false)
            .build()))
    .select()
    .paths(PathSelectors.regex("/user*))
    .build()
    .directModelSubstitute(LocalDate.class, String.class)
    .directModelSubstitute(LocalDateTime.class, String.class);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49892573

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档