<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> body, table { color: #333; font-family: Arial, sans-serif; font-size: 14px; line-height: 1.42857142857143; color: #333; } strong, b { font-weight: bold; } li { display: list-item; text-align: -webkit-match-parent; list-style-type: disc; } table { display: table; border-collapse: separate; border-spacing: 2px; border-color: grey; } thead { display: table-header-group; vertical-align: middle; border-color: inherit; } tr { display: table-row; vertical-align: inherit; border-color: inherit; } table.tablesorter > thead > tr > th { background: #F0F0F0 center right no-repeat; padding-right: 15px; cursor: pointer; } .wiki-content .tablesorter-header-inner, table.confluenceTable th.confluenceTh { color: #333333; } .confluenceTable { border-collapse: collapse; } .confluenceTable:first-child { margin-top: 0; } .confluenceTable, .table-wrap { margin: 10px 0 0 0; overflow-x: auto; } .confluenceTh, .confluenceTd { border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left; } </style> </head> <body> <ul> <li> <strong>功能描述</strong> <br/> $funcDescribe <br/> <br/> </li> <li> <strong>接口信息</strong> <br/> 1,请求方式:$requestMethod <br/> 2,服务地址:$requestUrl <br/> 3,请求参数类型:Json <br/> 4,返回参数类型:Json <br/> <br/> </li> <li> <p> <strong>接口参数</strong> <br/> $inInfo </p> $inTable <br/> </li> <li> <p> <strong>返回值</strong> <br/> $returnInfo </p> $returnTable </li> </ul> </body> </html>
public class DocGeneratorGA { public static void main(String[] args) throws IOException, TemplateException { DocGeneratorGA docGeneratorGA = new DocGeneratorGA(); docGeneratorGA.generate(new LetterCheckController(), "delete"); } private <T> void generate(T t, String methodName) throws IOException, TemplateException { // first step:instance freemarker configuration Configuration configuration = new Configuration(); // second step:set configuration directory String dir = DocGeneratorGA.class.getResource("/phalaenopsis/common/doc").getPath(); configuration.setDirectoryForTemplateLoading(new File(dir)); Template template = configuration.getTemplate("ApiDocTemplate.html"); String exportDir = JOptionPane.showInputDialog("请输入文档导出目录"); // export html Writer out = new FileWriter(new File(exportDir + File.separator + methodName + ".html")); Map map = new DocGeneratorGA().defineData(t, methodName); template.process(map, out); out.flush(); out.close(); } private <T> Map defineData(T t, String methodName) { DocGeneratorTools docGeneratorTools = new DocGeneratorTools(); Map map = docGeneratorTools.returnMethodParamMap(t, methodName); return map; }
public class DocGeneratorTools { /** * 添加slf4j写日志对象 */ private static final Logger logger = LoggerFactory.getLogger(DocGeneratorTools. class); /** * 设置Map大小常量 */ private static final int MAP_SIZE = 6; /** * 名称 */ private static final String NAME = "name"; /** * 说明 */ private static final String DESCRIBE = "describe"; /** * 类型 */ private static final String TYPE = "type"; /** * 是否必要参数 */ private static final String REQUIRE = "require"; /** * 例子 */ private static final String EXAMPLE = "example"; /** * Generic type */ private static final String SUB_CLASS = "subClass"; /** * 反射获取实体字段中,需要排除的字段。如 */ private static final String[] EXCLUDE_FIELDS = {"serialVersionUID"}; /** * 包装类型类全名 */ private static String[] classes = { "java.lang.Byte", "java.lang.Short", "java.lang.Integer", "java.lang.Long", "java.lang.Double", "java.lang.Float", "java.lang.Boolean", "java.util.Date" }; public <T> Map returnMethodParamMap(T t, String methodName) { Map<String, Object> map = new HashMap<String, Object>(); Method[] methods = t.getClass().getMethods(); RequestMapping clazzRequestMapper = t.getClass().getAnnotation(RequestMapping.class); List<Method> listMethod = Arrays.asList(methods); Method method = Linq.extEquals(listMethod, "name", methodName); RequestMapping methodRequestMapper = method.getAnnotation(RequestMapping.class); //0,得到方法描述 ApiOperation apiOperation = method.getAnnotation(ApiOperation.class); map.put("funcDescribe", apiOperation.value()); //1,得到完整的URL路径 String mappingUrl = clazzRequestMapper.value()[0] + methodRequestMapper.value()[0]; map.put("requestUrl", mappingUrl); //2,得到请求方法:GET、POST、PUT、Delete String requestMethod = methodRequestMapper.method()[0].name(); map.put("requestMethod", requestMethod); // 2.1得到返回的GenericReturnType Type genericReturnType = null; Type returnType = method.getGenericReturnType(); if (returnType instanceof ParameterizedType) { Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments(); genericReturnType = genericTypes[0]; } // 2.2得到传入参数泛型 Type genericParameterType = null; Type[] parameterTypes = method.getGenericParameterTypes(); for (Type parameterType : parameterTypes) { if (parameterType instanceof ParameterizedType) { Type[] genericTypes = ((ParameterizedType) parameterType).getActualTypeArguments(); genericParameterType = genericTypes[0]; } } //3,传入参数 Parameter[] inParameters = method.getParameters(); List<Map<String, String>> inListParam = new ArrayList<>(); for (Parameter parameter : inParameters) { if (parameter.getType().isPrimitive()) { // 简单类型 inListParam.add(getPrimitiveParameterMap(parameter)); } else if (parameter.getType().isArray()) { // 是否为集合 } else if (Arrays.binarySearch(classes, parameter.getType().getName()) > -1) { // 包装类型 inListParam.add(getPrimitiveParameterMap(parameter)); } else if (parameter.getType() == java.util.List.class) { } else { // 普通类 Field[] fields = parameter.getType().getDeclaredFields(); for (Field field : fields) { if (Arrays.binarySearch(EXCLUDE_FIELDS, field.getName()) == -1) { inListParam.add(getFieldMap(field, genericParameterType)); } } } } map.put("inList", inListParam); //4,得到返回参数 Class<?> clazz = method.getReturnType(); List<Map<String, String>> outListParam = new ArrayList<>(); if (clazz.isPrimitive()) { // 简单类型 outListParam.add(getReturnPrimitiveMap(clazz)); } else if (clazz.isArray()) { // 数组 } else if (Arrays.binarySearch(classes, clazz.getName()) > -1) { // 包装类型 outListParam.add(getReturnPrimitiveMap(clazz)); } else { // 实体类 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (Arrays.binarySearch(EXCLUDE_FIELDS, field.getName()) == -1) { outListParam.add(getFieldMap(field, genericReturnType)); } } } map.put("outList", outListParam); return map; } /** * 简单类型map */ private Map<String, String> returnPrimitiveMap; /** * 获取返回简单类型map * * @return */ private Map getReturnPrimitiveMap(Class<?> clazz) { returnPrimitiveMap = new HashMap<>(MAP_SIZE); primitiveMap.put(TYPE, clazz.getName()); primitiveMap.put(NAME, ""); primitiveMap.put(DESCRIBE, ""); primitiveMap.put(REQUIRE, ""); primitiveMap.put(EXAMPLE, ""); return returnPrimitiveMap; } /** * 包装类型map */ private Map<String, String> returnWrapMap; /** * 返回包装类型map * * @param clazz * @return */ private Map getReturnWarpMap(Class<?> clazz) { returnPrimitiveMap = getReturnPrimitiveMap(clazz); return returnPrimitiveMap; } private Map<String, String> primitiveMap; /** * 返回简单类型Map * * @param parameter * @return */ private Map getPrimitiveParameterMap(Parameter parameter) { //如果为简单类型 primitiveMap = new HashMap<>(MAP_SIZE); primitiveMap.put(TYPE, parameter.getType().getName()); ApiParam apiParam = parameter.getDeclaredAnnotation(ApiParam.class); PathParam pathParam = parameter.getDeclaredAnnotation(PathParam.class); RequestParam requestParam = parameter.getDeclaredAnnotation(RequestParam.class); primitiveMap.put(NAME, ""); primitiveMap.put(DESCRIBE, ""); primitiveMap.put(REQUIRE, ""); primitiveMap.put(EXAMPLE, ""); if (null != pathParam) { primitiveMap.put(NAME, pathParam.value()); } if (null != requestParam) { primitiveMap.put(NAME, requestParam.value()); primitiveMap.put(REQUIRE, requestParam.required() ? "是" : "否"); } if (null != apiParam) { primitiveMap.put(NAME, ""); primitiveMap.put(DESCRIBE, apiParam.value()); primitiveMap.put(REQUIRE, apiParam.required() ? "是" : "否"); primitiveMap.put(EXAMPLE, apiParam.example()); } return primitiveMap; } /** * 获取包装类型 */ private Map<String, String> warpMap; /** * 返回包装类型Map * * @return */ private Map getWarpperMap(Parameter parameter) { warpMap = getPrimitiveParameterMap(parameter); return warpMap; } /** * 成员字段 */ private Map<String, Object> fieldMap; /** * 泛型成员字段 */ private Map<String, Object> genericFieldMap; private Map createFieldMap(Field field, Map map, ApiModelProperty apiModel) { map = new HashMap<>(MAP_SIZE); map.put(NAME, field.getName()); map.put(TYPE, field.getType().getName()); if (null != apiModel) { map.put(DESCRIBE, apiModel.value()); map.put(REQUIRE, apiModel.required() ? "是" : "否"); map.put(EXAMPLE, apiModel.example()); } else { map.put(DESCRIBE, ""); map.put(REQUIRE, "否"); map.put(EXAMPLE, ""); } return map; } /** * @return */ private Map getGenericFieldMap(Field field) { ApiModelProperty apiModelProperty = field.getDeclaredAnnotation(ApiModelProperty.class); genericFieldMap = new HashMap<>(MAP_SIZE); genericFieldMap = createFieldMap(field, genericFieldMap, apiModelProperty); return genericFieldMap; } /** * 获取字段map * * @param field * @return */ private Map getFieldMap(Field field, Type methodGenericType) { ApiModelProperty apiModelProperty = field.getDeclaredAnnotation(ApiModelProperty.class); fieldMap = new HashMap<>(MAP_SIZE); fieldMap = createFieldMap(field, fieldMap, apiModelProperty); Type genericTypeSingle = field.getGenericType(); if (null != genericTypeSingle) { if (genericTypeSingle instanceof TypeVariable) { if (null != methodGenericType) { List<Map<String, Object>> genericMapList = new ArrayList<Map<String, Object>>(); Field[] genericFields = new Field[0]; try { genericFields = Class.forName(methodGenericType.getTypeName()).getDeclaredFields(); } catch (ClassNotFoundException e) { e.printStackTrace(); } for (Field subField : genericFields) { if (Arrays.binarySearch(EXCLUDE_FIELDS, subField.getName()) == -1) { genericMapList.add(getGenericFieldMap(subField)); } } fieldMap.put(SUB_CLASS, genericMapList); } } } // 如果field不是简单类型、不是包装类型、 if (field.getType() == java.util.List.class || field.getType().isArray()) { //如果是List类型,得到GeneraticType Type genericType = field.getGenericType(); if (null != genericType) { // 如果是泛型参数类型 if (genericType instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) genericType; List<Map<String, Object>> genericMapList = new ArrayList<Map<String, Object>>(); if (pt.getActualTypeArguments()[0] instanceof Class<?>) { Class<?> genericClazz = (Class<?>) pt.getActualTypeArguments()[0]; Field[] genericFields = genericClazz.getDeclaredFields(); for (Field subField : genericFields) { if (Arrays.binarySearch(EXCLUDE_FIELDS, field.getName()) == -1) { genericMapList.add(getGenericFieldMap(subField)); } } } else { Field[] genericFields = new Field[0]; try { if (null != methodGenericType) { genericFields = Class.forName(methodGenericType.getTypeName()).getDeclaredFields(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } for (Field subField : genericFields) { if (Arrays.binarySearch(EXCLUDE_FIELDS, subField.getName()) == -1) { genericMapList.add(getGenericFieldMap(subField)); } } } fieldMap.put(SUB_CLASS, genericMapList); } } } return fieldMap; } }