Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.hn.doc.xyj.XyjUtils Maven / Gradle / Ivy
package com.hn.doc.xyj;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.hn.doc.xyj.annotation.Api;
import com.hn.doc.xyj.domain.Doc;
import com.hn.doc.xyj.domain.DocContent;
import com.hn.doc.xyj.domain.DocData;
import com.hn.doc.xyj.parse.DomainParse;
import com.hn.doc.xyj.parse.MethodParse;
import com.hn.doc.xyj.parse.ParseUtils;
import com.hn.utils.AssertUtils;
import com.hn.utils.ClassUtil;
import org.springframework.web.bind.annotation.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
/**
* 描述: 小幺鸡通过注解生成接口类
*
* @author fei
* @since 2019-11-21 13:17
*/
public class XyjUtils {
private static final Log log = LogFactory.get();
private static List basicObjects = new ArrayList();
private static List objectMethods = new ArrayList<>();
static {
basicObjects.add(Integer.class);
basicObjects.add(Long.class);
basicObjects.add(String.class);
basicObjects.add(Byte.class);
basicObjects.add(Boolean.class);
basicObjects.add(Double.class);
basicObjects.add(Float.class);
basicObjects.add(BigDecimal.class);
basicObjects.add(BigInteger.class);
basicObjects.add(long.class);
basicObjects.add(int.class);
basicObjects.add(boolean.class);
basicObjects.add(double.class);
basicObjects.add(float.class);
basicObjects.add(Date.class);
}
static {
Class objectClass = Object.class;
Method[] methods1 = objectClass.getMethods();
for (Method method : methods1) {
objectMethods.add(method.getName());
}
objectMethods.add("initBinder");
}
private Xyj xyj;
private XyjUtils(Xyj xyj) {
this.xyj = xyj;
}
/**
* 初始化XyjUtils
*
* @param url 小幺鸡地址
* @param email 邮箱账号
* @param password 密码
* @return XyjUtils
*/
public static XyjUtils create(String url, String email, String password) {
return new XyjUtils(new Xyj(url, email, password));
}
/**
* 初始化XyjUtils
*
* @param url 小幺鸡地址
* @param cookie cookie
* @return XyjUtils
*/
public static XyjUtils create(String url, String cookie) {
return new XyjUtils(new Xyj(url, cookie));
}
public String project(String projectName, String projectUrl) {
String projectId = xyj.createProject(projectName);
// 初始化全局变量
xyj.createGlobal(projectId, projectUrl);
return projectId;
}
private static Map responseMap;
private static String dataKey;
private static String dataDesc;
/**
* 自定义返回结果 result
*
* @param response response
* @param key dataKey
* @param desc dataDesc
*/
public void customizeResult(Map response, String key, String desc) {
responseMap = response;
dataKey = key;
dataDesc = desc;
}
/**
* 根据包名创建文档
*
* @param packageName 包名
* @param projectId 项目ID
*/
public void docByPackageName(String packageName, String projectId) {
List> classes = ClassUtil.getClasses(packageName);
for (Class> clazz : classes) {
doc(clazz, projectId);
}
}
/**
* 创建文档
*
* @param className 包名+类名
* @param projectId 项目ID
* @throws ClassNotFoundException 找不到类异常
*/
public void doc(String className, String projectId) throws ClassNotFoundException {
Class clazz = Class.forName(className);
doc(clazz, projectId, null);
}
/**
* 创建文档
*
* @param clazz class
* @param projectId 项目ID
*/
public void doc(Class clazz, String projectId) {
doc(clazz, projectId, null);
}
/**
* 创建文档
* @param clazz class
* @param projectId 项目ID
* @param methodName 方法名
*/
public void doc(Class clazz, String projectId, String methodName) {
RequestMapping requestMapping = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
if (requestMapping == null) {
return;
}
Api clazzApi = (Api) clazz.getAnnotation(Api.class);
if (clazzApi == null) {
return;
}
// 需要登录
boolean authFlag = true;
Annotation[] clazzAnnotations = clazz.getAnnotations();
for (Annotation clazzAnnotation : clazzAnnotations) {
Class extends Annotation> aClass = clazzAnnotation.annotationType();
String simpleName = aClass.getSimpleName();
if ("NotAuth".equals(simpleName)) {
authFlag = false;
}
}
System.out.println(requestMapping.value()[0]);
Method[] methods = clazz.getMethods();
String preUrl = "$prefix$" + requestMapping.value()[0];
// 创建文件目录
String parentId = xyj.createFolder(clazzApi.value(), projectId);
for (Method method : methods) {
if (objectMethods.contains(method.getName())) {
continue;
}
if (StrUtil.isNotBlank(methodName) && !methodName.equals(method.getName())) {
continue;
}
DocContent docContent = new DocContent();
int flag = 0;
Api api = null;
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
Class extends Annotation> annotClass = annotation.annotationType();
String simpleName = annotClass.getSimpleName();
if (simpleName.endsWith("Mapping")) {
flag++;
setReqMethod(docContent, preUrl, annotation, simpleName);
}
if (authFlag) {
if ("NotAuth".equals(simpleName)) {
authFlag = false;
}
}
if (Api.class.equals(annotClass)) {
api = (Api) annotation;
}
}
if (flag == 0) {
continue;
}
if (api != null) {
// 创建文档
String docId = xyj.createDoc(parentId, api.value(), projectId);
System.out.println("apiResult:" + api.result());
// 请求方法
if (isJson(method)) {
docContent.setDataType("JSON");
}
// 请求头
if (authFlag) {
docContent.setRequestHeaderArg(DocData.create("token", "用户令牌"));
}
// 接口描述
docContent.setDescription(api.description());
// 请求参数
setRequestParams(method, docContent);
// 返回参数
setResponseParams(method, api.result(), docContent);
System.out.println("docContent:" + JSONUtil.toJsonStr(docContent));
// 更新文档
Doc doc = new Doc()
.setDocId(docId)
.setContent(docContent);
xyj.updateDoc(doc);
}
}
}
private void setResponseParams(Method method, Class> result, DocContent docContent) {
Class returnClass = method.getReturnType();
String returnName = returnClass.getSimpleName();
DocData data = null;
if ("void".equals(returnName)) {
log.info("无返回值");
} else if ("TableDataInfo".equals(returnName)) {
docContent.setResponseArgs(DocData.create("total", "总记录数"),
DocData.create("code", "消息状态码"),
DocData.create("msg", "消息内容"));
data = DocData.create("rows", "列表数据");
} else if ("AjaxResult".equals(returnName)) {
// 响应头
docContent.setResponseArgs(DocData.create("code", "消息状态码"),
DocData.create("msg", "消息内容"));
data = DocData.create("data", "数据");
} else {
Set> entries = responseMap.entrySet();
for (Map.Entry entry : entries) {
docContent.setResponseArg(DocData.create(entry.getKey(), entry.getValue()));
}
data = DocData.create(dataKey, dataDesc);
}
if (data == null) {
return;
}
if (void.class.equals(result)) {
docContent.setResponseArg(data);
return;
}
data.addChildren(getDocData(result));
docContent.setResponseArg(data);
}
private void setReqMethod(DocContent docContent, String preUrl, Annotation annotation, String simpleName) {
String url = preUrl;
String requestMethod = simpleName.replace("Mapping", "").toUpperCase();
docContent.setRequestMethod(requestMethod);
String[] values = null;
if (requestMethod.equals("POST")) {
PostMapping postMapping = (PostMapping) annotation;
values = postMapping.value();
} else if ("GET".equals(requestMethod)) {
GetMapping postMapping = (GetMapping) annotation;
values = postMapping.value();
} else if ("DELETE".equals(requestMethod)) {
DeleteMapping postMapping = (DeleteMapping) annotation;
values = postMapping.value();
} else if ("PUT".equals(requestMethod)) {
PutMapping postMapping = (PutMapping) annotation;
values = postMapping.value();
}
if (values != null && values.length > 0) {
String value = values[0];
url += value.startsWith("/") ? value : "/" + value;
}
docContent.setUrl(url);
log.info("请求方法:{},请求地址:{}", requestMethod, url);
}
private void setRequestParams(Method method, DocContent docContent) {
Class>[] parameterTypes = method.getParameterTypes();
for (Class> parameterType : parameterTypes) {
log.info("参数类型:{}", parameterType);
// 判断是否为基本包装类
// 或者是基本类型
if (basicObjects.contains(parameterType)) {
// 判断是否带 @PathVariable 注解
boolean pathVariable = isPathVariable(method);
if(!pathVariable){
}
continue;
}
docContent.setRequestArgs(getDocData(parameterType));
}
}
public List getDocData(Class clazz) {
DomainParse domainParse = ParseUtils.domain(clazz);
AssertUtils.notNull(domainParse, "实体类解析失败");
List fieldList =
AssertUtils.notNull(domainParse.getFieldList(), "实体类解析失败");
List docDataList = new ArrayList<>();
for (DomainParse.Field parseField : fieldList) {
String name = parseField.getName();
String comment = parseField.getComment();
Field field = ReflectUtil.getField(clazz, name);
Class> type = field.getType();
DocData docData = DocData.create(name, comment);
// 是基本对象
if (basicObjects.contains(type)) {
docDataList.add(docData);
continue;
}
// 不是基本对象
// list 还是 普通对象
if (List.class.equals(type)) {
// 如果是List类型,得到其Generic的类型
Type genericType = field.getGenericType();
if (genericType == null) {
docDataList.add(docData);
continue;
}
// 如果是泛型参数的类型
if (genericType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericType;
//得到泛型里的class类型对象
Class> genericClazz = (Class>) pt.getActualTypeArguments()[0];
if(!clazz.equals(genericClazz)){
// 可能会出现递归死循环
docData.addChildren(getDocData(genericClazz));
}
docData.setType("array[object]");
}
} else {
// 可能会出现递归死循环
if(!clazz.equals(field.getType())){
docData.addChildren(getDocData(field.getType()));
}
docData.setType("object");
}
docDataList.add(docData);
}
return docDataList;
}
/**
* 获取给 "方法参数" 进行注解的值
*
* @param method 要获取参数名的方法
* @return 按参数顺序排列的参数名列表
*/
private boolean isJson(Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations == null || parameterAnnotations.length == 0) {
return false;
}
for (Annotation[] parameterAnnotation : parameterAnnotations) {
for (Annotation annotation : parameterAnnotation) {
if (annotation instanceof RequestBody) {
return true;
}
}
}
return false;
}
/**
* 获取给 "方法参数" 进行注解的值
*
* @param method 要获取参数名的方法
* @return 按参数顺序排列的参数名列表
*/
private boolean isPathVariable(Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations == null || parameterAnnotations.length == 0) {
return false;
}
for (Annotation[] parameterAnnotation : parameterAnnotations) {
for (Annotation annotation : parameterAnnotation) {
if (annotation instanceof PathVariable) {
return true;
}
}
}
return false;
}
}