导入依赖
Knife4j的依赖坐标如下:
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
配置类
编写(或修改)配置类:
@Configuration
@EnableSwagger2 // 开启Swagger2
@EnableKnife4j // 开启Knife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Bean
public Docket createRestApi() {
// 设置文档类型
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// 设置Controller的包名
.apis(RequestHandlerSelectors.basePackage("com.linner.reggie.controller"))
.paths(PathSelectors.any())
.build();
}
/**
* API文档描述
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 文档标题
.title("瑞吉外卖")
// 文档版本
.version("1.0")
// 文档描述
.description("瑞吉外卖接口文档")
.build();
}
/**
* 设置静态资源映射
* <p>放行静态页面资源</p>
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// API文档的静态资源映射
registry.addResourceHandler("doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
资源放行
放行文档静态页面请求。必须确保以下静态资源路径可以被访问,不被拦截:
/doc.html
/webjars/**
/swagger-resources
/v2/api-docs
API 文档注解
注解 | 说明 |
---|---|
@Api |
用在请求的类上(例如Controller,使用tags 元素指定文档的标签。 |
@ApiModel |
用在类上(例如实体类),表示一个返回响应数据的信息。 |
@ApiModelProperty |
用在属性上,描述响应类(实体类)的属性。 |
@ApiOperation |
用在请求的方法上,说明方法的用途、作用。 |
@ApiImplicitParams |
用在请求的方法上,表示一组参数说明。 |
@ApiImplicitParam |
用在@ApiImplicitParams 注解中,指定一个请求参数的各个方面。如果只用说明一个参数的话, @ApiImplicitParam 可以单独用在方法上。 |
注意:@ApiImplicitParam不能对实体类进行定义,否则访问API文档时/v2/api-docs会出现接口异常(500状态码)。
示例
标识响应数据信息:
/**
菜品
*/
@Data
@ApiModel("菜品") // 标识实体类的名称
public class Dish implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("菜品ID") // 标识实体类属性的名称
private Long id;
//菜品名称
@ApiModelProperty("菜品名称") // 标识实体类属性的名称
private String name;
//菜品分类id
@ApiModelProperty("菜品分类ID") // 标识实体类属性的名称
private Long categoryId;
//菜品价格
@ApiModelProperty("菜品价格") // 标识实体类属性的名称
private BigDecimal price;
//商品码
@ApiModelProperty("商品码") // 标识实体类属性的名称
private String code;
//图片
@ApiModelProperty("菜品图片") // 标识实体类属性的名称
private String image;
//描述信息
@ApiModelProperty("描述信息") // 标识实体类属性的名称
private String description;
//0 停售 1 起售
@ApiModelProperty("商品状态") // 标识实体类属性的名称
private Integer status;
//顺序
@ApiModelProperty("展示顺序") // 标识实体类属性的名称
private Integer sort;
/* ... */
}
标识请求类:
/**
* 菜品管理
*/
@RestController
@RequestMapping("/dish")
@Api(tags = "菜品管理")
public class DishController {
@Autowired
private DishService dishService;
@Autowired
private DishFlavorService dishFlavorService;
@Autowired
private CategoryService categoryService;
@Autowired
private RedisTemplate redisTemplate;
/**
* 新增菜品
* @param dishDto
* @return
*/
@PostMapping
@ApiOperation("新增菜品") // 标识API方法,对API请求进行说明
public R<String> save(@RequestBody DishDto dishDto) {
// 清理某个分类下面的菜品缓存
String key = this.getRedisKey(dishDto);
redisTemplate.delete(key);
dishService.saveWithFlavor(dishDto);
return R.success("新增菜品成功"); // 返回一个请求成功的响应体信息
}
/**
* 菜品信息分页查询
* @param page
* @param pageSize
*/
@GetMapping("/page")
@ApiOperation("菜品信息分页查询") // 标识API方法,对API请求进行说明
@ApiImplicitParams({ // 标识API方法,对API请求参数进行说明
/**
* @ApiImplicitParam 对请求参数进行具体的说明,它的属性有:
* - name:标识请求参数的名称,与API方法的参数名对应
* - value:对name对应的参数进行说明
* - required:对name对应的参数是否为必须的请求参数进行说明
* - true:值为true表示该参数是请求时必须携带的
* - false:值为false表示在进行请求时,可以不必携带该参数
*/
@ApiImplicitParam(name = "page", value = "页码", required = true),
@ApiImplicitParam(name = "pageSize", value = "每页展示数据条数", required = true),
@ApiImplicitParam(name = "name", value = "要搜索的菜品名称")
})
public R<Page> page(int page, int pageSize, String name) {
// 构造分页构造器对象
Page<Dish> pageInfo = new Page<>(page, pageSize);
Page<DishDto> dishDtoPage = new Page<>();
// 条件构造器
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
// 添加过滤条件
queryWrapper.like(name != null, Dish::getName, name);
// 添加排序条件(降序排序)
queryWrapper.orderByDesc(Dish::getUpdateTime);
// isDeleted不为1(为1表示被删除)
queryWrapper.ne(Dish::getIsDeleted, 1);
// 执行分页查询
dishService.page(pageInfo, queryWrapper);
// 对象拷贝
BeanUtils.copyProperties(pageInfo, dishDtoPage, "records");
List<Dish> records = pageInfo.getRecords();
List<DishDto> list = records.stream().map((item) -> {
DishDto dishDto = new DishDto();
BeanUtils.copyProperties(item, dishDto);
Long categoryId = item.getCategoryId(); // 分类id
Category category = categoryService.getById(categoryId); // 根据id查询分类对象
if (category != null) {
String categoryName = category.getName();
dishDto.setCategoryName(categoryName);
}
return dishDto;
}).collect(Collectors.toList());
dishDtoPage.setRecords(list);
return R.success(dishDtoPage);
}
/**
* 根据id查询菜品全部信息(包括口味)
* @param id
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询菜品全部信息(包括口味)")
// 如果方法仅有一个参数,可以使用一个@ApiImplicitParam标识,无需使用@ApiImplicitParams
@ApiImplicitParam(name = "id", value = "要查询的菜品ID", required = true)
public R<DishDto> get(@PathVariable Long id) {
DishDto dishDto = dishService.getByIdWithFlavor(id);
return R.success(dishDto);
}
}
更多详细用法,请参考:瑞吉外卖项目 Knife4j 笔记
评论