【问题标题】:Spring-Boot OpenAPI - @RestControllerAdvice not limited to methods throwing the ExceptionSpring-Boot OpenAPI - @RestControllerAdvice 不限于抛出异常的方法
【发布时间】:2022-02-02 16:34:09
【问题描述】:

我需要用 OpenAPI 记录我的 SpringBoot API 及其可能的异常, 我正在使用 SpringDoc-OpenAPI https://springdoc.org/

为了处理 NotFound 案例,我创建了这个异常类:

import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

public class NotFoundException extends ResponseStatusException {
    public NotFoundException() {
        super(HttpStatus.NOT_FOUND);
    }
}

还有这个@RestControllerAdvice

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalControllerExceptionHandler {
    @ExceptionHandler(NotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResponseEntity<String> handleNotFoundException(RuntimeException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }
}

我面临的问题是生成的OpenAPI yaml文件有

  responses:
    "404":
      description: Not Found
      content:
        '*/*':
          schema:
            type: string

适用于所有@RestController 端点,而不是仅适用于带有throws NotFoundException 的方法。

如何限制 @ControllerAdvice(或 OpenAPI),只为带有 throwing 签名的方法生成 404 响应文档?

除了@RestControllerAdvice,我还需要使用其他东西吗? 我想避免必须注释每个方法。

【问题讨论】:

    标签: spring-boot openapi springdoc


    【解决方案1】:

    一个可能的解决方案是:

    1. 制作@RestControllerAdvice @Hidden
    2. 提供OperationCustomizer @Bean

    import io.swagger.v3.oas.annotations.Hidden;
    import it.eng.cysec.ot.risk.assessment.api.exceptions.NotFoundException;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    @Hidden
    @RestControllerAdvice
    public class GlobalControllerExceptionHandler {
        @ExceptionHandler(NotFoundException.class)
        @ResponseStatus(HttpStatus.NOT_FOUND)
        public ResponseEntity<String> handleNotFoundException(NotFoundException exception) {
            return new ResponseEntity<>(exception.getMessage(), HttpStatus.NOT_FOUND);
        }
    }
    

    import io.swagger.v3.oas.models.Operation;
    import io.swagger.v3.oas.models.media.Content;
    import io.swagger.v3.oas.models.media.MediaType;
    import io.swagger.v3.oas.models.media.StringSchema;
    import io.swagger.v3.oas.models.responses.ApiResponse;
    import io.swagger.v3.oas.models.responses.ApiResponses;
    import it.eng.cysec.ot.risk.assessment.api.exceptions.NotFoundException;
    import org.springdoc.core.customizers.OperationCustomizer;
    import org.springframework.web.method.HandlerMethod;
    
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.List;
    
    public class OperationResponseCustomizer implements OperationCustomizer {
        public static final ApiResponse NOT_FOUND_API_RESPONSE;
    
    
        static {
            MediaType mediaType = new MediaType();
            mediaType.setSchema(new StringSchema());
    
            Content content = new Content();
            content.addMediaType("*/*", mediaType);
    
            NOT_FOUND_API_RESPONSE = new ApiResponse()
                    .description("Not Found")
                    .content(content);
        }
    
        /**
         * Customize operation.
         *
         * @param operation     input operation
         * @param handlerMethod original handler method
         * @return customized operation
         */
        @Override
        public Operation customize(Operation operation, HandlerMethod handlerMethod) {
            Method method = handlerMethod.getMethod();
            List<Class<?>> exceptions = Arrays.asList(method.getExceptionTypes());
    
            if(exceptions.contains(NotFoundException.class)){
                ApiResponses apiResponses = operation.getResponses();
                apiResponses.addApiResponse("404", NOT_FOUND_API_RESPONSE);
            }
    
            return operation;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-26
      • 2019-09-19
      • 2019-01-24
      • 2018-12-30
      • 2020-02-05
      • 1970-01-01
      • 2020-12-21
      • 2021-10-28
      • 2020-11-10
      相关资源
      最近更新 更多