# 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>
2
3
4
5
6
在应用主类中增加@EnableSwagger2Doc注解
@EnableDiscoveryClient
@SpringBootApplication
@EnableSwagger2Doc
public class NacosServerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosServerApplication.class, args);
}
}
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>
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();
}
}
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();
}
}
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);
}
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){
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;
…
}
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;
}
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>
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>
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/**");
}
}
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");
}
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());
}
}
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/");
}
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"));
}
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()
);
}
2
3
4
5
6
7
8
设置完成后进入SwaggerUI,右上角出现“Authorization”按钮,点击即可输入我们配置的参数。
对于不需要输入参数的接口(上文所述的包含auth的接口),在未输入Authorization参数就可以访问。
其他接口则将返回401错误。点击右上角“Authorization”按钮,输入配置的参数后即可访问。参数输入后全局有效,无需每个接口单独输入。
至此,完成Swagger2 非全局、无需重复输入的Head参数配置。 Swagger2的相关完整代码如下