1. Visão geral da documentação da interface
Swagger é uma ferramenta popular de geração de documentos de interface em tempo real. O documento de interface é uma ferramenta indispensável no projeto atual de separação de front-end e back-end. Antes do desenvolvimento de front-end e back-end, o back-end deve produzir o documento de interface primeiro, e o front-end desenvolverá o projeto de acordo com o documento de interface.
Portanto, o documento de interface é na verdade um acordo entre as duas partes antes do desenvolvimento. Normalmente, a documentação da interface é dividida em offline e em tempo real. As ferramentas de documentação de interface offline incluem: word (equivalente a não mencionado), YAPI, Xiao Yaoji, etc. Este tipo de documentação precisa ser escrita por programadores e geralmente tem funções de teste de interface. Normalmente, os desenvolvedores primeiro escrevem as informações no documento de interface offline e, em seguida, as entregam ao pessoal de front-end para desenvolvimento de referência. A maior desvantagem é que quando nosso programa de interface muda, precisamos voltar e manter o conteúdo acima, o que é muito problemático, realmente problemático.
O documento de interface em tempo real é que o documento de interface correspondente pode ser gerado automaticamente de acordo com nosso código. A vantagem é que quando nosso código muda, o documento de interface gerado também será atualizado automaticamente, e não precisamos prestar atenção a modificação.A principal necessidade de publicá-lo a tempo. No entanto, como é gerado automaticamente com base no código, a maior desvantagem é que o código é intrusivo e precisamos integrar o código relevante do documento de interface gerado no código do projeto. Existem muitas soluções para documentos de interface em tempo real, mas a arrogância ainda é uma das mais influentes.
2. SpringBoot integra swagger2
Endereço do site oficial: swagger.io Claro, o site oficial está todo em inglês, o que parece ser bastante problemático. Sugiro que você siga meus passos diretamente, ainda é muito simples.
Ao mesmo tempo, estou dizendo uma coisa: swagger é dividido em duas versões comuns, swagger2 e swagger3. A diferença entre os dois não é muito grande, principalmente otimizada para dependências e anotações. O swagger2 precisa introduzir 2 pacotes jar, o swagger3 precisa apenas de um, e não há grande diferença no uso. Tome swagger2 como um exemplo abaixo.
2.1 Apresentando dependências
<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 Configuração de importação
首先需要添加一个注解 : @EnableSwagger2。 这个注解我们可以添加到SpringBoot的启动类上,也可以自定义一个配置类,放到上面。添加了这个注解以后,就代表我们已经在项目中开启了Swagger的功能。
我们采用第二种方式,自己定义一个配置类,正好还可以添加一个Docket配置。 所谓Docket配置,就是一组(一个项目或一个版本)接口文档的配置,比如设置名称, 联系人等等。
我们在config文件夹下,添加一个SwaggerConfig类。
@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方法,代表生成文档的所有接口中,都要包含一个header类型的token参数。
2.3 给Controller 添加注解
我们接口文档的直接描述主要就是在Controller这一层,比如这个接口的功能,参数的名称,返回值的名称等。这些值我们都需要在Controller上通过给方法上,请求参数和返回参数上添加对应的注解,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 注解定义了实体的名称和字段的名称,方便生成接口文档时展示。
再来看Controller:
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注解分别标注了接口组名和接口的名称。现在我们启动项目。
发现报了这个错误。
上网查询原因说是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格式的配置文件:
再次启动问题解决。
访问地址: ip:端口号/swagger-ui.html
正常情况就可以看到我们的界面了。一会再说非正常情况。由于我们只给用户接口添加了注解,所有用户接口是可以直接观察中文文档的。而剩下的两个接口,由于没添加注解,所以都是以默认的形式展示的。
点开接口,我们可以看到接口中的想详细信息
点击model,可以看到字段的中文描述。点击 Try it out,就可以直接调试接口。同时注意接口中都让填一个token,这就是我们之前的设置成效了。
截止到目前其实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**
页面出现了。我们在看看我们的用户接口:
这个风格确实更加的直观,同时也是可以直接进行调试的。大部分的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风格也发生了一些变化:
同时swagger3也是可以更换UI的。方法和swagger2一样。
四. swaggerUI 拦截器和跨域冲突处理
如果我们的项目中有关于跨域的处理,同时还有拦截器,然后还要使用swagger,这种情况大家要注意了,有可能我们的拦截器会将swagger中的页面路径拦截掉导致swagger页面出不来,当我们在拦截器中把swagger的页面排除掉的时候,也有可能会导致跨域配置的失效。
详细的解决方案可以看我之前写过的一篇博客: lsqingfeng.blog.csdn.net/article/det…
具体解决方案简单提一下:
拦截器:
/**
* 拦截器配置
*
* @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
Todos os artigos também serão atualizados na conta pública do WeChat. Bem-vindo a prestar atenção: Um raio de brisa em 1982
5. Escreva no final
A partir deste artigo, a série de notas de estudo sobre o SpringBoot foi atualizada com dezesseis artigos e basicamente diz adeus a todos. Obrigado a todos pelo apoio ao longo do caminho. Esses dezesseis artigos são principalmente para o aprendizado prático do SpringBoot e raramente introduzem alguns conceitos básicos. Ele também integrou a maioria dos frameworks e middleware atuais. Se você não sabe muito sobre alguns ciclos de vida, processos de inicialização, princípios de carregamento de classes e anotações comuns no Spring (porque esta parte raramente é apresentada), sugiro que você estude junto com a série de tutoriais Spring5 que escrevi antes, que apresenta Spring IOC e os principais conceitos de AOP.
Esta série de tutoriais foi atualizada aqui e pode não ser atualizada no futuro. Para o próximo objetivo, posso estar me preparando para escrever uma série de tutoriais do SpringCloud, principalmente para o uso de alguns componentes na versão alibaba. No entanto, devido à ocupação recente da empresa, a atualização pode ser mais lenta. Espero que você possa me apoiar.
Seja grato, não diga adeus, nos vemos na próxima série!