需要的包
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.github.biezhi</groupId>
<artifactId>TinyPinyin</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.20</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
<scope>compile</scope>
</dependency>
package com.xiaoyun.shopadmin.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;
public class Swagger2Ftl {
public static final String THIS_PACK = "com.xiaoyun.shopadmin";
public static final String javaPath = System.getProperty("user.dir") + File.separator + "src" + File.separator + "main" + File.separator + "java";
public static final String[] preNames = {"Sms", "Admin", "Sys", "Ums", "Cms", "Ims", "Mall", "Pms"};
public static final String[] attrNames = {"integer", "string", "boolean", "object"};
public static final String[] reqMethod_str = {"options", "head"};
public static final File classPathResource = new ClassPathResource("sw.json").getFile();
public static final File entityFile = new ClassPathResource("entity.ftl").getFile();
public static final File controllerFile = new ClassPathResource("controller.ftl").getFile();
public static void main(String[] args) {
JSONObject json = JSONUtil.readJSONObject(classPathResource, Charset.defaultCharset());
SwRoot swRoot = JSONUtil.toBean(json, SwRoot.class);
Map<String, SwPojo> definitions = swRoot.getDefinitions();
List<Entity> entityList = new ArrayList<>(definitions.size());
definitions.forEach((key, value) -> {
toEntity(entityList, value);
});
for (Entity entity : entityList) {
String outJavaFile = jointClassPath(entity.getPackageName(), entity.getClassName());
process(entity, entityFile, outJavaFile);
}
List<Controller> controllerList = getControllerList(swRoot);
for (Controller controller : controllerList) {
String outJavaFile = jointClassPath(controller.getPackageName(), controller.getClassName());
process(controller, controllerFile, outJavaFile);
}
}
private static List<Controller> getControllerList(SwRoot swRoot) {
List<Controller> controllerList = new ArrayList<>();
List<Tag> tags = swRoot.getTags();
initController(controllerList, tags);
Map<String, Controller> controllerMap = controllerList.stream().collect(Collectors.toMap(Controller::getClassName, item -> item));
Map<String, Map<String, Property>> paths = swRoot.getPaths();
paths.forEach((path, map) -> {
map.forEach((reqMethod, property) -> {
if (checkReqMethod(reqMethod)) {
return;
}
Methods methods = new Methods();
methods.setMethodUrl(path);
String[] tempTags = property.getTags();
Controller controller = controllerMap.get((checkControllerClassName(tempTags[0])));
if (tempTags.length == 2) {
methods.setTag(tempTags[1]);
}
Set<Field> fieldList = new HashSet<>();
List<JSONObject> parameters = property.getParameters();
for (JSONObject parameter : parameters) {
String in = (String) parameter.get("in");
if ("header".equals(in)) {
continue;
}
Field field = new Field();
String type = getType(controller, parameter);
String name = (String) parameter.get("name");
String description = (String) parameter.get("description");
Object aDefault = parameter.get("default");
if (Objects.nonNull(aDefault)) {
field.setDefaultValue(String.valueOf(aDefault));
}
Boolean required = (Boolean) parameter.get("required");
if (required) {
field.setRequired(required);
}
field.setFieldName(name);
field.setFieldDesc(description);
field.setFieldAttr(firstName2Up(checkAttrName(type)));
fieldList.add(field);
}
JSONObject jsonObject = property.getResponses().get("200");
Object schema = jsonObject.get("schema");
if (schema != null) {
Object resBodyDesc = ((JSONObject) schema).get("$ref");
if (resBodyDesc == null) {
resBodyDesc = ((JSONObject) schema).get("type");
}
String desc = String.valueOf(resBodyDesc);
methods.setResBodyDesc(desc);
String body = desc2ResBody(desc);
if (!checkDataType(body)) {
setControllerImport(controller, body);
}
methods.setResBody(checkAttrName(body));
}
methods.setReqBody(fieldList);
methods.setReqMethod(firstName2Up(reqMethod));
methods.setMethodDesc(property.getSummary());
methods.setMethodName(property.getOperationId());
Set<Methods> methodsList = controller.getMethodsList();
if (methodsList == null) {
methodsList = new HashSet<>();
}
methodsList.add(methods);
controller.setMethodsList(methodsList);
});
});
return controllerList;
}
private static boolean checkReqMethod(String reqMethod) {
for (String s : reqMethod_str) {
if (s.equals(reqMethod)) {
return true;
}
}
return false;
}
private static String getType(Controller controller, JSONObject parameter) {
String type = null;
if ("body".equals(parameter.get("in"))) {
JSONObject object = (JSONObject) parameter.get("schema");
Object schemaType = object.get("type");
String ref = null;
if (Objects.nonNull(schemaType) && "array".equals(String.valueOf(schemaType))) {
JSONObject tempJson = ((JSONObject) object.get("items"));
Object $ref = tempJson.get("$ref");
if (Objects.nonNull($ref)) {
ref = String.valueOf($ref);
type = ref2ClassName(ref);
setControllerImport(controller, type);
} else {
type = type2List(String.valueOf(tempJson.get("type")));
}
} else {
ref = (String) object.get("$ref");
if (ref == null) {
type = String.valueOf(schemaType);
} else {
type = ref2ClassName(ref);
if (Validator.hasChinese(type)) {
type = chinese2Pinyin(type);
}
if (!checkDataType(type)) {
setControllerImport(controller, firstName2Up(type));
}
}
}
} else {
type = (String) parameter.get("type");
if ("array".equals(type)) {
type = (String) ((JSONObject) parameter.get("items")).get("type");
type = type2List(type);
} else if ("ref".equals(type)) {
type = "Integer";
} else if ("file".equals(type)) {
type = "MultipartFile";
}
}
return type;
}
private static boolean checkDataType(String type) {
type = type.toLowerCase();
for (String attrName : attrNames) {
if (attrName.equals(type)) {
return true;
}
}
return false;
}
private static void setControllerImport(Controller controller, String type) {
Set<String> importClassName = controller.getImportClassName();
if (importClassName == null) {
importClassName = new HashSet<>();
}
importClassName.add(preNameAndEndNameGroup(type) + "." + type);
controller.setImportClassName(importClassName);
}
private static void setEntityImport(Entity entity, String type) {
Set<String> importClassName = entity.getImportClassName();
if (importClassName == null) {
importClassName = new HashSet<>();
}
importClassName.add(preNameAndEndNameGroup(type) + "." + type);
entity.setImportClassName(importClassName);
}
private static void initController(List<Controller> controllerList, List<Tag> tags) {
tags.stream().forEach(key -> {
String name = key.getName();
if (name.toLowerCase().endsWith("controller")) {
Controller controller = new Controller();
controller.setClassName(checkControllerClassName(name));
controller.setPackageName(preNameAndEndNameGroup(name));
controller.setDesc(key.getDescription());
controllerList.add(controller);
}
});
}
private static String desc2ResBody(String desc) {
if (desc.contains("/")) {
String[] split = desc.split("/");
desc = split[split.length - 1];
}
if (desc.contains("?")) {
desc = desc.substring(0, desc.indexOf("?"));
}
return desc;
}
private static String checkControllerClassName(String name) {
name = chinese2Pinyin(name);
if (!name.contains("-")) {
return name;
}
String[] split = name.split("-");
StringBuilder sb = new StringBuilder();
for (String s : split) {
sb.append(firstName2Up(s));
}
return sb.toString();
}
private static String jointClassPath(String packageName, String className) {
StringBuilder sb = new StringBuilder(javaPath);
String[] split = packageName.split("\\.");
for (int i = 0; i < split.length; i++) {
sb.append(File.separator).append(split[i]);
}
return sb.append(File.separator).append(className).append(".java").toString();
}
public static void process(Object obj, File ftlFile, String outFile) {
File file = new File(outFile);
File outParentFile = file.getParentFile();
if (!outParentFile.exists()) {
outParentFile.mkdirs();
}
Configuration configuration = new Configuration(Configuration.getVersion());
try (Writer out = new FileWriter(file)) {
configuration.setDirectoryForTemplateLoading(ftlFile.getParentFile());
configuration.setDefaultEncoding("utf-8");
Template template = configuration.getTemplate(ftlFile.getName());
template.process(obj, out);
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
}
private static void toEntity(List<Entity> entityList, SwPojo swPojo) {
Map<String, SwProperties> properties = swPojo.getProperties();
if (properties == null) {
return;
}
String title = swPojo.getTitle();
String className = firstName2Up(title);
if (className.contains("?")) {
return;
}
Entity entity = new Entity();
className = chinese2Pinyin(className);
entity.setDesc(title);
List<Field> fieldList = new ArrayList<>();
properties.forEach((key, value) -> {
Field field = new Field();
String type = value.getType();
if (type == null) {
String $ref = value.get$ref();
String name = ref2ClassName($ref);
String attrName = firstName2Up(name);
field.setFieldAttr(attrName);
field.setFieldName(firstName2Down(key));
setEntityImport(entity, name);
} else if ("array".equals(type)) {
Map<String, String> items = value.getItems();
if (CollUtil.isNotEmpty(items)) {
String tempType = items.get("type");
if (null != tempType) {
field.setFieldAttr(type2List(tempType));
field.setFieldName(firstName2Down(key));
} else {
String attrName = firstName2Up(ref2ClassName(items.get("$ref")));
if (attrName.startsWith("Map")) {
if (attrName.contains("?")) {
int index = attrName.indexOf("?");
String[] split = attrName.substring(index + 1, attrName.length() - 1).split(",");
attrName = attrName.substring(0, index) + "<" + firstName2Up(split[0]) + "," + firstName2Up(split[1]) + ">";
} else {
attrName = "Map<String,String>";
}
} else {
setEntityImport(entity, attrName);
}
field.setFieldName(firstName2Down(key));
field.setFieldAttr("List<" + attrName + ">");
}
}
} else {
field.setFieldAttr(checkAttrName(type));
field.setFieldName(firstName2Down(key));
}
field.setFieldDesc(value.getDescription());
fieldList.add(field);
});
entity.setFields(fieldList);
entity.setClassName(className);
entity.setPackageName(preNameAndEndNameGroup(className));
entityList.add(entity);
}
private static String type2List(String tempType) {
return "List<" + checkAttrName(tempType) + ">";
}
private static String chinese2Pinyin(String className) {
if (Validator.hasChinese(className)) {
String[] split = PinyinUtil.getPinyin(className, ",").split(",");
StringBuilder sb = new StringBuilder();
for (String str : split) {
sb.append(firstName2Up(str));
}
if (className.contains("&")) {
className = sb.toString().replace("&", "And");
} else {
className = sb.toString();
}
}
return className;
}
private static String checkAttrName(String attr) {
for (String attrName : attrNames) {
if (attrName.equals(attr)) {
return firstName2Up(attrName);
}
}
if ("number".equals(attr)) {
return "BigDecimal";
}
return attr;
}
private static String preNameAndEndNameGroup(String name) {
StringBuilder sb = new StringBuilder(THIS_PACK);
for (int i = 0; i < preNames.length; i++) {
String preName = preNames[i];
if (name.startsWith(preNames[i])) {
sb.append(".").append(firstName2Down(preName));
}
}
if (name.toLowerCase().endsWith("controller")) {
sb.append(".").append("controller");
} else {
sb.append(".").append("pojo");
}
if (name.endsWith("BO")) {
sb.append(".").append("bo");
} else if (name.endsWith("PO")) {
sb.append(".").append("po");
}
return sb.toString();
}
private static String firstName2Up(String name) {
return StrUtil.upperFirst(name);
}
private static String firstName2Down(String name) {
return StrUtil.lowerFirst(name);
}
private static String ref2ClassName(String $ref) {
if (!$ref.contains("/")) {
return null;
}
String[] split = $ref.split("/");
return split[split.length - 1];
}
@Data
public static class Controller {
private String packageName;
private String className;
private Set<String> importClassName;
private Set<Methods> methodsList;
private String desc;
}
@Data
@EqualsAndHashCode(of = {"methodUrl", "reqMethod"})
public static class Methods {
private String methodName;
private String methodUrl;
private String methodDesc;
private String reqMethod;
private Set<Field> reqBody;
private String resBody;
private String resBodyDesc;
private String tag;
}
@Data
public static class Entity {
private String packageName;
private String className;
private Set<String> importClassName;
private List<Field> fields;
private String desc;
}
@Data
@EqualsAndHashCode(of = {"fieldName"})
public static class Field {
private String fieldAttr;
private String fieldName;
private String fieldDesc;
private Boolean required;
private String defaultValue;
}
@Data
public class SwRoot {
private String swagger;
private String info;
private String host;
private String basePath;
private List<Tag> tags;
private Map<String, Map<String, Property>> paths;
private Map<String, SwPojo> definitions;
}
@Data
public class Property {
private String[] tags;
private String summary;
private String operationId;
private String[] produces;
private List<JSONObject> parameters;
private Map<String, JSONObject> responses;
private String deprecated;
}
@Data
public class Tag {
private String name;
private String description;
}
@Data
public class SwPojo {
private String type;
private Map<String, SwProperties> properties;
private String title;
}
@Data
public class SwProperties {
private String type;
private String format;
private String description;
private String $ref;
private Map<String, String> items;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String get$ref() {
return $ref;
}
public void set$ref(String $ref) {
this.$ref = $ref;
}
public Map<String, String> getItems() {
return items;
}
public void setItems(Map<String, String> items) {
this.items = items;
}
}
}
entity.ftl
package ${packageName};
<#if importClassName??>
<#list importClassName as name>
import ${name};
</#list>
</#if>
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import lombok.Data;
import io.swagger.annotations.ApiModelProperty;
<#if desc??>
</#if>
@Data
public class ${className} implements Serializable {
<#list fields as fieldBean>
<#if fieldBean.fieldDesc??>
@ApiModelProperty(value = "${fieldBean.fieldDesc}")
</#if>
private <#if fieldBean.fieldAttr??>${fieldBean.fieldAttr}<#else>String</#if> ${fieldBean.fieldName};
</#list>
}
controller.ftl
package ${packageName};
<#if importClassName??>
<#list importClassName as item>
import ${item};
</#list>
</#if>
import org.springframework.web.multipart.MultipartFile;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.time.LocalDateTime;
import java.math.BigDecimal;
@RestController
<#if desc??>
@Api(tags = "${className}", description = "${desc}")
</#if>
public class ${className} {
<#list methodsList as item>
<#if item.tag??>
</#if>
@${item.reqMethod}Mapping(value = "${item.methodUrl}")
@ApiOperation("${item.methodDesc}")
<#if item.reqBody?? && (item.reqBody?size > 0)>
@ApiImplicitParams({
<#list item.reqBody as req>
<#if req.fieldName??>@ApiImplicitParam(name = "${req.fieldName}"<#if req.fieldDesc??>, value = "${req.fieldDesc}"</#if><#if req.defaultValue??>, defaultValue = "${req.defaultValue}"</#if><#if req.required??>, required = true</#if> )<#if req_has_next>,
</#if></#if></#list>})</#if>
public <#if item.resBody??>${item.resBody}<#else>String</#if> ${item.methodName}(<#if item.reqBody??><#list item.reqBody as req><#if req.fieldAttr??>${req.fieldAttr} ${req.fieldName} <#if req_has_next>,</#if></#if></#list></#if>) {
<#if item.resBody??> return new ${item.resBody}();<#else>return "OK";</#if>
}
</#list>
}
|