常用注解
@Api(tags = "配件信息")
@ApiOperation("新增配件信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "rootid", value = "物料id"),
@ApiImplicitParam(name = "lid", value = "树节点id"),
@ApiImplicitParam(name = "soutype", value = "搜索类型"),
})
@ApiResponses({
@ApiResponse(code = 200,message = "OK",response = TrainUserTEntity.class),
})
@ApiModelProperty(value = "关联产品ID",required = true)
@ApiParam(value = "合同编号", required = true)
自定义注解(POST)
黑名单模式
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiIgp {
String[] value();
}
白名单模式
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiNeed {
String[] value();
}
实现swagger提供的插件 支持上面俩自定义注解
package com.jeesite.modules.common.swagger;
import com.fasterxml.classmate.TypeResolver;
import io.swagger.annotations.ApiModelProperty;
import org.apache.ibatis.javassist.*;
import org.apache.ibatis.javassist.bytecode.AnnotationsAttribute;
import org.apache.ibatis.javassist.bytecode.ConstPool;
import org.apache.ibatis.javassist.bytecode.annotation.Annotation;
import org.apache.ibatis.javassist.bytecode.annotation.BooleanMemberValue;
import org.apache.ibatis.javassist.bytecode.annotation.StringMemberValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ParameterBuilderPlugin;
import springfox.documentation.spi.service.contexts.ParameterContext;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
@Order
@Component
public class SwaggerModelReader implements ParameterBuilderPlugin {
private TypeResolver typeResolver;
private static final Logger logger = LoggerFactory.getLogger(SwaggerModelReader.class);
@Autowired
public void setTypeResolver(TypeResolver typeResolver) {
this.typeResolver = typeResolver;
}
@Override
public void apply(ParameterContext parameterContext) {
ResolvedMethodParameter methodParameter = parameterContext.resolvedMethodParameter();
Optional<ApiIgp> ignorePropsOptional = methodParameter.findAnnotation(ApiIgp.class);
Optional<ApiNeed> needPropsOptional = methodParameter.findAnnotation(ApiNeed.class);
String apiUrl = parameterContext.getOperationContext().requestMappingPattern();
if (ignorePropsOptional.isPresent() && needPropsOptional.isPresent()) {
StringBuilder errorMsg = new StringBuilder("@DaisyApiIgnoreProps with @DaisyApiNeedProps cannot exist at the same time! ");
errorMsg.append("api路径:").append(apiUrl).append("\t");
Optional<String> defaultName = parameterContext.resolvedMethodParameter().defaultName();
if (defaultName.isPresent()) {
errorMsg.append("参数名:").append(defaultName.get()).append("\t");
}
logger.error(errorMsg.toString());
}
if (ignorePropsOptional.isPresent() || needPropsOptional.isPresent()) {
Class originClass = parameterContext.resolvedMethodParameter().getParameterType().getErasedType();
boolean isCollection = Collection.class.isAssignableFrom(originClass);
if (isCollection) {
originClass = parameterContext.resolvedMethodParameter().getParameterType().getTypeBindings().getBoundType(0).getErasedType();
}
Random random = new Random();
String name = originClass.getSimpleName() + random.nextInt(100);;
String[] properties;
boolean ignore = ignorePropsOptional.isPresent();
if (ignore) {
properties = ignorePropsOptional.get().value();
} else {
properties = needPropsOptional.get().value();
}
parameterContext.getDocumentationContext()
.getAdditionalModels()
.add(typeResolver.resolve(createRefModelIgp(properties, name, originClass, ignore)));
ModelRef modelRef;
if (!isCollection) {
modelRef = new ModelRef(name);
} else {
modelRef = new ModelRef("List", new ModelRef(name));
}
parameterContext.parameterBuilder()
.parameterType("body")
.modelRef(modelRef)
.name(name);
}
}
private Class createRefModelIgp(String[] propertys, String name, Class origin, boolean ignore) {
ClassPool pool = ClassPool.getDefault();
String newClassName = origin.getPackage().getName() + "." + name;
try {
CtClass ctClass = pool.getOrNull(newClassName);
if (ctClass != null) {
ctClass.detach();
}
ctClass = pool.makeClass(origin.getPackage().getName() + "." + name);
List<Field> fieldList = getAllField(origin, null);
List<String> dealProperties = Arrays.asList(propertys);
List<Field> dealFileds = fieldList.stream().filter(
s -> ignore ? (!(dealProperties.contains(s.getName()))) : dealProperties.contains(s.getName())
).collect(Collectors.toList());
createCtFileds(dealFileds, ctClass);
return ctClass.toClass();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static List<Field> getAllField(Class clazz, List<Field> fieldList) {
if (fieldList == null) {
fieldList = new ArrayList<>(16);
}
Field[] declaredFields = clazz.getDeclaredFields();
if (declaredFields.length > 0) {
fieldList.addAll(Arrays.asList(declaredFields));
}
Class superclass = clazz.getSuperclass();
if (!superclass.equals(Object.class)) {
fieldList = getAllField(superclass, fieldList);
}
return fieldList;
}
public void createCtFileds(List<Field> dealFileds, CtClass ctClass) throws CannotCompileException, NotFoundException {
ConstPool constPool = ctClass.getClassFile().getConstPool();
for (Field field : dealFileds) {
CtField ctField = new CtField(ClassPool.getDefault().get(field.getType().getName()), field.getName(), ctClass);
ctField.setModifiers(Modifier.PUBLIC);
AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
Annotation ann = new Annotation(ApiModelProperty.class.getName(), constPool);
ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);
if (apiModelProperty != null) {
String[] valNames = new String[]{"name", "value", "example", "allowableValues", "access", "notes", "dataType", "reference"};
String[] vals = new String[]{apiModelProperty.name(),
apiModelProperty.value(), apiModelProperty.example(),
apiModelProperty.allowableValues(), apiModelProperty.access(),
apiModelProperty.notes(), apiModelProperty.dataType(), apiModelProperty.reference()};
for (int i = 0; i < valNames.length; i++) {
if (!"".equals(vals[i])) {
ann.addMemberValue(valNames[i], new StringMemberValue(vals[i], constPool));
}
}
ann.addMemberValue("hidden", new BooleanMemberValue(apiModelProperty.hidden(), constPool));
ann.addMemberValue("required", new BooleanMemberValue(apiModelProperty.required(), constPool));
}
attr.addAnnotation(ann);
ctField.getFieldInfo().addAttribute(attr);
ctClass.addField(ctField);
}
}
@Override
public boolean supports(DocumentationType delimiter) {
return true;
}
}