Prechádzať zdrojové kódy

增加开发人员工具

zhouhao 7 rokov pred
rodič
commit
cf627a1061

+ 49 - 0
hsweb-system/hsweb-system-dev-tools/pom.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-dev-tools</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework</groupId>
+            <artifactId>hsweb-utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-authorization-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-commons-controller</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.github.javaparser/javaparser-core -->
+        <dependency>
+            <groupId>com.github.javaparser</groupId>
+            <artifactId>javaparser-core</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 27 - 0
hsweb-system/hsweb-system-dev-tools/src/main/java/org/hswebframework/web/dev/tools/DevToolsAutoConfiguration.java

@@ -0,0 +1,27 @@
+package org.hswebframework.web.dev.tools;
+
+import org.hswebframework.web.dev.tools.web.FileManagerDevToolsController;
+import org.hswebframework.web.dev.tools.writer.CodeWriter;
+import org.hswebframework.web.dev.tools.writer.DefaultCodeWriter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+@Configuration
+public class DevToolsAutoConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean(CodeWriter.class)
+    public DefaultCodeWriter defaultCodeWriter() {
+        return new DefaultCodeWriter();
+    }
+
+    @Bean
+    public FileManagerDevToolsController fileManagerDevToolsController() {
+        return new FileManagerDevToolsController();
+    }
+}

+ 30 - 0
hsweb-system/hsweb-system-dev-tools/src/main/java/org/hswebframework/web/dev/tools/reader/FileInfo.java

@@ -0,0 +1,30 @@
+package org.hswebframework.web.dev.tools.reader;
+
+import lombok.Data;
+
+import java.io.File;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+@Data
+public class FileInfo {
+    private String name;
+
+    private Long length;
+
+    private String parent;
+
+    private String absolutePath;
+
+
+    public static FileInfo from(File file){
+        FileInfo info=new FileInfo();
+        info.setName(file.getName());
+        info.setLength(file.length());
+        info.setParent(file.getParent());
+        info.setAbsolutePath(file.getAbsolutePath());
+        return  info;
+    }
+}

+ 87 - 0
hsweb-system/hsweb-system-dev-tools/src/main/java/org/hswebframework/web/dev/tools/web/FileManagerDevToolsController.java

@@ -0,0 +1,87 @@
+package org.hswebframework.web.dev.tools.web;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.SneakyThrows;
+import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.controller.message.ResponseMessage;
+import org.hswebframework.web.dev.tools.reader.FileInfo;
+import org.hswebframework.web.dev.tools.writer.GeneratedCode;
+import org.hswebframework.web.dev.tools.writer.CodeWriter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+@RestController
+@RequestMapping("/dev/tools/file")
+@Authorize(permission = "dev-tools", description = "开发人员工具-文件管理")
+@Api(tags = "开发人员工具-文件管理", value = "开发人员工具-文件管理")
+public class FileManagerDevToolsController {
+
+    @Autowired
+    private CodeWriter codeWriter;
+
+    @PostMapping("/write")
+    @ApiOperation("写出文件")
+    @Authorize(action = "write", description = "写出文件")
+    public ResponseMessage<String> write(@RequestBody List<GeneratedCode> codes) {
+        return ResponseMessage.ok(codeWriter.write(codes));
+    }
+
+    @GetMapping("/list")
+    @ApiOperation("获取目录下的全部文件,不包含子目录")
+    @Authorize(action = "read", description = "读取文件")
+    public ResponseMessage<List<FileInfo>> write(@RequestParam String path) {
+        File file = new File(path);
+        if (!file.exists()) {
+            return null;
+        }
+        List<FileInfo> list;
+        if (file.isDirectory()) {
+            File[] files = file.listFiles();
+            if (files == null) {
+                list = Collections.emptyList();
+            } else {
+                list = Stream.of(files)
+                        .map(FileInfo::from)
+                        .collect(Collectors.toList());
+            }
+        } else {
+            list = Collections.singletonList(FileInfo.from(file));
+        }
+        return ResponseMessage.ok(list);
+    }
+
+    @GetMapping("/read")
+    @ApiOperation("读取文本文件内容")
+    @SneakyThrows
+    @Authorize(action = "read", description = "读取文件")
+    public ResponseMessage<String> read(@RequestParam String file) {
+        File fileInfo = new File(file);
+        if (!fileInfo.exists()) {
+            return null;
+        }
+        if (fileInfo.length() > 2 * 1024 * 1024 * 1024L) {
+            return ResponseMessage.error(500, "文件过大,无法读取");
+        }
+        List<String> list = Files.readAllLines(Paths.get(file));
+        StringJoiner joiner = new StringJoiner("\n");
+        list.forEach(joiner::add);
+        return ResponseMessage.ok(joiner.toString());
+    }
+
+}

+ 79 - 0
hsweb-system/hsweb-system-dev-tools/src/main/java/org/hswebframework/web/dev/tools/writer/ClassWriter.java

@@ -0,0 +1,79 @@
+package org.hswebframework.web.dev.tools.writer;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.comments.Comment;
+import com.github.javaparser.ast.expr.AnnotationExpr;
+import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
+import lombok.SneakyThrows;
+import org.hswebframework.utils.file.FileUtils;
+
+import java.io.File;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+public class ClassWriter {
+    @SneakyThrows
+    public static void writeClass(String file, String code) {
+        File oldClassFile = new File(file);
+        if (oldClassFile.exists()) {
+            CompilationUnit old = JavaParser.parse(oldClassFile);
+            CompilationUnit newClazz = JavaParser.parse(code);
+            Map<String, FieldDeclaration> oldFields = old
+                    .findAll(FieldDeclaration.class)
+                    .stream()
+                    .collect(Collectors.toMap(declaration -> declaration.getVariable(0).getNameAsString(), Function.identity()));
+
+
+            Map<String, MethodDeclaration> oldMethod = old
+                    .findAll(MethodDeclaration.class)
+                    .stream()
+                    .collect(Collectors.toMap(NodeWithSimpleName::getNameAsString, Function.identity()));
+
+            newClazz.findAll(FieldDeclaration.class).forEach(declaration -> {
+                String name = declaration.getVariable(0).getNameAsString();
+                if (oldFields.get(name) == null) {
+                    VariableDeclarator declarator = declaration.getVariable(0);
+                    FieldDeclaration newField = old.getType(0)
+                            .addField(declarator.getType(), declarator.getNameAsString(),
+                                    declaration.getModifiers().toArray(new Modifier[]{}));
+
+                    declaration.getJavadocComment().ifPresent(newField::setJavadocComment);
+                    for (Comment comment : declaration.getAllContainedComments()) {
+                        newField.setComment(comment);
+                    }
+                    for (AnnotationExpr annotationExpr : declaration.getAnnotations()) {
+                        newField.addAnnotation(annotationExpr.clone());
+                    }
+                }
+            });
+            newClazz.findAll(MethodDeclaration.class).forEach(declaration -> {
+                String name = declaration.getNameAsString();
+                if (oldMethod.get(name) == null) {
+                    MethodDeclaration newMethod = old.getType(0)
+                            .addMethod(name, declaration.getModifiers().toArray(new Modifier[]{}));
+
+                    declaration.getJavadocComment().ifPresent(newMethod::setJavadocComment);
+                    for (Comment comment : declaration.getAllContainedComments()) {
+                        newMethod.setComment(comment);
+                    }
+                    for (AnnotationExpr annotationExpr : declaration.getAnnotations()) {
+                        newMethod.addAnnotation(annotationExpr.clone());
+                    }
+                }
+            });
+            code = old.toString();
+        }
+
+        FileUtils.writeString2File(code, file, "utf-8");
+    }
+}

+ 11 - 0
hsweb-system/hsweb-system-dev-tools/src/main/java/org/hswebframework/web/dev/tools/writer/CodeWriter.java

@@ -0,0 +1,11 @@
+package org.hswebframework.web.dev.tools.writer;
+
+import java.util.List;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+public interface CodeWriter {
+    String write(List<GeneratedCode> codes);
+}

+ 59 - 0
hsweb-system/hsweb-system-dev-tools/src/main/java/org/hswebframework/web/dev/tools/writer/DefaultCodeWriter.java

@@ -0,0 +1,59 @@
+package org.hswebframework.web.dev.tools.writer;
+
+import lombok.SneakyThrows;
+import org.hswebframework.utils.file.FileUtils;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+public class DefaultCodeWriter implements CodeWriter {
+
+    @Value("${hsweb.dev.workspace:./}")
+    private String workspace = "./";
+
+    @SneakyThrows
+    private void writeCode(String path, GeneratedCode code) {
+        File file = new File(path);
+        file.mkdir();
+        String type = code.getType();
+        if ("dir".equals(type)) {
+            code.getChildren()
+                    .forEach(childrenCode -> writeCode(path + "/" + code.getFile(), childrenCode));
+        } else if ("file".equals(type)) {
+            String template = code.getTemplate();
+            String fileName = path + "/" + code.getFile();
+            String replaceMod = code.getRepeat();
+            File codeFile = new File(fileName);
+            if (codeFile.exists() && replaceMod != null && !fileName.endsWith(".java")) {
+                switch (replaceMod) {
+                    case "ignore":
+                        return;
+                    case "append":
+                        String old = FileUtils.reader2String(fileName);
+                        template = old + template;
+                        break;
+                    default:
+                        break;
+                }
+            }
+            if (fileName.endsWith(".java")) {
+                ClassWriter.writeClass(fileName, template);
+            } else {
+                FileUtils.writeString2File(template, fileName, "utf-8");
+            }
+        }
+    }
+
+    @Override
+    public String write(List<GeneratedCode> codes) {
+
+        codes.forEach(code -> writeCode(workspace, code));
+
+        return workspace;
+    }
+}

+ 31 - 0
hsweb-system/hsweb-system-dev-tools/src/main/java/org/hswebframework/web/dev/tools/writer/GeneratedCode.java

@@ -0,0 +1,31 @@
+package org.hswebframework.web.dev.tools.writer;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+@Data
+@ApiModel("文件信息")
+public class GeneratedCode {
+
+    @ApiModelProperty("文件名")
+    private String file;
+
+    @ApiModelProperty("文件类型,file:文件,dir:目录")
+    private String type;
+
+    @ApiModelProperty("相同文件替换方式,ignore:跳过,append:追加,其他覆盖")
+    private String repeat;
+
+    @ApiModelProperty("文件内容")
+    private String template;
+
+    @ApiModelProperty("子文件")
+    private List<GeneratedCode> children;
+}

+ 3 - 0
hsweb-system/hsweb-system-dev-tools/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+# Auto Configure
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.hswebframework.web.dev.tools.DevToolsAutoConfiguration

+ 2 - 0
hsweb-system/pom.xml

@@ -30,6 +30,8 @@
         <module>hsweb-system-oauth2-server</module>
         <module>hsweb-system-oauth2-client</module>
         <module>hsweb-system-calendar</module>
+        <module>hsweb-system-dashboard</module>
+        <module>hsweb-system-dev-tools</module>
     </modules>
     <artifactId>hsweb-system</artifactId>