# swagger

返回:一些功能解决

版本兼容

为什么是这个版本呢?我试了2.9.x,也试了2.7.x,
有一些问题只有2.8.0解决了,例如“接口返回示例”部分只有2.8.0按照Java类书写的顺序显示
其他版本是按照字符串顺序显示。
其他问题我就不一一列举了,大家尝试一下,也没必要一定使用2.8.0。更换版本的话只需要改一下 pom 里面的版本即可,其他配置不用变。

pom.xml文件增加依赖

<!-- https://mvnrepository.com/artifact/com.spring4all/swagger-spring-boot-starter -->
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>
1
2
3
4
5
6

在应用主类中增加@EnableSwagger2Doc注解

@EnableDiscoveryClient
@SpringBootApplication
@EnableSwagger2Doc
public class NacosServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosServerApplication.class, args);
    }
}
1
2
3
4
5
6
7
8

默认情况下就能产生所有当前Spring MVC加载的请求映射文档。

# 使用原生的swagger

返回顶部

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
1
2
3
4
5
6
7
8
9
10
11
12

@EnableSwagger2 使用@EnableSwagger2注解在Control类上就可以swagger的功能

@RequestMapping("/excel")
@Slf4j
@RestController
@EnableSwagger2
@Api(value = "Excel Controller", tags = "excel")
public class ExcelController {

    @GetMapping("/test")
    public void exportExcel(HttpServletRequest request, HttpServletResponse response){
        try(OutputStream out = response.getOutputStream()) {
        String fileName = "HTRING-TEST";
        response.setContentType("octets/stream");
        response.addHeader("Content-Disposition"
                    , "attachment;filename="+new String( fileName.getBytes("gb2312")
                        , "ISO8859-1" )+".xlsx");
            ExcelUtil.export(out,fileName, Arrays.asList("1","2","3","4","5"),this.genDataList());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 使用全局api结构

返回顶部

增加配置类

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestApi(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(getApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.chlm.mysession.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo getApiInfo(){
        return new ApiInfoBuilder().title("共享session工程通过Swagger构建APIs")
                .description("更多详情请咨询开发者")
                .termsOfServiceUrl("https://htring.org")
                .contact(new Contact("htring","https://htring.org","htring@mail.htring.org"))
                .version("1.0.0")
                .build();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

再通过createRestApi函数创建Docket的Bean之后,apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。
select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现,本例采用指定扫描的包路径来定义,Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被@ApiIgnore指定的请求)。

# 修改配置类做过滤

/**
     - 是否允许接口文档暴露
     */
    @Value("${swagger2.enable}")
    private boolean enableApiDoc;

    @Bean("DocApis")
    public Docket docApis(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("文档模块")
                .apiInfo(getApiInfo())
                .select()
//                .apis(RequestHandlerSelectors.basePackage("com.chlm.mysession.controller"))
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
//                .paths(PathSelectors.any())
                .paths(PathSelectors.regex("/export/.*"))
                .build()
                .enable(enableApiDoc);
    }

    @Bean("JobApis")
    public Docket jobApis(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("定时任务模块")
                .apiInfo(getApiInfo())
                .select()
//                .apis(RequestHandlerSelectors.basePackage("com.chlm.mysession.controller"))
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
//                .paths(PathSelectors.any())
                .paths(PathSelectors.regex("/job/.*"))
                .build()
                .enable(enableApiDoc);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

注意paths中的过滤

修改Controller类

@Slf4j
@RestController
@RequestMapping("/export")
@Api(value = "File Export",tags = {"文件导出"})
public class FileExportController {
    private final FreeMarkerConfigurer freeMarkerConfigurer;
    private Base64 b64Encoder = new Base64();

    @Autowired
    public FileExportController(FreeMarkerConfigurer freeMarkerConfigurer) {
        this.freeMarkerConfigurer = freeMarkerConfigurer;
    }

    /**
     - 导出word
     - @param request 请求
     - @param response 响应
     */
    @GetMapping("/word")
    @ApiOperation(value = "导出word", notes = "导出测试的word")
    public void exportWord(HttpServletRequest request, HttpServletResponse response){
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

注意:如果有参数,前需加上@RequestParam

  • swagger的注解

我们可以使用swagger定义更详细接口说明

@Api:用在类上,标志此类是Swagger资源
value:接口说明,该参数没什么意义,在UI界面上也看到,所以不需要配置"
tags:接口说明,可以在页面中显示。可以配置多个,当配置多个的时候,在页面中会显示多个接口的信息 ,说明该类的作用,可以在UI界面上看到的注解
@ApiOperation:用在方法上,描述方法的作用
value:说明方法的用途、作用
notes:方法的备注说明
@ApiImplicitParams:包装器:包含多个ApiImplicitParam对象列表
@ApiImplicitParam:定义在@ApiImplicitParams注解中,定义单个参数详细信息 ○ paramType:参数放在哪个地方
§ header-->请求参数的获取:@RequestHeader
§ query-->请求参数的获取:@RequestParam
§ path(用于restful接口)-->请求参数的获取:@PathVariable
§ body(以流的形式提交 仅支持POST,不常用)
§ form(以form表单的形式提交 仅支持POST,不常用)
○ name:参数名
○ dataType:参数的数据类型,参数放在哪个地方, 只作为标志说明,并没有实际验证
§ Long
§ String
○ required:参数是否必须传
§ true
§ false
○ value:参数的意义,参数的汉字说明、解释
○ defaultValue:参数的默认值
@ApiModel:描述一个Swagger Model的额外信息
@ApiModel用在类上,表示对类进行说明,用于实体类中的参数接收说明
@ApiModelProperty:在model类的属性添加属性说明
@ApiParam:用于Controller中方法的参数说明
@ApiResponses:包装器:包含多个ApiResponse对象列表
@ApiResponse:定义在@ApiResponses注解中,一般用于描述一个错误的响应信息
○ code:错误码,例如400 ○ message:信息,例如"请求参数没填好" ○ response:抛出异常的类 @Authorization Declares an authorization scheme to be used on a resource or an operation.
@AuthorizationScope Describes an OAuth2 authorization scope.

# @ApiModel 和@ApiModelProperty

定义model类

@ApiModel( description = "学生")
public class Student {
    @ApiModelProperty(value = "主键id")
    private String id;
    @ApiModelProperty(value = "名称", required = true)
    private String name;
    @ApiModelProperty(value = "年龄", required = true)
    private int age;}
1
2
3
4
5
6
7
8
9
10

在方法使用

@RequestMapping(value = "/update", method = {RequestMethod.POST})
// 方法说明
@ApiOperation(value = "添加学生记录", notes="传递复杂对象DTO",produces = "application/json")
public int update(@RequestBody Student student){
    System.out.println("update student = " + student);
    return 1;
}
1
2
3
4
5
6
7

# 本地化

# 样式修改

返回顶部

修改为swagger-ui-layer

<!-- https://mvnrepository.com/artifact/com.github.caspar-chen/swagger-ui-layer -->
        <dependency>
            <groupId>com.github.caspar-chen</groupId>
            <artifactId>swagger-ui-layer</artifactId>
            <version>1.1.3</version>
        </dependency>
1
2
3
4
5
6

添加swagger功能和注解

启用swagger ,创建SwaggerConfig文件,内容如下,

需要注意的一点是 swagger api 的默认地址是/v2/api-docs 所以swagger-ui-layer也读取的是默认地址, 所以在new Docket()的时候不能指定group参数,否则 swagger api 的地址会在后面加入group的参数导致swagger-ui-layer不能正确请求到数据,其地址为:http://{ip}:{port}/docs.html

另有一个ui:swagger-bootstrap-ui,基本同上,修改pom文件

<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/swagger-bootstrap-ui -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.4</version>
        </dependency>
1
2
3
4
5
6

其默认地址为:http://{ip}:{port}/doc.html

# 问题

返回顶部

  • 整合spring security的问题

新增安全过滤

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**");
    }

}
1
2
3
4
5
6
7
8
9

2.5以上

 @Override
    public void configure(WebSecurity web) throws Exception {
        //allow Swagger URL to be accessed without authentication
        web.ignoring().antMatchers("/v2/api-docs",//swagger api json
                "/swagger-resources/configuration/ui",//用来获取支持的动作
                "/swagger-resources",//用来获取api-docs的URI
                "/swagger-resources/configuration/security",//安全选项
                "/swagger-ui.html");
    }
1
2
3
4
5
6
7
8
9
  • 整合了spring security后get请求不做拦截,但是post请求会被403

需要在Security相关配置类中添加Swagger相关请求允许访问

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.csrf().disable();//csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}
1
2
3
4
5
6
7
8
9

上面的解决方式太粗暴,直接禁用掉csrf

  • 访问页面404
public class Swagger extends WebMvcConfigurerAdapter{

    @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/");
    }
1
2
3
4
5
6
7
8
9
10

# Swagger加入全局head参数(如token)

返回顶部

1.通过Swagger2的securitySchemes配置全局参数:如下列代码所示,securitySchemes的ApiKey中增加一个名为“Authorization”,type为“header”的参数。

private List<ApiKey> securitySchemes() {
        return newArrayList(
                new ApiKey("Authorization", "Authorization", "header"));
 }
1
2
3
4

2.在Swagger2的securityContexts中通过正则表达式,设置需要使用参数的接口(或者说,是去除掉不需要使用参数的接口),如下列代码所示,通过PathSelectors.regex(“^(?!auth).*$”),所有包含”auth”的接口不需要使用securitySchemes。即不需要使用上文中设置的名为“Authorization”,type为“header”的参数。

private List<SecurityContext> securityContexts() {
       return newArrayList(
               SecurityContext.builder()
                       .securityReferences(defaultAuth())
                       .forPaths(PathSelectors.regex("^(?!auth).*$"))
                       .build()
       );
   }
1
2
3
4
5
6
7
8

设置完成后进入SwaggerUI,右上角出现“Authorization”按钮,点击即可输入我们配置的参数。 对于不需要输入参数的接口(上文所述的包含auth的接口),在未输入Authorization参数就可以访问。 其他接口则将返回401错误。点击右上角“Authorization”按钮,输入配置的参数后即可访问。参数输入后全局有效,无需每个接口单独输入。

至此,完成Swagger2 非全局、无需重复输入的Head参数配置。 Swagger2的相关完整代码如下