前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot实战之swagger整合

springboot实战之swagger整合

作者头像
lyb-geek
发布2019-11-07 17:21:11
1.4K0
发布2019-11-07 17:21:11
举报
文章被收录于专栏:Linyb极客之路

什么是swagger

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。

swagger的核心功能

  • 接口的文档在线自动生成。
  • 功能测试。

swagger常用注解说明

常用注解推荐查看如下链接,这边就不再论述

https://my.oschina.net/Rayn/blog/3064162

springboot与swagger整合

这边整合的内容有如下

  1. 接口文档生成与测试
  2. swagger分组
  3. 全局token以及局部token配置
  4. 与接口版本号进行集成

接口文档在线生成与测试

1、pom.xml引入

代码语言:javascript
复制
<dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
        <exclusions>
            <exclusion>
                <groupId>io.swagger</groupId>
                <artifactId>swagger-annotations</artifactId>
            </exclusion>
            <exclusion>
                <groupId>io.swagger</groupId>
                <artifactId>swagger-models</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.21</version>
        </dependency>

        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.5.21</version>
        </dependency>

ps:排除2.9.2版本的swagger-models和swagger-annotations,而引入1.5.21版本,是因为使用2.9.2版本时,当字段为数值型映射文档字段属性会出异常

2、创建Swagger的配置类

代码语言:javascript
复制
@Configuration
public class SwaggerConfig {




    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .version("1.0")
                .title("API接口文档 ")
                .description("API接口文档")
                .build();
    }



    @Bean
    public Docket createRestApi(){

        return new Docket(DocumentationType.SWAGGER_2).useDefaultResponseMessages(false)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.github.lybgeek.swagger"))
           .paths(PathSelectors.regex("/api.*")).build();

    }
}

3、在启动类上加上@EnableSwagger2注解

代码语言:javascript
复制
@SpringBootApplication
@EnableSwagger2
public class SwaggerSourceApplication
{
    public static void main( String[] args )
    {

        SpringApplication.run(SwaggerSourceApplication.class,args);
    }
}

4、在实体bean上加上@ApiModel注解,实体的字段上加上@ApiModelProperty注解

代码语言:javascript
复制
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ApiModel
public class BookDTO  {
  @ApiModelProperty(value = "编号", name = "id", example = "1")
  private Long id;

  @ApiModelProperty(value = "书名", name = "name", example = "swagger2入门")
  @NotNull(message = "书名不能为空")
  private String bookName;

  @ApiModelProperty(value = "作者", name = "author", example = "张三")
  @NotNull(message = "作者不能为空")
  private String author;

  @ApiModelProperty(value = "描述", name = "description", example = "swagger2入门实战")
  private String description;

  @ApiModelProperty(value = "价格", name = "price", example = "10")
  @NotNull(message = "价格不能为空")
  private BigDecimal price;

  @ApiModelProperty(value = "库存", name = "stock", example = "20")
  @NotNull(message = "库存不能为空")
  private Integer stock;


}

5、contoller层做形如下配置

代码语言:javascript
复制
@RestController
@RequestMapping(value={"/api/{version}/book","/book"})
@Slf4j
@Api(value = "书目管理", tags = {"书目管理"})

@ApiResponses({@ApiResponse(code = 200, message = "成功")})
public class BookController {

  @Autowired
  private BookService bookService;


  @PostMapping(value="/add")
  @ApiOperation(value = "添加书籍", notes = "添加书籍")
  public Result<BookDTO> addBook(@Valid BookDTO bookDTO, BindingResult bindingResult){
    Result<BookDTO> result = new Result<>();
    if (bindingResult.hasErrors()){
      return ResultUtil.INSTANCE.getFailResult(bindingResult, result);
    }
    try {
      BookDTO book = bookService.addBook(bookDTO);
      result.setData(book);
    } catch (Exception e) {
      log.error("addBook error:"+e.getMessage(),e);
      result.setStatus(Result.fail);
      result.setMessage(e.getMessage());
    }

    return result;

  }


  @PostMapping(value="/update")
  @ApiOperation(value = "更新书籍", notes = "更新书籍")
  public Result<BookDTO> upadteBook(BookDTO bookDTO){
    Result<BookDTO> result = new Result<>();
    if(bookDTO.getId() == null){
      result.setStatus(Result.fail);
      result.setMessage("id不能为空");
      return result;
    }
    BookDTO book = bookService.editBook(bookDTO);
    result.setData(book);
    return result;


  }


  @PostMapping(value="/del/{id}")
  @ApiOperation(value = "删除书籍", notes = "根据书籍编号删除书籍")
  @ApiImplicitParams({
          @ApiImplicitParam(name = "id", value = "书籍编号", dataType = "Long", required = true)
  })
  public Result<Boolean> delBook(@PathVariable("id")Long id){
    Result<Boolean> result = new Result<>();
    Boolean delFlag = bookService.delBookById(id);
    result.setData(delFlag);
    return result;

  }

  @PostMapping(value="/list")
  @ApiOperation(value = "查找书籍列表", notes = "根据查询条件查询书籍")
  public Result<List<BookDTO>> listUsers(BookDTO bookDTO){
    Result<List<BookDTO>> result = new Result<>();
    List<BookDTO> books = bookService.listBooks(bookDTO);
    result.setData(books);
    return result;
  }

  @PostMapping(value="/page")
  @ApiOperation(value = "书籍分页", notes = "根据查询条件查询书籍")
  @ApiImplicitParams({
          @ApiImplicitParam(name = "pageNo", value = "页码", dataType = "Integer", required = true),
          @ApiImplicitParam(name = "pageSize", value = "分页大小", dataType = "Integer", required = true)
  })
  public Result<PageResult<BookDTO>> pageUsers(BookDTO bookDTO,Integer pageNo,Integer pageSize){

    PageQuery<BookDTO> pageQuery = new PageQuery<>();
    pageQuery.setPageNo(pageNo);
    pageQuery.setPageSize(pageSize);
    pageQuery.setQueryParams(bookDTO);
    Result<PageResult<BookDTO>> result = new Result<>();
    PageResult<BookDTO> books = bookService.pageBook(pageQuery);
    result.setData(books);
    return result;
  }

  @PostMapping(value="/get/{id}")
  @ApiOperation(value = "查找书籍", notes = "根据书籍编号查找书籍")
  @ApiImplicitParams({
          @ApiImplicitParam(name = "id", value = "书籍编号", dataType = "Long", required = true)
  })
  public Result<BookDTO> getBookById(@PathVariable("id") Long id){
    Result<BookDTO> result = new Result<>();
    BookDTO book = bookService.getBookById(id);
    result.setData(book);
    return result;
  }






}

6、如果代码有配置拦截器,可以看具体需求看是否要拦截swagger相关页面,下面代码为不拦截swagger相关页面配置

代码语言:javascript
复制
@Configuration
public class IntercepterConfig implements WebMvcConfigurer {

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {

    registry.addResourceHandler("/static/**")
        .addResourceLocations("classpath:/static/");

  }

  @Bean
  public AuthIntercepors authIntercepors() {

    return new AuthIntercepors();
  }

  @Override
  public void addInterceptors(InterceptorRegistry registry) {

    registry.addInterceptor(authIntercepors()).addPathPatterns("/**")
        .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**","/swagger-ui.html","/doc.html","/docs.html");


  }
}

7、通过访问项目地址/swagger-ui.html,进入在线接口文档页面

swagger分组

swagger 分组只需在swagger配置加入groupName属性就行了,配置如下

代码语言:javascript
复制
@Configuration
public class SwaggerConfig {




    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .version("1.0")
                .title("API接口文档 ")
                .description("API接口文档")
                .build();
    }


    @Bean
    public Docket createRestApiWithApiVersion(){


        return new Docket(DocumentationType.SWAGGER_2).useDefaultResponseMessages(false)
                .apiInfo(apiInfo())
                .groupName(ApiVersionUtil.DEFAULT_API_VERSION)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.github.lybgeek.swagger"))
//                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
//                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.regex("/api.*")).build()




    }


    @Bean
    public Docket createRestApi(){


        return new Docket(DocumentationType.SWAGGER_2).useDefaultResponseMessages(false)
            .apiInfo(apiInfo())
            .groupName("default")
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.github.lybgeek.swagger"))
            .paths(PathSelectors.regex("(?!/api).+")).build();


    }

}

swagger设置局部token以及全局token

1、配置局部token

主要是在swagger配置中加入globalOperationParameters属性就行,其配置如下

代码语言:javascript
复制
@Configuration
public class SwaggerConfig {




    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .version("1.0")
                .title("API接口文档 ")
                .description("API接口文档")
                .build();
    }


    @Bean
    public Docket createRestApiWithApiVersion(){
        List<Parameter> pars = new ArrayList<>();
        ParameterBuilder tokenPar = new ParameterBuilder();
        tokenPar.name(Constant.ACCESS_TOKEN).description(Constant.ACCESS_TOKEN).modelRef(new ModelRef("string")).parameterType("header").required(true).build();

        pars.add(tokenPar.build());

        return new Docket(DocumentationType.SWAGGER_2).useDefaultResponseMessages(false)
                .apiInfo(apiInfo())
                .groupName(ApiVersionUtil.DEFAULT_API_VERSION)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.github.lybgeek.swagger"))
//                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
//                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.regex("/api.*")).build()
                .genericModelSubstitutes(ResponseEntity.class)
                 //每个接口单独传token
                .globalOperationParameters(pars);


    }

2、配置全局token

主要是在swagger配置中加入securitySchemes属性以及securityContexts属性,其配置如下

代码语言:javascript
复制
@Configuration
public class SwaggerConfig {




    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .version("1.0")
                .title("API接口文档 ")
                .description("API接口文档")
                .build();
    }



    @Bean
    public Docket createRestApi(){
        ParameterBuilder tokenPar = new ParameterBuilder();
        List<Parameter> pars = new ArrayList<>();
        tokenPar.name(Constant.ACCESS_TOKEN).description(Constant.ACCESS_TOKEN).modelRef(new ModelRef("string")).parameterType("header").required(true).build();
        pars.add(tokenPar.build());

        return new Docket(DocumentationType.SWAGGER_2).useDefaultResponseMessages(false)
            .apiInfo(apiInfo())
            .groupName("default")
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.github.lybgeek.swagger"))
//                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
//                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//                .paths(PathSelectors.regex("/api.*")).build()
            .paths(PathSelectors.regex("(?!/api).+")).build()
            .genericModelSubstitutes(ResponseEntity.class)
//            .globalOperationParameters(pars);
            //设置全局token
            .securitySchemes(securitySchemes())
            .securityContexts(securityContexts());

    }


    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Collections.singletonList(SecurityReference.builder()
            .reference(Constant.ACCESS_TOKEN)
            .scopes(authorizationScopes).build());
    }

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts=new ArrayList<>();
        securityContexts.add(
            SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex("(?!/api).+"))
                .build());
        return securityContexts;
    }




    private List<ApiKey> securitySchemes() {
        return newArrayList(
            new ApiKey(Constant.ACCESS_TOKEN, Constant.ACCESS_TOKEN, "header")
        )


}

swagger与接口版本号集成

1、接口版本号控制实现

因为这个接口版本号控制的实现,与本文的论述的关联不大,因此就不展开描述了。感兴趣的朋友,可以查看如下链接

https://www.jianshu.com/p/fd4a61c47b86

这篇文章讲述比较详细,但是里面有个实现细节有bug,如果大家是参考这篇文章进行实现就会发现。其bug的解决方案可参考如下链接

https://my.oschina.net/pwh19920920/blog/2413927

2、swagger与接口版本号集成

主要依然是在swagger配置中实现,其设置和局部token的设置方式一样,只是token是设置在header,版本号设置在path,其代码如下

代码语言:javascript
复制
@Configuration

public class SwaggerConfig {




    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .version("1.0")
                .title("API接口文档 ")
                .description("API接口文档")
                .build();
    }


    @Bean
    public Docket createRestApiWithApiVersion(){
        List<Parameter> pars = new ArrayList<>();
        ParameterBuilder tokenPar = new ParameterBuilder();
        tokenPar.name(Constant.ACCESS_TOKEN).description(Constant.ACCESS_TOKEN).modelRef(new ModelRef("string")).parameterType("header").required(true).build();
        ParameterBuilder versionPar = new ParameterBuilder();
        versionPar.name("version").description("version").modelRef(new ModelRef("string")).parameterType("path")
            .defaultValue(ApiVersionUtil.DEFAULT_API_VERSION).required(false).build();
        pars.add(tokenPar.build());
        pars.add(versionPar.build());

        return new Docket(DocumentationType.SWAGGER_2).useDefaultResponseMessages(false)
                .apiInfo(apiInfo())
                .groupName(ApiVersionUtil.DEFAULT_API_VERSION)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.github.lybgeek.swagger"))
//                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
//                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.regex("/api.*")).build()
                .genericModelSubstitutes(ResponseEntity.class)
                 //每个接口单独传token
                .globalOperationParameters(pars);


    }

配置比较符合国人使用习惯的UI

1、pom.xml配置

代码语言:javascript
复制
<dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.3</version>
        </dependency>

2、在swagger的配置类上,加上@EnableSwaggerBootstrapUI注解

代码语言:javascript
复制
@Configuration
@EnableSwaggerBootstrapUI
public class SwaggerConfig {

3、如果有配置拦截器,要放行doc.html

4、访问项目地址/doc.html

总结

本文介绍的内容大体都是平常使用swagger会经常碰到的,至于自定义接口文档排序等优先级不是那么高的就不再介绍。更多相关swagger的介绍,大家感兴趣可以查看

https://github.com/swagger-api/swagger-ui

或者访问官网

http://swagger.io

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-swagger

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是swagger
    • swagger的核心功能
      • swagger常用注解说明
      • springboot与swagger整合
        • 接口文档在线生成与测试
          • swagger分组
            • swagger设置局部token以及全局token
              • swagger与接口版本号集成
                • 配置比较符合国人使用习惯的UI
                • 总结
                • demo链接
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档