SpringBoot는 매우 상세한 Swagger2 프로세스를 통합합니다!

삑 하는 소리

머리말

이 글은 API 시각화 프레임워크인 Swagger를 SpringBoot 프레임워크에 통합하는 과정을 소개하고, 통합 과정에서 부딪히는 문제점을 논의하고, Swagger2의 일련의 콘텐츠를 테스트해 볼 것입니다.

Swagger에 대한 간략한 소개

Swagger는 RESTful 웹 서비스를 생성, 설명, 호출 및 시각화하기 위한 사양 및 완전한 프레임워크입니다. 전반적인 목표는 클라이언트와 파일 시스템이 서버와 동일한 속도로 업데이트되도록 하는 것입니다. 메서드, 매개변수 및 모델 문서화는 서버 측 코드에 긴밀하게 통합되어 API가 항상 동기화 상태를 유지할 수 있도록 합니다. Swagger를 사용하면 배포 관리와 강력한 API 사용이 그 어느 때보다 쉬워집니다.

준비

통합을 시작하기 전에 SpringBoot 프로젝트를 생성해야 합니다.이 문서에서 사용된 도구 및 버전은 다음과 같습니다.

프로젝트 콘텐츠
IDE 나는 그 생각을 이해한다
자바 만년 동안 변하지 않은 Java8
스프링부트 2.2.5.릴리스

SpringBoot 버전이 2.6 이상인 경우 기본 경로 일치 방법은 PathPatternMatcher이고 Swagger2는 AntPathMatcher를 기반으로 하며 documentationPluginsBootstrapper'가 있을 것이며 중첩 예외는 java.lang.NullPointer 오류입니다. 둘의 궁합! ! !

종속성 소개

이 기사에서는 Maven을 관리 도구로 사용하는 방법에 대해 설명합니다. Swagger2를 도입하는 두 가지 방법, 즉 스타터 방법과 기본 Maven 종속성 방법이 있습니다.

기본 Maven 종속성

Swagger2의 종속성은 Maven 창고 에서 찾을 수 있습니다 . 사용된 버전은 2.9.2이며 종속성은 여기에 게시됩니다.

<!-- swagger start -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
<!-- swagger end -->

스타터 소개

SpringForAll의 spring-boot-starter-swagger는 Spring Boot의 자동 구성 기능을 사용하여 swagger2를 스프링 부트 애플리케이션에 신속하게 도입하여 API 문서를 생성하고 swagger2의 기본 사용을 위한 통합 코드를 단순화합니다.

spring-boot-starter-swagger의 GitHub 페이지에 매우 자세한 소개 및 통합 자습서가 있으므로 여기서는 너무 자세히 설명하지 않고 이러한 방식으로 통합해야 하는 경우 spring-boot로 이동하십시오. -스타터- 스웨거 .

기타 의존성

롬복

swagger2 및 SpringBoot의 종속성 외에도 Lombok을 도입하여 일부 get/set/toString 메서드 작성을 줄이고 전임자가 만든 휠을 합리적으로 사용합니다.

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>

물론 IDEA를 활용하여 프로젝트를 만들 때 Lombok을 도입하는 것이 불가능한 것은 아닙니다.

commons-lang3

commons-lang3에는 많은 도구 클래스가 있으며 여기에서도 인용합니다.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.9</version>
</dependency>

구성

여기서는 여전히 기본 Maven 종속성의 통합에 중점을 둡니다.구성을 위해 구성 파일을 사용하는 Starter와 달리 기본 메서드는 구성 클래스를 사용하여 구성해야 합니다.

물론 이 기사에서는 구성 클래스와 구성 파일을 함께 사용하여 유연하지 않은 구성 문제도 해결할 수 있습니다.

Swagger 속성

여기서는 Swagger2 구성 클래스에 필요한 매개변수를 Properties 클래스로 캡슐화합니다. src/main/java 패키지에서 Properties 클래스를 저장할 config/properties 패키지를 만듭니다.

package com.javafeng.boxcloud.config.properties;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;

import java.util.List;

@Data
@Component
@ConfigurationProperties(prefix = "swagger")
public class SwaggerProperties {
    
    
    // 是否启用Swagger
    private boolean enable;

    // 扫描的基本包
    @Value("${swagger.base.package}")
    private String basePackage;

    // 联系人邮箱
    @Value("${swagger.contact.email}")
    private String contactEmail;

    // 联系人名称
    @Value("${swagger.contact.name}")
    private String contactName;

    // 联系人网址
    @Value("${swagger.contact.url}")
    private String contactUrl;

    // 描述
    private String description;

    // 标题
    private String title;

    // 网址
    private String url;

    // 版本
    private String version;
}

application.yml

다음으로 application.yml 또는 application.properties 구성 파일을 구성합니다. 이 문서에서는 Properties 클래스와 일치하는 application.yml을 사용합니다.

spring:
  application:
    name: BoxCloud
swagger:
  # 是否启用
  enable: true
  base:
    # 扫描的包,多个包使用逗号隔开
    package: com.javafeng
  contact:
    email: [email protected]
    name: JAVAFENG
    url: https://www.javafeng.com
  description:
  title: ${
    
    spring.spring.name} API Document
  url: https://www.javafeng.com
  version: @project.version@

Swagger2Config

매개변수가 구성된 후 Swagger2Config를 구성합니다. 여기서는 spring-boot-plus 의 구성 방법 을 참조 하고 몇 가지 단순화합니다.

package com.javafeng.boxcloud.config;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.javafeng.boxcloud.config.properties.SwaggerProperties;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.RequestHandler;
import springfox.documentation.annotations.ApiIgnore;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Arrays;

@Configuration
@EnableSwagger2
public class Swagger2Config {
    
    
    @Autowired
    private SwaggerProperties swaggerProperties;

    // 扫描多包时,包路径的拆分符,分号
    private static final String SPLIT_COMMA = ",";

    // 扫描多包时,包路径的拆分符,逗号
    private static final String SPLIT_SEMICOLON = ";";

    // Swagger忽略的参数类型
    private Class<?>[] ignoredParameterTypes = new Class[]{
    
    
            ServletRequest.class,
            ServletResponse.class,
            HttpServletRequest.class,
            HttpServletResponse.class,
            HttpSession.class,
            ApiIgnore.class
    };

    @Bean
    public Docket createRestApi() {
    
    
        // 获取需要扫描的包
        String[] basePackages = getBasePackages();
        ApiSelectorBuilder apiSelectorBuilder = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select();
        // 如果扫描的包为空,则默认扫描类上有@Api注解的类
        if (ArrayUtils.isEmpty(basePackages)) {
    
    
            apiSelectorBuilder.apis(RequestHandlerSelectors.withClassAnnotation(Api.class));
        } else {
    
    
            // 扫描指定的包
            apiSelectorBuilder.apis(basePackage(basePackages));
        }
        Docket docket = apiSelectorBuilder.paths(PathSelectors.any())
                .build()
                .enable(swaggerProperties.isEnable())
                .ignoredParameterTypes(ignoredParameterTypes);
        return docket;
    }

    /**
     * 获取apiInfo
     * @return
     */
    private ApiInfo apiInfo() {
    
    
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description(swaggerProperties.getDescription())
                .termsOfServiceUrl(swaggerProperties.getUrl())
                .contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
                .version(swaggerProperties.getVersion())
                .build();
    }

    /**
     * 获取扫描的包
     *
     * @return
     */
    public String[] getBasePackages() {
    
    
        String basePackage = swaggerProperties.getBasePackage();
        if (StringUtils.isBlank(basePackage)) {
    
    
            throw new RuntimeException("Swagger basePackage不能为空");
        }
        String[] basePackages = null;
        if (basePackage.contains(SPLIT_COMMA)) {
    
    
            basePackages = basePackage.split(SPLIT_COMMA);
        } else if (basePackage.contains(SPLIT_SEMICOLON)) {
    
    
            basePackages = basePackage.split(SPLIT_SEMICOLON);
        }
        return basePackages;
    }

    public static Predicate<RequestHandler> basePackage(final String[] basePackages) {
    
    
        return input -> declaringClass(input).transform(handlerPackage(basePackages)).or(true);
    }

    private static Function<Class<?>, Boolean> handlerPackage(final String[] basePackages) {
    
    
        return input -> {
    
    
            // 循环判断匹配
            for (String strPackage : basePackages) {
    
    
                boolean isMatch = input.getPackage().getName().startsWith(strPackage);
                if (isMatch) {
    
    
                    return true;
                }
            }
            return false;
        };
    }
    @SuppressWarnings("deprecation")
    private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
    
    
        return Optional.fromNullable(input.declaringClass());
    }
}

knife4j 강화

Enhancement의 구성이 간단하고 Enhancement 사용의 효율성이 높기 때문에 이 부분의 콘텐츠를 고급화했습니다. 이전과 함께 설명하지 않은 이유는 Swagger에서 나온 것과 knife4j에서 나온 것을 구분하기 쉽도록 이해하기 쉽기 때문입니다.

이 기사에서는 Swagger의 향상된 기능으로 knife4j를 통합하고 pom에 종속성을 추가합니다.

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>2.0.2</version>
</dependency>

application.yml에 다음 구성을 추가합니다.

knife4j:
  enable: ${swagger.enable} -- knife4j启用与否取决于Swagger是否启用
  basic:
    enable: true
    username: admin
    password: admin

Swagger2Config를 수정하고 knife4j를 활성화하기 위한 관련 메모를 추가합니다.

......
@Configuration
@EnableSwagger2
@EnableKnife4j
public class Swagger2Config {
  ......
}

knife4j의 자세한 구성은 필요에 따라 공식 웹 사이트에서 확인할 수 있습니다.

Knife4j 2.0.6 이상, @EnableKnife4j 주석을 사용할 필요 없이 구성 파일에서 knife4j.enable = true를 구성하기만 하면 됩니다. 여기서 구분하기 위해 데모용으로 2.0.2를 사용한다.

시험

위의 단계가 완료되면 기본적으로 예비 구성 작업이 완료되며 브라우저에서 직접 액세스할 수 있습니다: http://localhost:8080/swagger-ui.html, 구성이 완료되었음을 나타내는 다음 인터페이스가 나타납니다. 성공적인:

여기에 이미지 설명 삽입

향상이 구성되었으므로 knife4j를 사용하여 확인하는 것이 좋습니다. http://localhost:8080/doc.html을 방문하면 향상 구성이 성공했음을 나타내는 다음 인터페이스가 나타납니다(이 페이지 전에 사용자 이름과 암호가 필요한 페이지는 구성을 따르십시오. 작성하십시오):

여기에 이미지 설명 삽입

사용

이 부분의 스크린샷은 knife4j 페이지의 스크린샷이며 표시 효과와 페이지 논리가 더 명확합니다.

다음으로 컨트롤러를 생성하고 테스트를 위한 일부 인터페이스를 선언합니다.여기에서는 사용자 추가, 삭제, 확인 및 수정, 아바타 업로드 및 로그인과 같은 기능을 시뮬레이션하여 Swagger2를 전반적으로 사용하는 방법을 보여줍니다. 클래스에 나타나는 Swagger2 주석은 클래스가 끝난 후 소개될 예정입니다(공통 속성만 소개되며, 심층 연구가 필요한 경우 공식 웹사이트의 문서를 참조하는 것이 좋습니다).

실제로 여기에서 구별해야 할 몇 가지 상황이 있습니다.

  • 입력 매개변수가 엔티티 클래스인지 여부
  • 응답이 엔티티 클래스인지 여부

위에서 언급한 Api 인터페이스 중 간단한 분석:

  • 새 인터페이스, 수정된 인터페이스, 로그인 인터페이스 및 기타 입력 매개변수는 엔티티 클래스이고 기타 입력 매개변수는 비엔티티 클래스입니다.
  • 검색 인터페이스의 응답은 엔터티 클래스이고 나머지 응답은 비엔티티 클래스입니다.

다른 상황에 따라 다른 Swagger 주석이 처리에 사용됩니다.

엔티티 클래스

import lombok.Data;

@Data
@ApiModel(value = "用户", description = "查询用户")
public class Users {
    
    
    @ApiModelProperty(value = "ID", example = "1")
    private Integer id;
    @ApiModelProperty(value = "用户名")
    private String username;
    @ApiModelProperty(value = "密码")
    private String password;
    @ApiModelProperty(value = "头像")
    private String avatar;

    public Users(Integer id, String username, String password, String avatar) {
    
    
        this.id = id;
        this.username = username;
        this.password = password;
        this.avatar = avatar;
    }

    public Users() {
    
    
    }
}

@ApiModel

주석/공통 속성 설명하다
@ApiModel 엔터티 클래스(모델)를 수정하는 데 사용되며 엔터티 클래스에 대한 설명으로 간주할 수 있습니다.
 값 모델의 대체 이름
 설명 수업에 대한 자세한 설명

@ApiModelProperty

주석/공통 속성 설명하다
@ApiModelProperty 필드의 모든 측면에 대한 설명 및 제한으로 간주될 수 있는 엔터티 클래스 필드를 수정하는 데 사용됩니다.
 값 필드 설명
 이름 원래 필드 이름을 재정의하는 새 필드 이름
 예 기본값(이 필드가 문자열 유형인 경우 기본값은 ""임)
 허용 가능한 값
제한된 값 목록({1,2,3}), 범위 값([1,5]), 최대/최소 값([1, infinity] infinity 또는 -infinity는 무한을 의미함) 으로 표현되는 이 필드의 값 범위를 제한합니다. 가치)
 필수의 이 필드가 필수인지 여부를 표시합니다. 기본값은 false입니다.
 숨겨진 필드가 숨겨져 있는지 표시, 기본값은 false

엔터티 클래스를 입력 매개변수로 사용할 때 위의 주석을 사용하여 엔터티 클래스 매개변수를 설명하는 목적을 달성하기 위해 엔터티 클래스를 수정할 수 있습니다.

제어 장치

여기에서 컨트롤러는 상황에 따라 별도로 설명합니다.첫 번째는 Controller 컨트롤러 클래스의 정의입니다.

package com.javafeng.boxcloud.controller;

import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
@Api(tags = {
    
    "用户管理"})
public class UsersController {
    
    
   /** 此处编写Api接口方法 **/
   /** --start-- **/
   /** --end-- **/
}
주석/공통 속성 설명하다
@아피 인터페이스 그룹이라고 할 수 있는 Controller를 꾸미기 위해 사용되며, 이 클래스의 Api는 자동으로 문서를 생성합니다.
 태그 인터페이스 그룹의 이름으로 간주될 수 있습니다.

다음은 인터페이스 메소드의 정의입니다.이 섹션의 시작 부분에서 인터페이스 메소드의 중앙 매개 변수 및 응답에 대해 배웠습니다.여기서 이러한 다양한 상황을 설명합니다.

  1. 입력 매개변수로서의 엔티티 클래스

새 인터페이스와 수정된 인터페이스는 모두 입력 매개변수로서의 엔티티 클래스입니다.

@PostMapping("/add")
@ApiOperation(value = "新增用户", notes = "用户不得为空")
public Boolean add(@RequestBody Users user) {
    
    
    return true;
}

@PostMapping("/update")
@ApiOperation(value = "修改用户", notes = "用户不得为空")
public Boolean update(@RequestBody Users user) {
    
    
    return true;
}

@ApiOperation

주석/공통 속성 설명하다
@ApiOperation 인터페이스 그룹이라고 할 수 있는 Controller를 꾸미기 위해 사용되며, 이 클래스의 Api는 자동으로 문서를 생성합니다.
 값 API 인터페이스 이름
 노트 인터페이스 설명
 태그 추가 인터페이스 그룹 정의
예: @Api(tags = 'User Management')에 인터페이스 그룹이 정의된 경우에도 이 주석에 @ApiOperation(tags = 'Account Management')와 같은 다른 인터페이스 그룹을 지정할 수 있으므로 이 인터페이스는 동시에 두 인터페이스 그룹(사용자 관리 및 계정 관리)에 나타날 수 있습니다.

엔터티 클래스를 입력 매개변수로 사용할 때 해당 매개변수 설명 주석 및 사용법은 앞선 [엔티티 클래스] 부분에서 소개했으며, @ApiOperation을 제외한 다른 주석(@ApiModel, @ApiModelProperty)은 여기서는 설명하지 않는다.

여기에 이미지 설명 삽입

  1. 비엔티티 클래스를 입력 매개변수로 사용

비엔티티 클래스를 입력 매개변수로 사용하는 경우 다음과 같은 상황으로 세분할 수 있습니다.

  • 일반 쿼리 매개변수

여기에서 특정 사용자를 찾는 매개변수를 공통 매개변수의 Api 메소드로 정의합니다.

@GetMapping("/get")
@ApiOperation(value = "查询单个用户")
@ApiImplicitParams({
    
    
        @ApiImplicitParam(name = "id",
                value = "用户ID",
                required = true,
                paramType = "query"
        )
})
public Users get(@RequestParam("id") Integer id) {
    
    
    return new Users(id, "admin", "123456", "/resource/image/head.png");
}

@ApiImplicitParams 및 ApiImplicitParam

주석/공통 속성 설명하다
@ApiImplicitParams 요청 매개변수를 선언하도록 Api 인터페이스 메소드 수정
 @ApiImplicitParam @ApiImplicitParams에 정의된 각 @ApiImplicitParam은 매개변수에 해당합니다.
  이름 매개변수 이름
[일반적으로 입력 매개변수 이름에 해당]
  값 매개변수 설명
  필수의 이 매개변수가 필요한지 여부를 표시합니다. 기본값은 false입니다.
  paramType 경로, 쿼리, 본문, 양식, 헤더 등을 포함하여 매개변수의 위치를 ​​표시합니다.
[일반적으로 본문 및 양식은 엔터티 클래스를 입력 매개변수로 사용하는 것이 좋습니다.]

여기에 이미지 설명 삽입

  • 경로 매개변수
@DeleteMapping("/delete/{id}")
@ApiOperation(value = "删除用户", notes = "用户ID不得为空")
@ApiImplicitParams({
    
    
        @ApiImplicitParam(name = "id",
                value = "用户ID",
                required = true,
                paramType = "path"
        )
})
public Boolean delete(@PathVariable("id") Integer id) {
    
    
    return true;
}

매개변수가 경로 매개변수인 경우 @ApiImplicitParam의 paramType 값은 경로여야 하며 동시에 @PathVariable 주석을 사용하여 경로 매개변수를 수정합니다.

@PathVariable 어노테이션은 위 인터페이스의 {id}와 같이 URL에서 템플릿을 식별할 수 있으며, Swagger 어노테이션에 속하지 않는 템플릿을 기반으로 매개변수가 획득되었음을 표시할 수 있으며 여기서 소개하지 않습니다. .

여기에 이미지 설명 삽입

  • 헤더 매개변수
@PostMapping("/login")
@ApiOperation(value = "登录")
@ApiImplicitParams({
        @ApiImplicitParam(name = "username",
                value = "用户名",
                required = true,
                paramType = "header"
        ),
        @ApiImplicitParam(name = "password",
                value = "密码",
                required = true,
                paramType = "header"
        )
})
public Boolean login(@RequestHeader("username") String username,@RequestHeader("password")  String password) {
    System.out.println(username + password);
    return true;
}

매개변수가 경로 매개변수인 경우 @ApiImplicitParam의 paramType 값은 헤더여야 하며 동시에 @RequestHeader 주석을 사용하여 매개변수를 수정하고 헤더에서 얻은 매개변수의 획득 위치를 표시하여 SpringMVC가 Header. 매개변수에서 올바르게 가져올 수 있습니다.

여기에 이미지 설명 삽입

  • 파일 매개변수

여기에서는 복잡한 상황을 직접 설명합니다. 즉, 파일 매개변수와 공통 매개변수를 동시에 포함하는 것을 고려하고 실제 개발 과정에서 필요에 따라 수정합니다.

@PostMapping("/upload")
@ApiOperation(value = "上传头像", notes = "参数需要头像文件以及对应用户ID")
@ApiImplicitParams({
    
    
        @ApiImplicitParam(name = "id",
                value = "该头像对应的用户ID",
                required = true
        )
})
public Boolean upload(@ApiParam(value = "图片文件", required = true) @RequestParam("avatar") MultipartFile avatar, @RequestParam("id") Integer id) {
    
    
    System.out.println(avatar);
    return true;
}

对于非文件参数的普通参数,参照第一条【普通查询参数】中的声明方式即可;

对于文件参数,则需要使用@ApiParam对参数进行修饰;

@ApiParam

注解/常用属性 说明
@ApiImplicitParams 修饰Api接口方法,用来声明请求参数
 value 参数名称
 required 标记该参数是否必需,默认false
 allowMultiple 是否允许多个文件,默认false

同样的,需要在参数上使用@RequestParam进行修饰。

여기에 이미지 설명 삽입

这里插入一个解释,就是对于同时出现Swagger注解(一般以Api作为前缀)和非Swagger注解同时对参数进行修饰时,并不会彼此影响,Swagger注解只是用来对Api方法进行描述,并不会对该方法造成实质影响,

而例如@RequestParam、@RequestHeader在内的注解是决定SpringMVC是否能正确读取到参数的关键

这里对于两种注解之间的侵入性,掘金大佬1黄鹰在其源码剖析@ApiImplicitParam对@RequestParam的required属性的侵入性做了深入剖析,感兴趣的可以去看看

  1. 实体类作为响应

当实体类作为响应时,通常在实体类上的注解所生成的描述也会作为响应的描述出现,在此处不再进行赘述。

여기에 이미지 설명 삽입

  1. 非实体类作为响应

我们对新增接口进行修改,在其方法上添加@ApiResponses来对响应进行描述:

@PostMapping("/add")
@ApiOperation(value = "新增用户", notes = "用户不得为空")
@ApiResponses({
        @ApiResponse(code = 200, message = "添加成功"),
        @ApiResponse(code = 500, message = "服务器错误"),
        @ApiResponse(code = 400, message = "参数异常")
})
public Boolean add(@RequestBody Users user) {
    return true;
}

需要注意的是,Swagger无法对非实体类响应进行详细描述,只能通过@ApiResponses和@ApiResponse描述响应码信息。同时,在以实体类作为响应时,同样可也以使用@ApiResponses和@ApiResponse。

여기에 이미지 설명 삽입

Token处理

在做前后端分离的应用时,后端接口通常会要求在Header中添加Token以保证安全性,这里我们依然是参考SpringBootPlus的处理方式,对Token进行处理。

需要注意的是,此处的Token处理是基于Swagger进行接口测试时的,并不是对接口如何增加Token进行讲解,只是对有Token的接口如何通过Swagger进行测试做出讲解。

修改SwaggerProperties

思路是,在Swagger配置中添加默认的全局参数描述,对Token进行处理,这里我们默认Token信息附加在Header中。

首先在SwaggerProperties中新增以下内容:

@NestedConfigurationProperty
private List<ParameterConfig> parameterConfig;

// 自定义参数配置
@Data
public static class ParameterConfig {
    
    
    // 名称
    private String name;
    // 描述
    private String description;
    // 参数类型
    // header, cookie, body, query
    private String type = "head";
    // 数据类型
    private String dataType = "String";
    // 是否必填
    private boolean required;
    // 默认值
    private String defaultValue;
}

修改application.yml

随后在application.yml中对新增部分编写对应的配置项,这里贴出整体内容,自定义参数配置部分为新增内容:

spring:
  application:
    name: BoxCloud
    
swagger:
  enable: true
  base:
    package: com.javafeng
  contact:
    email: [email protected]
    name: JAVAFENG
    url: https://www.javafeng.com
  description:
  title: ${spring.application.name} API Document
  url: https://www.javafeng.com
  version: @project.version@
  # 自定义参数配置,可配置N个
  parameter-config:
    - name: token
      description: Token Request Header
      # header, cookie, body, query
      type: header
      data-type: String
      required: false
      # 测试接口时,自动填充token的值
      default-value:
      
knife4j:
  enable: ${swagger.enable}
  basic:
    enable: true
    username: admin
    password: admin

这里可以根据不同的需求,配置多个自定义参数,这里只演示了Token一个参数,如果是多个参数的话,配置多个即可,如下:

parameter-config:
   - name: param1
     description: This is param1
     type: header
     data-type: String
     required: false
     default-value:
 parameter-config:
   - name: param2
     description: This is param2
     type: header
     data-type: String
     required: false
     default-value:
 parameter-config:
   - name: param3
     description: This is param3
     type: header
     data-type: String
     required: false
     default-value:

修改Swagger2Config

接下来,我们在Swagger2Config中对Token参数进行处理,首先在Swagger2Config中添加如下方法,从application.yml中获取到配置的额外Token参数并进行封装:

/**
 * 添加额外参数
 *
 * @return
 */
private List<Parameter> getParameters() {
    
    
    // 获取自定义参数配置
    List<SwaggerProperties.ParameterConfig> parameterConfig = swaggerProperties.getParameterConfig();
    if (CollectionUtils.isEmpty(parameterConfig)) {
    
    
        return null;
    }
    List<Parameter> parameters = new ArrayList<>();
    parameterConfig.forEach(parameter -> {
    
    
        // 设置自定义参数
        parameters.add(new ParameterBuilder()
                .name(parameter.getName())
                .description(parameter.getDescription())
                .modelRef(new ModelRef(parameter.getDataType()))
                .parameterType(parameter.getType())
                .required(parameter.isRequired())
                .defaultValue(parameter.getDefaultValue())
                .build());
    });
    return parameters;
}

随后修改createRestApi方法,在声明Docket的位置添加对额外参数的处理,添加后如下:

... ...
Docket docket = apiSelectorBuilder.paths(PathSelectors.any())
        .build()
        .enable(swaggerProperties.isEnable())
        .ignoredParameterTypes(ignoredParameterTypes)
        .globalOperationParameters(getParameters()); // 此处为新增
... ...

重启项目后,我们随意打开一个接口的文档,这里我们打开的是knife4j的页面,选择调试,在请求头部位置就可以看到Token的相关内容:

여기에 이미지 설명 삽입

当然,在Swagger的原生界面也可以看到:

여기에 이미지 설명 삽입

参考和引用

  1. dynamicbeamswagger2常用注解API,来源 CSDN
  2. 随风行云Spring Boot整合swagger使用教程,来源 CNBLOG
  3. 1 Yellow Eagle : @ApiImplicitParam이 @RequestParam의 필수 속성 , 소스 Nuggets 에 대한 침입성에 대한 소스 코드 분석
  4. 스프링부트플러스

추천

출처blog.csdn.net/u012751272/article/details/127101042