A.3 springboot swagger

springboot swagger

1. 介绍

目前大部分项目都是前后端分离,或者是以服务的形式暴露RESTful API接口,但是如何向调用方提供接口说明文档?如何快速单元测试我们的接口?如何在更改了接口之后快速的更新于接口文档中?带着这些问题,引入swagger。

特性:

  • swagger可以生成互动性的API控制台
  • 调用者和开发者尝试API
  • 形成一种合作契约,让团队更加敏捷的开发
  • 对代码有一定的入侵型

2. 集成

2.1 POM配置

pom中增加swagger的依赖



    io.springfox
    springfox-swagger-ui
    2.4.0


    io.springfox
    springfox-swagger2
    2.4.0

2.2 开启swagger

在入口程序的启动类(Application.java)上增加@EnableSwagger2的注解

@EnableSwagger2
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        //启动入口
        SpringApplication.run(Application.class, args);
    }

}

2.3 配置swagger

@Configuration
public class AppConfig {
    
    /**
     * 创建swagger ui的摘要
     * @return
     */
    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                // 扫描的class的包路径
                .apis(RequestHandlerSelectors.basePackage("pers.mateng.demo.springboot"))
                // 只扫描类上有API注解的class
//                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
                // 只扫描方法上有ApiOperation注解的方法
//                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * swagger ui的标题信息
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("标题")
                .description("副标题")
                .version("1.0")
                .build();
    }

}

2.4 声明 API

修改UserController,注意类注解(@Api)和方法注解(@ApiOperation)

@RestController
@RequestMapping(path="user")
@Api(tags="用户管理")
public class UserController {
    
    @Autowired
    private UserDao userDao;
    
    @ApiOperation(value="查询用户", notes="测试无请求参数的swagger-ui")
    @RequestMapping(method=RequestMethod.GET)
    public List findAll() {
        return userDao.findAll();
    }
    
    @ApiOperation(value="增加用户-测试1", notes="测试application/x-www-form-urlencoded形式提交参数")
    @RequestMapping(method=RequestMethod.POST)
    public User add(@ModelAttribute User user) {
        return userDao.save(user);
    }
    
    @ApiOperation(value="修改用户-测试1", notes="测试application/json形式提交参数")
    @RequestMapping(path="/{id}", method=RequestMethod.PUT)
    public User update1(@ApiParam(value="用户id") @PathVariable Long id, @RequestBody User user) {
        User temp = userDao.findOne(id);
        if(temp != null) {
            temp.setName(user.getName());
            temp.setAge(user.getAge());
            return userDao.save(temp);
        }
        return null;
    }
    
    @ApiOperation(value="根据id查询用户", notes="测试path参数提交")
    @GetMapping(path="/{id}")
    public User findById(@ApiParam(value="用户id") @PathVariable Long id) {
        return userDao.findOne(id);
    }
    
    @ApiOperation(value="根据id删除用户", notes="测试path参数提交")
    @DeleteMapping(path="/{id}")
    public Boolean del(@ApiParam(value="用户id") @PathVariable Long id) {
        userDao.delete(id);
        return Boolean.TRUE;
    }
}

3. 验证

启动工程,使用eclipse的run as重新启动Application的main函数

使用浏览器访问http://localhost:8888/swagger-ui.html。即可查看UserControlerl中暴漏的接口

填写参数后,点击 “try it out” 即可发送请求

4. 进阶详解

4.1 @ModelAttribute 的参数说明

在swagger-ui上查看“增加用户-测试1”接口,发现该接口的描述并不完善,问题如下:

  • 所有的请求参数都没有中文描述
  • 增加用户时参数“id”是不需要的

那么接口调用方是无法更好的理解接口的使用,解决办法如下

方法一

  • 使用 @ApiIgnore,让 swagger 忽略该实体类的参数
  • 使用 @ApiImplicitParams 重新声明参数的类型、说明、是否必须、参数位置

详细代码如下:

@ApiOperation(value="增加用户-测试2")
@RequestMapping(path="add2", method=RequestMethod.POST)
@ApiImplicitParams({
    @ApiImplicitParam(value="用户名", name="name", required=true, dataType="String", paramType="form"),
    @ApiImplicitParam(value="年龄", name="age", required=false, dataType="integer", paramType="form")
})
public User add2(@ApiIgnore @ModelAttribute User user) {
    return userDao.save(user);
}

方法二

  • 升级 swagger的版本到2.7.0
  • 使用 @ApiModelProperty(hidden=true) 隐藏参数
  • 使用 @ApiModelProperty(value = "xxx") 描述参数的说明
  • 使用 @ApiModelProperty(required=false) 标识参数是否必须输入

修改实体类User,==注意每个属性的注解==

@Entity
@Table(name="TB_USER")
public class User {
    
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="U_ID")
    @ApiModelProperty(hidden=true)
    private Long id;
    
    @Column(name="U_NAME", nullable = false, length=32, unique=true)
    @ApiModelProperty(value = "用户名称", required=true)
    private String name;
    
    @Column(name="U_AGE", length=4)
    @ApiModelProperty(value = "年龄", required=false)
    private Integer age;
    
    
    get/set...
}

4.2 @RequestBody 的参数说明

在 swagger-ui 上查看“修改用户-测试1”接口,发现该接口的描述并不完善,问题如下:

  • 所有的请求参数都没有中文描述
  • 为了追求 RESTful 风格,导致id声明了两次,在 Path 和 Resquestbody 中各声明了一次

所以接口调用方是无法更好的理解接口的使用,解决办法如下

方法一

不使用@Resquestbody 直接使用@ModelAttribute + @ApiImplicitParams的方法,==也就是4.1章节中的方法一==

代码如下:

@ApiOperation(value="修改用户-测试2", notes="测试application/x-www-form-urlencoded形式提交参数")
@RequestMapping(path="update2", method=RequestMethod.PUT)
@ApiImplicitParams({
    @ApiImplicitParam(value="用户id", name="id", required=true, dataType="Integer", paramType="form"),
    @ApiImplicitParam(value="用户名", name="name", required=true, dataType="String", paramType="form"),
    @ApiImplicitParam(value="年龄", name="age", required=false, dataType="integer", paramType="form")
})
public User update2(@ApiIgnore @ModelAttribute User user) {
    User temp = userDao.findOne(user.getId());
    if(temp != null) {
        temp.setName(user.getName());
        temp.setAge(user.getAge());
        return userDao.save(temp);
    }
    return null;
}

方法二

==也就是4.1章节中的方法二==

  • 使用 @ApiModelProperty(hidden=true) 隐藏参数
  • 使用 @ApiModelProperty(value = "xxx") 描述参数的说明
  • 使用 @ApiModelProperty(required=false) 标识参数是否必须输入

在实体类 User上增加注解,代码如下:

@Entity
@Table(name="TB_USER")
public class User {
    
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="U_ID")
    @ApiModelProperty(hidden=true)
    private Long id;
    
    @Column(name="U_NAME", nullable = false, length=32, unique=true)
    @ApiModelProperty(value = "用户名称", required=true)
    private String name;
    
    @Column(name="U_AGE", length=4)
    @ApiModelProperty(value = "年龄", required=false)
    private Integer age;

    get/set……
    
}

4.3 @PathVariable/@RequestParam 的参数说明

在这两个注解的前面增加swagger的注解@ApiParam(value="xxx")

@DeleteMapping(path="/{id}")
public Boolean del(@ApiParam(value="用户id") @PathVariable Long id) {
    userDao.delete(id);
    return Boolean.TRUE;
}

@GetMapping(path="/name")
public String findByName(@ApiParam(value="用户名") @RequestParam String name) {
    return name;
}

4.4 总结

在4.1章节和4.2章节中,处理参数的说明都使用了两种方法,概括的讲,方法一是在方法体的注解上想办法解决,方法二是在参数的属性上想办法解决。

方法一的优缺点分析:

  • 缺点:写的代码多。
  • 优点:适应性好,例如:有多个api接口都需要使用同一个javabean作为入参,但是每个接口实际暴露的参数不一样。就可以复用同一个javabean,而在各自的方法上处理。
  • 优点:对javabean没有入侵性。
  • 适合formdata/x-www-form-urlencoded表单提交。

方法二的优缺点:

  • 缺点:复用性差,例如:有多个api接口都需要使用同一个javabean作为入参,但是每个接口实际暴露的参数不一样。不能复用同一个javabean。
  • 缺点:如果一个javabean即作为入参,又作为出参。
  • 优点:代码写的少。
  • 适合application/json提交参数。

5. 源码

springboot-demo-3

你可能感兴趣的:(A.3 springboot swagger)