后端开发一定厌倦了和前端对API接口的麻烦,之前还是小白时愣是手写 word 文档给前端工程师使用,各种 copy 字段加解释…
然而,有更好用的API框架可以使用,可以让我们摆脱这种烦恼,下面说下 spring-fox swagger 的简单使用
注:swagger 是一种API规范,springfox 是其规范的一种实现
- 引入 swagger 依赖
-
-
<dependency>
-
<groupId>io.springfox</groupId>
-
<artifactId>springfox-swagger2</artifactId>
-
<version>2.8.0</version>
-
</dependency>
-
-
<dependency>
-
<groupId>io.springfox</groupId>
-
<artifactId>springfox-swagger-ui</artifactId>
-
<version>2.8.0</version>
-
</dependency>
- 配置 swagger,本例中使用的是 springboot 配置,如需 xml 配置请自行百度
编写SwaggerConfig
添加注解
@Configuration
@EnableSwagger2
Docket.apis()中配置的包名为要扫描生成API的 Controller 包名,将会为该包下的 controller 生成相关文档
ApiInfo 为相关信息,该信息将会展示在文档中
-
/**
-
* Created by wangqichang on 2018/6/22.
-
*/
-
-
2
-
public class SwaggerConfig{
-
-
-
public Docket createRestApi(){
-
return new Docket(DocumentationType.SWAGGER_2)
-
.apiInfo(apiInfo())
-
.select()
-
.apis(RequestHandlerSelectors.basePackage(“com.kichun.controller”))
-
.paths(PathSelectors.any())
-
.build();
-
}
-
-
private ApiInfo apiInfo(){
-
return new ApiInfoBuilder()
-
.title(“炒鸡好用的系統API“)
-
.description(“更多内容请咨询开发者 王启昌”)
-
.termsOfServiceUrl(“http://kichun.xin/”)
-
.contact(“wangqichang”)
-
.version(“1.0”)
-
.build();
-
}
-
}
- 在需要添加的 controller 类和方法中加上 api 注解
加在类上
@Api(value = “字典操作接口”,tags = {“字典常量操作”})
加在方法上
@ApiOperation(value = “删除字典类型”,notes = “”)
@ApiImplicitParam(name = “id”,value = “字典 ID”,required = true,dataType = “String”)
-
/**
-
* <p>
-
* 前端控制器
-
* </p>
-
*
-
* @author wangqichang
-
* @since 2018-06-15
-
*/
-
-
-
-
public class DataDictController{
-
-
private DataDictService dataDictService;
-
-
/**
-
* 删除字典类型
-
*
-
* @author Qichang.Wang
-
* @date 16:04 2018/6/15
-
*/
-
-
-
-
public ResultDTO delete(String id) {
-
if (StrUtil.isBlank(id)) {
-
return new ResultDTO(400, “参数异常”);
-
}
-
BaseDictEnum baseDictEnum = BaseDictEnum.fromId(id);
-
if (baseDictEnum != null) {
-
return new ResultDTO(500, “暂不支持删除顶级字典!”);
-
}
-
boolean insert = dataDictService.deleteById(id);
-
return insert ? new ResultDTO(200, “success”) : new ResultDTO(500, “fail”);
-
}
-
当有多个参数时用@ApiImplicitParams
-
/**
-
* 登录
-
*
-
* @author Qichang.Wang
-
* @date 17:27 2018/6/14
-
*/
-
“用户登录接口”, notes = “”)(value =
-
“name”, value = “用户名”, required = true),(value = { (name =
-
“pwd”, value = “密码”, required = true),(name =
-
“rememberMe”, value = “勾选时传递 true”, required = false) })(name =
-
“/login”, method = RequestMethod.POST)(value =
-
public ResultDTO login(String name, String pwd, String rememberMe){
-
if (StrUtil.isBlank(name) || StrUtil.isBlank(pwd)) {
-
return new ResultDTO(500, “用户名及角色不能为空”);
-
}
-
Boolean remember = false;
-
if (StrUtil.isNotBlank(rememberMe) || “true”.equals(rememberMe.trim())) {
-
remember = true;
-
}
-
UsernamePasswordToken token = new UsernamePasswordToken(name, pwd, remember);
-
try {
-
SecurityUtils.getSubject().login(token);
-
} catch (Exception e) {
-
log.error(“登录失败,信息:{}”, e.getMessage());
-
return new ResultDTO(401, “登录失败, 用户名或密码不匹配”);
-
}
-
return new ResultDTO(200, “登录成功!”);
-
}
当参数是个对象时,参数前加入
@RequestBody @ModelAttribute
这样才能将对象的属性给到 swagger
-
* 新增更新字典类型
-
*
-
*Qichang.Wang
-
* 16:05 2018/6/15
-
*/
-
“新增及更新字典”,notes = “对象包含 ID 时为更新,不包含 ID 时为新增”)(value =
-
“dict”,value = “字典对象,详细请查看对象属性”,required = true,dataType = “DataDict”)(name =
-
“/update”, method = RequestMethod.POST)(value =
-
public ResultDTO update(@RequestBody @ModelAttribute DataDict dict){
-
if (StrUtil.isBlank(dict.getParentId()) || StrUtil.isBlank(dict.getName())) {
-
return new ResultDTO(400, “参数异常”);
-
}
-
BaseDictEnum baseDictEnum = BaseDictEnum.fromId(dict.getId());
-
if (baseDictEnum != null) {
-
return new ResultDTO(500, “暂不支持修改顶级字典!”);
-
}
-
-
if (StrUtil.isBlank(dict.getId())){
-
DataDict exist = new DataDict();
-
exist.setName(dict.getName());
-
exist.setParentId(dict.getParentId());
-
List<DataDict> dataDicts = dataDictService.selectList(new EntityWrapper<>(dict));
-
if (CollUtil.isNotEmpty(dataDicts)) {
-
return new ResultDTO(500, “该类型名已存在”);
-
}
-
dataDictService.insert(dict);
-
} else {
-
-
boolean insert = dataDictService.updateById(dict);
-
}
-
return new ResultDTO(200,“操作成功”);
-
}
注解的各个属性相信各位大佬一看就能明了,不多加解释了
加好注解后,重启应用
接下来是见证奇迹的时候
访问路径:应用地址+端口+swagger-ui.html 例如http://localhost:8800/swagger-ui.html
展开 contoller 效果
展开接口效果
点 try it out 可以直接对接口进行测试,彻底抛弃什么 Postman,RestfulClient 等调试工具!
只要注释写的全,再复杂的应用统统搞定有没有!!!
改了接口自动重新生成API文档有没有!!!
会写代码的前端工程师都能看懂有没有!!!
还是看不懂的前端直接打屎算了有没有!!!
美中不足是字段详细我还不确定能不能加注释,你们研究下吧,我觉得达到这效果已经 OK 了
20180921 补充:
针对接口请求对象及返回对象使用上述方式无法展示字段说明。使用@ModelAttribute 注解可能会导致一些莫名错误无法获取参数
实体注解
@ApiModel 用于实体类上,标注为需要生成文档的实体
@ApiModelProperty(value = “url 菜单”,required = true) 用于实体属性,标注该属性的说明,require 为 false 时不会在页面上进行展示该属性
-
-
import com.baomidou.mybatisplus.enums.IdType;
-
import io.swagger.annotations.ApiModel;
-
import io.swagger.annotations.ApiModelProperty;
-
-
/**
-
* <p>
-
* 权限表
-
* </p>
-
*
-
* @author wangqichang
-
* @since 2018-06-14
-
*/
-
-
-
-
-
public class Resource extends Model<Resource> {
-
-
private static final long serialVersionUID = 1L;
-
-
/**
-
* 资源 ID
-
*/
-
-
-
private String id;
-
-
/**
-
* url
-
*/
-
-
private String url;
-
-
/**
-
* 父 ID
-
*/
-
-
-
private String parentId;
-
-
/**
-
* 资源名
-
*/
-
-
-
private String resourceName;
-
-
/**
-
* 资源类型(menu,btn)
-
*/
-
-
-
private String resourceType;
-
-
/**
-
* 资源码
-
*/
-
-
-
private String resourceCode;
-
-
/**
-
* 资源描述
-
*/
-
-
-
private String resourceDesc;
-
-
/**
-
* 菜单图标
-
*/
-
-
private String myicon;
-
-
/**
-
* 是否可用
-
*/
-
-
private Integer available;
-
-
/**
-
* 创建时间
-
*/
-
-
-
private Date createTime;
-
-
/**
-
* 创建人 id
-
*/
-
-
-
private Date createId;
-
-
/**
-
* 排序
-
*/
-
-
private Integer sort;
-
-
/**
-
* 临时字段,供前端选中使用
-
*/
-
-
-
private Boolean isChecked;
-
-
-
-
protected Serializable pkVal() {
-
return this.id;
-
}
-
-
}
-
在实体添加注解后,在接口中使用如下注解
@ApiParam(name = “资源对象”,value = “json 格式”,required = true)
标识该对象为文档实体
-
-
-
public ResultDTO resource( Resource resource) {
-
Integer count = 0;
-
try {
-
count = userService.updateResources(resource);
-
} catch (Exception e) {
-
log.error(“新增或更新资源异常:{}”, e.getMessage());
-
return new ResultDTO(500, e.getMessage());
-
}
-
return count > 0 ? new ResultDTO(200, “保存成功”) : new ResultDTO(500, “操作失败,请查询日志”);
-
}
实体注释文档界面
需要点击 model 才会显示说明
效果如下