Spring-boot集成Swagger2

Swagger用于定义API文档,实现前后端开发分离,测试时不再需要浏览器输入URL访问Controller。对于post请求,无需使用postman模拟,在接口文档中填参数,可直接模拟发请求。本文介绍Swagger2的引入及常用注解。

pom.xml中添加依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>

引入Swagger2

新建类,注解方式引入Swagger2

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
@Configuration
@EnableSwagger2
public class Swagger2 {
public static Contact contact = new Contact("引入swagger2","http://monkeybean.cn/","monkeybean_zhang@163.com");
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.kodgames.pokeragent"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2构建RESTful APIs")
.description("swagger2 接口文档")
.termsOfServiceUrl("http://monkeybean.cn/")
.contact(contact)
.version("1.0")
.build();
}
}

Controller中添加注解

举例:

1
2
3
4
5
6
7
8
9
10
11
/**
* 查询用户是否为代理
*/
@ApiOperation(value="查询用户是否为代理商")
@ApiImplicitParam(name = "id", value = "用户id", required = true, dataType = "int",paramType = "query")
@ApiResponses(value = {@ApiResponse(code = -1,message = "用户不存在"),@ApiResponse(code = -20,message = "代理商被封号"),@ApiResponse(code = -23,message = "当前用户已提交申请,且申请处于审核中")})
@RequestMapping(path = "agent/is_agent", method = RequestMethod.GET)
public HashMap<String, Object> isAgent(@RequestParam(value = "id") int accountId)
{
return service.isAgent(accountId);
}

示例说明:
1.@ApiOperation:用在方法上,说明方法的作用,再比如:

1
@ApiOperation(value="查询返还明细", notes="下级id不支持模糊搜索")

2.@ApiImplicitParams:用在方法上包含一组参数说明
如:

1
2
3
4
5
6
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户id", required = true, dataType = "int",paramType = "query"),
@ApiImplicitParam(name = "phone_number", value = "手机号", required = true, dataType = "string",paramType = "query"),
@ApiImplicitParam(name = "validcode", value = "验证码", required = true, dataType = "string",paramType = "query"),
@ApiImplicitParam(name = "advantages", value = "个人优势", required = true, dataType = "string",paramType = "query")
})

3.@ApiImplicitParam:用在@ApiImplicitParams注解中,对单个参数进行说明

  • name:参数名
  • value:参数含义
  • required:参数是否必须传
  • defaultValue:参数默认值
  • dataType:参数类型(对象类型,基本类型要使用包装类)
  • paramType:参数放在哪个位置

    • header–>放在header中,请求参数获取方法:@RequestHeader
    • query–>放在url中,请求参数获取方法:@RequestParam
    • path(用于restful接口)–>请求参数获取方法:@PathVariable,示例如下,重点为{}

      1
      2
      3
      4
      5
      6
      @ApiOperation(value="获取用户详细信息", notes="根据url的id来获取用户详细信息")
      @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "long", paramType = "path")
      @RequestMapping(value="/{id}", method=RequestMethod.GET)
      public User getUser(@PathVariable Long id) {
      return users.get(id);
      }
    • body及form不常用

  • @ApiResponses:用于表示一组响应
  • @ApiResponse:用在@ApiResponses中,表示单个错误响应信息
    • code:错误码
    • message:错误码含义
    • response:抛出异常的类

常用补充:

  • @Api:用在类上,说明该类的作用
    如:

    1
    2
    3
    @Api(value= "代理商相关api")
    public class ProxyController
    {}
  • @ApiModel:描述一个Model的信息(一般用于post创建时,使用@RequestBody,请求参数无法使用@ApiImplicitParam注解进行描述)

  • @ApiModelProperty:描述单个model的属性
  • @PathVariable: 从url模板取值,注意{};若方法参数名称和绑定的uri template中变量名不一致,需要在@PathVariable(“name”)指定uri template中的名称。
    如:

    1
    2
    3
    4
    5
    6
    7
    @RequestMapping("/user/{id}")
    public void userInfo(@PathVariable int id) {
    }
    @RequestMapping("/user/{id}")
    public void userInfo(@PathVariable(name="id") int roleId) {
    }
  • @RequestHeader: 请求header部分的值绑定到方法的参数上

  • @CookieValue:Request header中关于cookie的值绑定到方法的参数上

    访问api接口文档

    输入http://172.16.2.163:8080/swagger-ui.html 访问
    路径为swagger-ui.html.
    上一步骤中的查询用户是否为代理的示例效果如下:
    swagger_isAgent

安全性

api接口文档在内部联调时使用不会有什么问题,正式上线时涉及到安全问题,肯定不可随意访问,后台接口不可暴露。
可采用如下安全方案:
1.将启用Swagger2的注解注释掉。进入页面时,服务器不会将任何接口返回给浏览器,浏览器拿到的是无任何接口的空页面。效果如下:
empty_swagger
2.多数情况在上线后仍想访问后台API,则使用拦截器,过滤tokenKey。访问Url如http://172.16.2.163:8080/swagger-ui.html?sdfhiohsdabfnjkawe78oih4342598as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 请求Swagger2使用key单独过滤
if(httpServletRequest.getServletPath().toLowerCase().contains("swagger") || httpServletRequest.getServletPath().toLowerCase().contains("api-docs"))
{
if(httpServletRequest.getServletPath().toLowerCase().contains("/swagger-ui.html"))
{
if(!httpServletRequest.getQueryString().toLowerCase().contains("sdfhiohsdabfnjkawe78oih4342598as"))
{
httpServletResponse.setStatus(401);
return;
}
}
chain.doFilter(httpServletRequest, httpServletResponse);
return;
}