SpringBoot集成Swagger3接口文档及添加Authorization授权

Posted LO嘉嘉VE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot集成Swagger3接口文档及添加Authorization授权相关的知识,希望对你有一定的参考价值。

swagger可以为前端提供接口文档及接口测试功能,后端集成起来很方便,对代码也没有入侵,全注解完成,非常好用。

一、集成基础功能

第一步、添加依赖

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

 第二步、创建配置文件Swagger3Config

@Configuration
@EnableOpenApi
public class Swagger3Config 

    @Bean
    public Docket docket() 
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
                // 自行修改为自己的接口路径,不配置扫描全部路径
                .apis(RequestHandlerSelectors.basePackage("com.by.hellosecurityresource.controller"))
                .paths(PathSelectors.any())
                .build();
    

    private ApiInfo apiInfo() 
        return new ApiInfoBuilder()
                .title("Swagger3 API文档")
                .description("RESTFul 风格接口")
                .version("1.0")
                .build();
    



第三步、给接口添加注解

@Api(tags = "测试不需要登录验证就能访问的接口")

@RestController
@RequestMapping("/noAuth")
public class NoAuthController 

    /**
     * 服务对象
     */
    private TestService testService;

    public NoAuthController(TestService testService) 
        this.testService = testService;
    

    @Operation(summary = "获取test列表数据")
    @RequestMapping(value = "", method = RequestMethod.GET)
    public Page<STest> list(@RequestParam @Parameter(description = "页数从1开始", required = true) int page,
                            @RequestParam @Parameter(description = "每页的条数", required = true) int limit,
                            HttpServletRequest request) 

        return testService.list(page - 1, limit);

    

Api  给Controller添加的注解

Operation 给Contoller里的方法添加的注解

Parameter 给方法中参数添加的注解

Schema 给实体类及其变量添加的注解

@Schema(description = "test数据")
@Setter
@Getter
public class TestRequestBean 

    @Schema(description = "测试字段1")
    private String test;

    @Schema(description = "测试字段2")
    private String value;
    

访问地址: baseUrl/swagger-ui/index.html

 二、让swgger文档支持授权访问

修改配置文件,使swagger支持添加token

@Configuration
@EnableOpenApi
public class Swagger3Config 

    @Bean
    public Docket docket() 
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
                // 自行修改为自己的接口路径,不配置扫描全部路径
                .apis(RequestHandlerSelectors.basePackage("com.by.hellosecurityresource.controller"))
                .paths(PathSelectors.any())
                .build()//;
                .securitySchemes(securitySchemes())
                .securityContexts(Collections.singletonList(securityContext()));
    

    private ApiInfo apiInfo() 
        return new ApiInfoBuilder()
                .title("Swagger3 API文档")
                .description("RESTFul 风格接口")
                .version("1.0")
                .build();
    

    private List<SecurityScheme> securitySchemes() 
        List<SecurityScheme> apiKeyList= new ArrayList<>();
        //注意,这里应对应登录token鉴权对应的k-v
        apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
        return apiKeyList;
    

    /**
     * 这里设置 swagger2 认证的安全上下文
     */
    private SecurityContext securityContext() 
        return SecurityContext.builder()
                .securityReferences(Collections.singletonList(new SecurityReference("Authorization", scopes())))
                .build();
    

    /**
     * 这里是写允许认证的scope
     */
    private AuthorizationScope[] scopes() 
        return new AuthorizationScope[]
                new AuthorizationScope("web", "All scope is trusted!")
        ;
    


ResourseServer配置中,过滤以下路径,使不通过验证就能访问到,否则无法打开swagger文档

"/swagger-ui/**"
"/swagger-resources/**"
"/v3/**"

示例代码如下

    @Override
    public void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests()
                .antMatchers("/noAuth/**", "/swagger-ui/**", "/swagger-resources/**", "/v3/**").permitAll() //设置/oauth/**的接口不需要授权就可以访问
                .anyRequest().authenticated();
    

 再次访问接口文档,会有此按钮标记 

 点击可输入token

这样,在swagger中测试接口的时候就会带上token了。

三、生产服务器注意关闭swagger文档 

在applicaiton中添加配置

springfox:
  documentation:
    auto-startup: false #false关闭swagger文档 true打开swagger

测试代码地址:

Hello-Security: OAuth2授权服务器

SpringBoot集成Swagger2生成API接口文档

SpringBoot2.3.0集成Swagger2

背景:最近在工作中发现,已经多次发现后台开发人员提供的接口协议和实际的业务代码不统一。这些现象往往都是因为开发人员在对接口协议调整后没有及时进行协议文档的更新造成的。

引入Swagger2相应的依赖

在SprintBoot中引入Swagger2依赖包很简单,在pom.xml文件中引入相应的依赖即可。

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

入门示例

我们创建一个入门的Springboot项目。项目整体目录结构如下:

然后编写一个DemoController类,在类中添加几个方法,具体如下:

package com.majing.learning.springboot.swagger2.controller;

import com.majing.learning.springboot.swagger2.entity.User;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@Api(tags = "用户管理相关接口")
@RequestMapping(value="/users")
public class DemoController 

    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());

    static
        users.put(1L, new User(1L,"majing1", "31"));
        users.put(2L, new User(2L,"majing2", "32"));
        users.put(3L, new User(3L,"majing3", "33"));
        users.put(4L, new User(4L,"majing4", "34"));
    

    @ApiOperation(value="获取用户列表", notes="")
    @RequestMapping(value="", method= RequestMethod.GET)
    @ApiResponses(value=@ApiResponse(code=9001, message="OK"),@ApiResponse(code=9002, message="ERROR"))
    public List<User> getUserList() 
        List<User> r = new ArrayList<User>(users.values());
        return r;
    

    @ApiOperation(value="创建用户", notes="根据User对象创建用户")
    @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
    @RequestMapping(value="/", method=RequestMethod.POST)
    public String postUser(@RequestBody User user) 
        users.put(user.getId(), user);
        return "success";
    

    @ApiOperation(value="获取用户详细信息", notes="根据url的id来获取用户详细信息")
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long")
    @RequestMapping(value="/id", method=RequestMethod.GET)
    public User getUser(@PathVariable Long id) 
        return users.get(id);
    

    @ApiOperation(value="更新用户详细信息", notes="根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
    @ApiImplicitParams(
            @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
    )
    @RequestMapping(value="/id", method=RequestMethod.PUT)
    public String putUser(@PathVariable Long id, @RequestBody User user) 
        User u = users.get(id);
        u.setName(user.getName());
        u.setAge(user.getAge());
        users.put(id, u);
        return "success";
    

    @ApiOperation(value="删除用户", notes="根据url的id来指定删除对象")
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long")
    @RequestMapping(value="/id", method=RequestMethod.DELETE)
    public String deleteUser(@PathVariable Long id) 
        users.remove(id);
        return "success";
    



对于上面的实体类User定义如下:

package com.majing.learning.springboot.swagger2.entity;

import io.swagger.annotations.ApiModel;

@ApiModel
public class User 

    private Long id;
    private String name;
    private String age;

    public User(long id, String name, String age)
        this.id = id;
        this.name = name;
        this.age = age;
    

    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getAge() 
        return age;
    

    public void setAge(String age) 
        this.age = age;
    


为了使用Swagger2,需要在应用启动类同级目录加上Swagger2的配置及注解,具体如下:

package com.majing.learning.springboot.swagger2;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2Config 

    @Bean
    public Docket createRestApi() 
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.majing.learning.springboot.swagger2.controller"))
                .paths(PathSelectors.any())
                .build();
    

    private ApiInfo apiInfo() 
        return new ApiInfoBuilder()
                .title("Spring Boot中使用Swagger2构建RESTful APIs")
                .description("测试使用Swagger2生成API文档")
                .termsOfServiceUrl("https://***.com/")
                .contact("马靖")
                .version("1.0")
                .build();
    

接下来我们启动应用程序,然后访问http://localhost:5002/swagger-ui.html,即可看到自动生成的API文档。这里的端口根据需要在application.properties文件自行调整。

至此,在SpringBoot2中集成Swagger2便完成了,看了下生成的API文档,感觉还是不错的。

SpringBoot2集成Swagger2后启动报错

上面的示例是没问题的,但是最开始尝试集成Swagger2时遇到个启动报错,其中有一段错误信息如下:

AnnotationConfigServletWebServerApplicationContext: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'linkDiscoverers' defined in class path resource [org/springframework/hateoas/config/HateoasConfiguration.class]: Unsatisfied dependency expressed through method 'linkDiscoverers' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.plugin.core.PluginRegistry<org.springframework.hateoas.client.LinkDiscoverer, org.springframework.http.MediaType>' available: expected single matching bean but found 15: modelBuilderPluginRegistry,modelPropertyBuilderPluginRegistry,typeNameProviderPluginRegistry,documentationPluginRegistry,apiListingBuilderPluginRegistry,operationBuilderPluginRegistry,parameterBuilderPluginRegistry,expandedParameterBuilderPluginRegistry,resourceGroupingStrategyRegistry,operationModelsProviderPluginRegistry,defaultsProviderPluginRegistry,pathDecoratorRegistry,relProviderPluginRegistry,linkDiscovererRegistry,entityLinksPluginRegistry

刚开始看到这个错误有点懵逼,后来百度了下,说是Swagger2版本和Springboot版本不兼容导致,所以就修改了下Swagger2的版本,用了2.8.0,我自己的SpringBoot版本是2.3.0,重新启动了下,发现问题真的没有了。这里做个记录。

结语

上面我们通过Swagger2实现了后台代码动态生成和更新API文档,非常方便。但是有个缺点是没有访问权限的控制,数据Mock等功能。而且存在一定的代码侵入。后来针对国内外的API接口管理平台给调研了下,主要看了下ShowDoc、阿里云的RAP和CRAP-API,觉得都还挺好用的,有需要的可以自己研究下,这三个都是可以支持私有化部署的。

以上是关于SpringBoot集成Swagger3接口文档及添加Authorization授权的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot整合Swagger3生成接口文档

SpringBoot 集成FluentMyBatis 框架之完善

SpringBoot 集成Swagger3

SpringBoot: 后台接口文档 - 基于Swagger3

SpringBoot: 后台接口文档 - 基于Swagger3

SpringBoot: 后台接口文档 - 基于Swagger3