package com.apigcc.springmvc; import com.apidoc.core.ApiDoc; import com.apidoc.core.common.URI; import com.apidoc.core.common.description.ObjectTypeDescription; import com.apidoc.core.common.description.TypeDescription; import com.apidoc.core.common.helper.AnnotationHelper; import com.apidoc.core.common.helper.ExpressionHelper; import com.apidoc.core.common.helper.StringHelper; import com.apidoc.core.parser.ParserStrategy; import com.apidoc.core.schema.Chapter; import com.apidoc.core.schema.Header; import com.apidoc.core.schema.Row; import com.apidoc.core.schema.Section; import com.apigcc.springmvc.resovler.SpringComponentTypeResolver; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.expr.AnnotationExpr; import com.github.javaparser.ast.expr.Expression; import java.util.List; import java.util.Optional; import static com.apigcc.springmvc.ParameterHelper.ANNOTATION_REQUEST_HEADER; import static com.apigcc.springmvc.ParameterHelper.ANNOTATION_REQUEST_PARAM; /** * spring 解析 * * @author fengyuchenglun * @version 1.0.0 */ public class SpringParser implements ParserStrategy { /** * The constant FRAMEWORK. */ public static final String FRAMEWORK = "springmvc"; /** * The constant EXT_URI. */ public static final String EXT_URI = "uri"; @Override public String name() { return FRAMEWORK; } @Override public void onLoad() { // 添加类型解析器 ApiDoc.getInstance().getTypeResolvers().addResolver(new SpringComponentTypeResolver()); // 类型名称解析器 ApiDoc.getInstance().getTypeResolvers().addNameResolver(new SpringComponentTypeResolver()); } /** * 处理被@RestController和@Controller标记的类 * * @return classOrInterfaceDeclaration */ @Override public boolean accept(ClassOrInterfaceDeclaration classOrInterfaceDeclaration) { return AnnotationHelper.isAnnotationPresent(classOrInterfaceDeclaration, SpringMVCContext.getInstance().getControllers()); } /** * 类被@RestController标记,或方法被@ResponseBody标记 * * @param methodDeclaration methodDeclaration * @return boolean */ @Override public boolean accept(MethodDeclaration methodDeclaration) { //类被@RestController标记,或方法被@ResponseBody标记 return RequestMappingHelper.isRest(methodDeclaration) && AnnotationHelper.isAnnotationPresent(methodDeclaration, RequestMappingHelper.ANNOTATION_REQUEST_MAPPINGS); } /** * 解析类定义 * * @param n * @param chapter */ @Override public void visit(ClassOrInterfaceDeclaration n, Chapter chapter) { chapter.getExt().put(EXT_URI, RequestMappingHelper.pickUriToParent(n)); } /** * 解析方法定义 * * @param n * @param chapter * @param section */ @Override public void visit(MethodDeclaration n, Chapter chapter, Section section) { visitMethod(n, chapter, section); visitUri(n, chapter, section); visitPathVariable(n, chapter, section); visitHeaders(n, chapter, section); visitParameters(n, chapter, section); visitReturn(n, chapter, section); } /** * 解析请求方法 * * @param n the n * @param chapter the chapter * @param section the section */ private void visitMethod(MethodDeclaration n, Chapter chapter, Section section) { section.setMethod(RequestMappingHelper.pickMethod(n)); } /** * 解析请求URI,与父类URI拼接 * * @param n the n * @param chapter the chapter * @param section the section */ private void visitUri(MethodDeclaration n, Chapter chapter, Section section) { URI uri = (URI) chapter.getExt().get(EXT_URI); section.setUri(new URI(uri.toString()).add(RequestMappingHelper.pickUri(n.getAnnotations())).toString()); } /** * 解析方法参数 * * @param n the n * @param chapter the chapter * @param section the section */ private void visitParameters(MethodDeclaration n, Chapter chapter, Section section) { if (ParameterHelper.hasRequestBody(n.getParameters())) { visitRequestBody(n, chapter, section); } else { visitParameter(n, chapter, section); } } /** * 解析PathVariable * * @param n the n * @param chapter the chapter * @param section the section */ private void visitPathVariable(MethodDeclaration n, Chapter chapter, Section section) { for (Parameter parameter : n.getParameters()) { if (ParameterHelper.isPathVariable(parameter)) { section.getPathVariable().put(parameter.getNameAsString(), ""); Row row = new Row(); row.setKey(parameter.getNameAsString()); row.setType(parameter.getType().toString()); section.getParamTag(row.getKey()).ifPresent(tag -> row.setRemark(tag.getContent())); section.addRequestRow(row); } } } /** * 解析RequestHeader * * @param n the n * @param chapter the chapter * @param section the section */ private void visitHeaders(MethodDeclaration n, Chapter chapter, Section section) { List headers = RequestMappingHelper.pickHeaders(n.getAnnotations()); for (String text : headers) { section.addInHeader(Header.valueOf(text)); } List consumers = RequestMappingHelper.pickConsumers(n.getAnnotations()); if (!consumers.isEmpty()) { section.addInHeader(new Header("Content-Type", String.join(",", consumers))); } List produces = RequestMappingHelper.pickProduces(n.getAnnotations()); if (!produces.isEmpty()) { section.addOutHeader(new Header("Content-Type", String.join(",", produces))); } for (Parameter parameter : n.getParameters()) { if (ParameterHelper.isRequestHeader(parameter)) { String key = parameter.getNameAsString(); String defaultValue = "{value}"; AnnotationExpr annotationExpr = parameter.getAnnotationByName(ANNOTATION_REQUEST_HEADER).get(); Optional valueOptional = AnnotationHelper.getAnyAttribute(annotationExpr, "value", "name"); if (valueOptional.isPresent()) { key = String.valueOf(ExpressionHelper.getValue(valueOptional.get())); } Optional defaultValueOptional = AnnotationHelper.getAttribute(annotationExpr, "defaultValue"); if (defaultValueOptional.isPresent()) { defaultValue = String.valueOf(ExpressionHelper.getValue(defaultValueOptional.get())); } TypeDescription description = ApiDoc.getInstance().getTypeResolvers().resolve(parameter.getType()); if (description.isAvailable()) { Object value = description.getValue(); if (StringHelper.isBlank(defaultValue) && StringHelper.nonBlank(value)) { defaultValue = String.valueOf(value); } section.addInHeader(new Header(key, defaultValue)); } } } } /** * 解析RequestBody * * @param n the n * @param chapter the chapter * @param section the section */ private void visitRequestBody(MethodDeclaration n, Chapter chapter, Section section) { section.setQueryParameter(false); section.addInHeader(Header.APPLICATION_JSON); for (Parameter parameter : n.getParameters()) { if (ParameterHelper.isRequestBody(parameter)) { TypeDescription description = ApiDoc.getInstance().getTypeResolvers().resolve(parameter.getType()); if (description.isAvailable()) { if (description.isArray()) { section.setParameter(description.asArray().getValue()); } else if (description.isObject()) { section.setParameter(description.asObject().getValue()); } section.addRequestRows(description.rows()); } break; } } } /** * 解析RequestParameter * * @param n the n * @param chapter the chapter * @param section the section */ private void visitParameter(MethodDeclaration n, Chapter chapter, Section section) { ObjectTypeDescription objectTypeDescription = new ObjectTypeDescription(); for (Parameter parameter : n.getParameters()) { if (ParameterHelper.isRequestParam(parameter)) { String key = parameter.getNameAsString(); Object defaultValue = null; Boolean required = null; Optional optional = parameter.getAnnotationByName(ANNOTATION_REQUEST_PARAM); if (optional.isPresent()) { Optional valueOptional = AnnotationHelper.getAnyAttribute(optional.get(), "value", "name"); if (valueOptional.isPresent()) { key = String.valueOf(ExpressionHelper.getValue(valueOptional.get())); } Optional defaultValueOptional = AnnotationHelper.getAttribute(optional.get(), "defaultValue"); if (defaultValueOptional.isPresent()) { defaultValue = ExpressionHelper.getValue(defaultValueOptional.get()); } Optional requiredOptional = AnnotationHelper.getAttribute(optional.get(), "required"); if (requiredOptional.isPresent() && requiredOptional.get().isBooleanLiteralExpr()) { required = requiredOptional.get().asBooleanLiteralExpr().getValue(); } } TypeDescription description = ApiDoc.getInstance().getTypeResolvers().resolve(parameter.getType()); if (description.isAvailable()) { section.getParamTag(key).ifPresent(tag -> description.addRemark(tag.getContent())); if (required != null) { description.setRequired(required); } if (description.isObject()) { objectTypeDescription.merge(description.asObject()); } else { description.setKey(key); if (defaultValue != null && (description.isPrimitive() || description.isString())) { description.setDefaultValue(defaultValue); } objectTypeDescription.add(description); } } } } section.setParameter(objectTypeDescription.getValue()); section.addRequestRows(objectTypeDescription.rows()); } /** * 解析方法返回参数 * * @param n the n * @param chapter the chapter * @param section the section */ private void visitReturn(MethodDeclaration n, Chapter chapter, Section section) { TypeDescription description = ApiDoc.getInstance().getTypeResolvers().resolve(n.getType()); if (description.isAvailable()) { if (description.isPrimitive()) { section.setRawResponse(description.getValue()); } else if (description.isString()) { section.setRawResponse(description.getValue()); } else if (description.isArray()) { section.setResponse(description.asArray().getValue()); } else if (description.isObject()) { section.setResponse(description.asObject().getValue()); } section.addResponseRows(description.rows()); } } }