ホームページ  >  記事  >  Java  >  SpringBoot 統合 Swagger サンプル分析

SpringBoot 統合 Swagger サンプル分析

PHPz
PHPz転載
2023-05-16 08:34:131249ブラウズ

1. インターフェイス ドキュメントの概要

swagger は、人気のあるリアルタイム インターフェイス ドキュメント生成ツールです。現在のフロントエンドとバックエンドの分離プロジェクトでは、インターフェイス ドキュメントは不可欠なツールです。フロントエンドとフロントエンドの開発の前に、バックエンドはまずインターフェイス ドキュメントを作成する必要があります。フロントエンドは、インターフェイス ドキュメントに基づいてプロジェクトを開発します。双方の開発が完了した後、共同でデバッグとテストが実施されます。

つまり、インターフェイス文書は実際には開発前の両当事者間の合意です。通常、インターフェースドキュメントはオフラインとリアルタイムに分けられます。オフライン インターフェイス ドキュメント ツールには、Word (Wu 氏の発言に相当)、YAPI、Xiaoyaoji などが含まれます。この種のドキュメントはプログラマーによって作成される必要があり、一般にインターフェイス テスト機能が備わっています。通常、開発者はまずオフライン インターフェイス ドキュメントに情報を書き込み、それをリファレンス開発のためにフロントエンド担当者に渡します。最大の欠点は、インターフェイス プログラムが変更されると、戻って上記の内容をメンテナンスする必要があることです。これは非常に面倒で、本当に面倒です。

リアルタイム インターフェイス ドキュメントでは、コードに基づいて対応するインターフェイス ドキュメントを自動的に生成できます。利点は、コードが変更されると、生成されたインターフェイス ドキュメントが自動的に更新されることです。変更に注意を払う必要はありません。そして、時間通りにリリースする必要があります。ただし、コードに基づいて自動的に生成されるため、最大の欠点は、コードが非常に侵入的であり、インターフェイス ドキュメントを生成するための関連コードをプロジェクト コードに統合する必要があることです。リアルタイム インターフェイスのドキュメント化には多くのソリューションがありますが、Swagger は依然として最も影響力のあるソリューションの 1 つです。

2. SpringBoot Integrateds swagger2

公式サイトのアドレス: swagger.io もちろん公式サイトはすべて英語なので、かなり面倒そうです。とても簡単なので、私の手順に従うことをお勧めします。

同時に、一言言わせてください。swagger は、一般的に使用される 2 つのバージョン、swagger2 と swagger3 に分かれています。 2 つの違いはそれほど大きくなく、主に依存関係とアノテーションを最適化します。 Swagger2 では jar パッケージを 2 つ導入する必要がありますが、swagger3 では 1 つだけで済みますので、使い方に大きな違いはありません。以下では、swagger2 を例に挙げます。

2.1 依存関係の導入

<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>

2.2 構成の導入

最初に、アノテーション @EnableSwagger2 を追加する必要があります。このアノテーションを SpringBoot スタートアップ クラスに追加することも、構成クラスをカスタマイズしてそのアノテーションに配置することもできます。このアノテーションを追加した後、プロジェクトで Swagger 機能が有効になったことを意味します。

2 番目の方法を使用して構成クラスを独自に定義し、Docket 構成を追加することもできます。いわゆる Docket 構成は、名前や連絡先などの設定など、一連のインターフェイス ドキュメント (プロジェクトまたはバージョン) の構成です。

SwaggerConfig クラスを config フォルダーの下に追加します。

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    /**
     * 设置多个:
     *
     * @Bean
     *     public Docket appApi() {
     *
     *         List<Parameter> pars = new ArrayList<>();
     *         ParameterBuilder token = new ParameterBuilder();
     *         token.name("token").description("用户令牌").modelRef(new ModelRef("string")).parameterType("header").required(false)
     *                 .build();
     *         pars.add(token.build());
     *
     *         return new Docket(DocumentationType.SWAGGER_2).select().paths(regex("/app/.*")).build()
     *                 .globalOperationParameters(pars).apiInfo(pdaApiInfo()).useDefaultResponseMessages(false)
     *                 .enable(enableSwagger)
     *                 .groupName("appApi");
     *
     *     }
     *
     *     @Bean
     *     public Docket adminApi() {
     *
     *         List<Parameter> pars = new ArrayList<>();
     *         ParameterBuilder token = new ParameterBuilder();
     *         token.name("token").description("用户令牌").modelRef(new ModelRef("string")).parameterType("header").required(false)
     *                 .build();
     *         pars.add(token.build());
     *         return new Docket(DocumentationType.SWAGGER_2).select().paths(regex("/admin/.*")).build()
     *                 .globalOperationParameters(pars).apiInfo(pdaApiInfo()).useDefaultResponseMessages(false)
     *                 .enable(enableSwagger)
     *                 .groupName("adminApi");
     *
     *     }
     *
     *
     * @return
     */

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
                .apis(RequestHandlerSelectors.basePackage("com.lsqingfeng.action.swagger.controller")).paths(PathSelectors.any())
                .build().globalOperationParameters(setHeaderToken());

    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("action-swagger").description("swagger实战").termsOfServiceUrl("")
                .version("1.0").build();
    }

    /**
     * @Description: 设置swagger文档中全局参数
     * @param
     * @Date: 2020/9/11 10:15
     * @return: java.util.List<springfox.documentation.service.Parameter>
     */

    private List<Parameter> setHeaderToken() {
        List<Parameter> pars = new ArrayList<>();
        ParameterBuilder userId = new ParameterBuilder();
        userId.name("token").description("用户TOKEN").modelRef(new ModelRef("string")).parameterType("header")
                .required(true).build();
        pars.add(userId.build());
        return pars;
    }
}

上記は構成例であり、setToken メソッドも設定されています。これは、ドキュメントを生成するすべてのインターフェイスにヘッダー タイプのトークン パラメーターが含まれている必要があることを意味します。

2.3 コントローラに注釈を追加する

インターフェイス ドキュメントの直接の説明は、このインターフェイスの機能、パラメータの名前、パラメータの名前など、主にコントローラ レベルです。戻り値などこれらの値については、Swagger が対応するインターフェイス ドキュメントの生成に役立つように、コントローラーのメソッド、リクエスト パラメーター、および戻りパラメーターに対応するアノテーションを追加する必要があります。これは、先ほど述べた既存のコードへの侵入です。

ケースを書いてみましょう。

最初に vo パッケージを作成し、その中にリクエストと対応するパラメータを記述し、JavaBean を使用してリクエストとレスポンスのデータ構造を定義します。対応するアノテーションをここに追加する必要があることに注意してください:

リクエスト クラス:

package com.lsqingfeng.springboot.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @className: SwaggerReqVO
 * @description:
 * @author: sh.Liu
 * @date: 2022-03-22 19:19
 */
@Data
@ApiModel("创建Swagger请求参数")
public class SwaggerReqVO {

    @ApiModelProperty("id")
    private Integer id;

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("性别")
    private Integer gender;
}

レスポンス クラス:

package com.lsqingfeng.springboot.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @className: SwaggerResVO
 * @description:
 * @author: sh.Liu
 * @date: 2022-03-22 19:20
 */
@Data
@ApiModel("创建Swagger响应结果")
public class SwaggerResVO {

    @ApiModelProperty("id")
    private Integer id;

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("性别")
    private Integer gender;

    @ApiModelProperty("啥啥")
    private String what;
}

@ApiModel アノテーションと @@ApiModelProperty アノテーションは、ここで定義するために使用されます。インターフェイスドキュメントを生成するときに簡単に表示できるエンティティ名とフィールド名。

コントローラーをもう一度見てみましょう:

package com.lsqingfeng.springboot.controller;

import com.lsqingfeng.springboot.vo.SwaggerReqVO;
import com.lsqingfeng.springboot.vo.SwaggerResVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

/**
 * @className: SwaggerController
 * @description: swagger 接口测试
 * @author: sh.Liu
 * @date: 2022-03-22 19:18
 */
@RestController
@RequestMapping("/swagger")
@Api(value = "用户接口", tags = {"用户接口"})
public class SwaggerController {

    @ApiOperation("新增用户")
    @PostMapping("save")
    public String save(@RequestBody SwaggerReqVO req) {
        return "success";
    }

    @GetMapping("getById")
    @ApiOperation("根据条件查询用户")
    public SwaggerResVO getById(@RequestBody SwaggerResVO req) {
        return new SwaggerResVO();
    }
}

@Api アノテーションと @ApiOperation アノテーションは、それぞれインターフェイス グループ名とインターフェイス名をマークするために使用されます。それでは、プロジェクトを開始します。

SpringBoot 統合 Swagger サンプル分析

#このエラーが報告されているのを発見しました。

オンラインで検索する理由は、SpringBoot2.6 のバージョンが Swagger2.9.2 と互換性がないためです。 guava パッケージのバージョンが低すぎることが原因であるという人もいます。

これらをすべて個別に試してみましたが、guava の上位バージョンの依存関係を置き換えるという問題は依然として存在します。

この問題の主な理由は、SpringBoot のバージョンが高すぎることです。 SpringBoot2.5.x以前のバージョンをご利用の場合は問題ありません。

Spring Boot 2.6.X はパスの一致に PathPatternMatcher を使用します。Swagger によって参照される Springfox によって使用されるパスの一致は AntPathMatcher に基づいています。

したがって、これを解決したい場合は、設定を追加し、springBoot MVC の道路マッチング モードを変更します。

springBoot 設定ファイルに設定を追加します:

spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER

yml 形式の設定ファイルの場合:

SpringBoot 統合 Swagger サンプル分析

解決するにはもう一度やり直してください問題。

アクセスアドレス: ip:ポート番号/swagger-ui.html

SpringBoot 統合 Swagger サンプル分析

正常情况就可以看到我们的界面了。一会再说非正常情况。由于我们只给用户接口添加了注解,所有用户接口是可以直接观察中文文档的。而剩下的两个接口,由于没添加注解,所以都是以默认的形式展示的。

点开接口,我们可以看到接口中的想详细信息

SpringBoot 統合 Swagger サンプル分析

点击model,可以看到字段的中文描述。点击 Try it out,就可以直接调试接口。同时注意接口中都让填一个token,这就是我们之前的设置成效了。

SpringBoot 統合 Swagger サンプル分析

截止到目前其实swagger的集成就已经完毕了,主要就是根据我们的注解生成文档,并且可以在线调用调试。开发的时候,我们只需要把Controller这一层的请求和响应,以及方法描述等内容先开发完毕,就可以提供给前端让他们参照开发了。

2.4 [404]问题解决

正常情况我们按照上面的步骤就可以出现页面,但是有些时候可能是由于springBoot的版本过高导致的,我们输入之前的地址,出现404的情况,这个主要是由于项目中无法读取到swagger依赖包下的页面导致的。如果出现了这个问题,我们可以添加一个配置类,让他实现WebMvcConfigurer 接口,在添加一个方法:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");
    registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

完整代码如下:

package com.lsqingfeng.springboot.config;

import com.lsqingfeng.springboot.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @className: WebMvcConfig
 * @description:webMvc配置
 * @author: sh.Liu
 * @date: 2022-01-13 09:51
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

这个时候在启动就可以了!

2.5 替换UI

上面的整个过程已经完成了,但是生成的接口文档的页面,其实很多人不太喜欢,觉得不太符合国人的使用习惯,所有又有一些大神,提供了其他的UI测试页面。这个页面的使用还是比较广泛的。

修改方式:只需引入一个依赖包:

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
</dependency>

然后把刚才实现的那个的那个方法再添加一条:

registry.addResourceHandler("doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");

完成代码:

package com.lsqingfeng.springboot.config;

import com.lsqingfeng.springboot.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @className: WebMvcConfig
 * @description:webMvc配置
 * @author: sh.Liu
 * @date: 2022-01-13 09:51
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        //拦截
//        registry.addInterceptor(new TokenInterceptor())
//                .addPathPatterns("/**")
//                .excludePathPatterns("/login");
//    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");
    }
}

重新启动项目: 访问路径发生了变化:** ip:端口号/doc.html**

SpringBoot 統合 Swagger サンプル分析

页面出现了。我们在看看我们的用户接口:

SpringBoot 統合 Swagger サンプル分析

这个风格确实更加的直观,同时也是可以直接进行调试的。大部分的swagger都用的这个风格的文档。

三. SpringBoot集成swagger3

上面已经很详细的讲解了swagger2的集成方式,而swagger3的集成方式更加的简洁一些。

首先引入依赖:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-boot-starter</artifactId>
  <version>3.0.0</version>
</dependency>

然后是替换注解: swagger2使用的开启注解是: @EnableSwagger2

而在swagger3中,这个注解要换成: @EnableOpenApi

配置类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.OAS_30) // v2 不同
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.swaggerv3.controller")) // 设置扫描路径
                .build();
    }
}

要注意,里边的版本类型换成了 OAS_30, 就是swagger3的意思。

OAS 是 OpenAPI Specification 的简称,翻译成中文就是 OpenAPI 说明书。

同时访问地址:原始地址,也就是没换UI的地址: localhost:8080/swagger-ui/index.html这个要和swagger2区分开。

swagger3的原始UI风格也发生了一些变化:

SpringBoot 統合 Swagger サンプル分析

同时swagger3也是可以更换UI的。方法和swagger2一样。

四. swaggerUI 拦截器和跨域冲突处理

如果我们的项目中有关于跨域的处理,同时还有拦截器,然后还要使用swagger,这种情况大家要注意了,有可能我们的拦截器会将swagger中的页面路径拦截掉导致swagger页面出不来,当我们在拦截器中把swagger的页面排除掉的时候,也有可能会导致跨域配置的失效。

具体解决方案简单提一下:

拦截器:

/**
 * 拦截器配置
 *
 * @author liuShuai
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
 
    @Bean
    public TokenInterceptor tokenInterceptor() {
        return new TokenInterceptor();
    }
 
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
                .addInterceptor(tokenInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/user/downloadExcel")
                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
    }
 
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

跨域配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
 
/**
 * @className: CorsConfig
 * @description:
 * @author: sh.Liu
 * @date: 2020-12-02 10:16
 */
@Configuration
public class CorsConfig {
 
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.setAllowCredentials(true);
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        return new CorsFilter(configSource);
    }
}

用这两种方式去配置,就可以让他们和平共处了。

另: 配套项目代码已托管中gitCode: gitcode.net/lsqingfeng/…

分支: feautre/MybatisPlus

以上がSpringBoot 統合 Swagger サンプル分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。