springboot Knife4j 自定义请求参数【分组版】
减少Controller @ApiOperationSupport(includeParameters ={…}) 编写
同一个功能组在Controller 层总会因为参数忽略问题反复的修改,与添加,大大的增加了工作效率。特编写自定义 分组请求参数 注解
编写注解 【分组 请求包含参数】
import java.lang.annotation.*;
/**
* 参考 原注解 ===》ApiOperationSupport
* <p>Help Java development engineers build powerful Swagger documents</p>
* <p>This annotation belongs to the enhanced annotation of @ApiOperation, which is unique to swagger-bootstrap-ui and provides Swagger's extended attributes.</p>
* @since 1.9.4
* @author <a href="mailto:xiaoymin@foxmail.com">xiaoymin@foxmail.com</a>
* 2019/06/06 19:26
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MrApiOperationSupport {
/***
* 请求参数
* @return
*/
Class requestBody();
/***
* 请求参数别名
* @return
*/
String requestBodyName() default "";
/***
* 请求参数分组
* @return
*/
Class<?>[] includeParameters() default {};
}
实体类标识注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @ClassName IncludeParas
* @author mr王
* @version 1.0.0
* @Description 接口包含请求参数
* @createTime 2021/4/7 16:50
*/
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IncludeParas {
/***
* 分组接口标识
* @return
*/
Class<?>[] groups() default {};
}
自定义分组注解包含请求参数 减少非接口字段忽略添加
import com.github.xiaoymin.knife4j.spring.plugin.AbstractOperationBuilderPlugin;
import com.wang.soulboy.config.Knife4j.custom.mrAnnotation.IncludeParas;
import com.wang.soulboy.config.Knife4j.custom.mrAnnotation.MrApiOperationSupport;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.service.ListVendorExtension;
import springfox.documentation.service.VendorExtension;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.OperationContext;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.util.*;
/***
* 忽略接口某个参数,避免编写过多的实体类,该插件通过给Open API v2.0 的Path节点添加扩展属性x-ignoreParameters扩展属性,结合前端ui自定义实现过滤规则.
* 2.0.3版本添加includeParameters属性的支持
* @since:swagger-bootstrap-ui 1.9.5
* @author <a href="mailto:xiaoymin@foxmail.com">xiaoymin@foxmail.com</a>
* 2019/07/30 15:32
*
*
* 自定义分组注解包含请求参数 减少非接口字段忽略添加
*
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE+102)
public class MrOperationIgnoreParameterPlugin extends AbstractOperationBuilderPlugin {
/***
* 请求参数分组
* @return
*/
public static final String INCLUDE_PARAMETER_EXTENSION_NAME="x-includeParameters";
@Override
public void apply(OperationContext context) {
Optional<MrApiOperationSupport> apiOperationSupportOptional=context.findAnnotation(MrApiOperationSupport.class);
if (apiOperationSupportOptional.isPresent()){
MrApiOperationSupport apiOperationSupport=apiOperationSupportOptional.get();
addExtensionParameters(apiOperationSupport.requestBody(),apiOperationSupport.requestBodyName(), apiOperationSupport.includeParameters(),INCLUDE_PARAMETER_EXTENSION_NAME,context);
}
}
@Override
public boolean supports(DocumentationType delimiter) {
return true;
}
/***
* 添加扩展属性参数
* @param params 参数
* @param requestBody
* @param requestBodyName
* @param includeParameters
* @param context
*/
private void addExtensionParameters( Class requestBody,String requestBodyName,Class<?>[] params,String includeParameters,OperationContext context){
if (params!=null&¶ms.length>0){
Map<String,Boolean> map=new HashMap<>();
Field[] fields = requestBody.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if(field.getAnnotation(NotNull.class) != null){
/*** 将分组必填项添加到【包含请求参数】 ***/
for (Class<?> group : field.getAnnotation(NotNull.class).groups()) {
for (Class<?> param : params) {
if(group.equals(param)){
map.put(requestBodyName+"."+field.getName(),true);
}
}
}
}
if(field.getAnnotation(IncludeParas.class) != null){
/*** 将分组标明 包含请求参数 注解的字段 添加到【包含请求参数】 ***/
for (Class<?> group : field.getAnnotation(IncludeParas.class).groups()) {
for (Class<?> param : params) {
if(group.equals(param)){
map.put(requestBodyName+"."+field.getName(),true);
}
}
}
}
}
if (map.size()>0){
List<Map<String,Boolean>> maps=new ArrayList<>();
maps.add(map);
ListVendorExtension<Map<String,Boolean>> listVendorExtension=new ListVendorExtension<>(includeParameters,maps);
List<VendorExtension> vendorExtensions=new ArrayList<>();
vendorExtensions.add(listVendorExtension);
context.operationBuilder().extensions(vendorExtensions);
}
}
}
}
测试实体类
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
/**
* @ClassName Dbentity
* @author 王先生敲代码
* @version 1.0.0
* @Description 生成实体类所需字段
* @createTime 2021/4/7 11:47
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Dbentity {
/** 创建单个数据表的实体类 */
public interface createOne{}
/** 创建所有数据表的实体类 */
public interface createAll{}
@Valid
@ApiModelProperty(name = "db_name",value = "数据库名" ,dataType="String",example="数据库名",allowEmptyValue = true)
@NotNull(message = "数据库名 db_name ===》 不能为空!",groups = {createOne.class,createAll.class})
private String db_name;
@Valid
@ApiModelProperty(name = "table_name",value = "数据表名" ,dataType="String",example="数据表名",allowEmptyValue = true)
@NotNull(message = "数据表名 table_name ===》 不能为空!",groups = {createOne.class})
private String table_name;
@Valid
@ApiModelProperty(name = "tableComment",value = "导出的实体类表说明" ,dataType="String",example="这是什么表?",allowEmptyValue = true)
@NotNull(message = "导出的实体类表说明 tableComment ===》 不能为空!",groups = {createOne.class})
private String tableComment;
@Valid
@ApiModelProperty(name = "path",value = "导出的实体类位置" ,dataType="String",example="d:/Dbentity/",allowEmptyValue = true)
@NotNull(message = "导出的实体类位置 path ===》 不能为空!",groups = {createOne.class,createAll.class})
private String path;
@Valid
@IncludeParas(groups = {createOne.class}) // 包含参数
@ApiModelProperty(name = "entit_package",value = "实体类在项目中存放的位置" ,dataType="String",example=";",allowEmptyValue = true)
@NotNull(message = "实体类在项目中存放的位置 entit_package ===》 不能为空!",groups = {createAll.class})
private String entit_package;
}
Controller 接口
@ApiOperation(value="数据表导出实体类存至指定位置" ,notes = "描述:数据表导出实体类")
@ApiOperationSupport(order=2)
@RequestMapping(value = "dataToFile",method = RequestMethod.POST,produces="application/json;charset=UTF-8")
@MrApiOperationSupport(requestBody = Dbentity.class,requestBodyName = "entity",includeParameters = Dbentity.createOne.class)
public Rest dataToFile(HttpServletRequest request, @Validated({Dbentity.createOne.class}) @RequestBody Dbentity entity){
.........
}