当前位置:   article > 正文

java自动生成代码_guava jpeot 生成代码

guava jpeot 生成代码

java自动生成代码

​ 为了简化日常编写代码,根据公司的自身情况,编写了一个自动生成代码的简易工具。

主要需要熟悉freemarker模板引擎,JDBC等相关知识;

<dependency>
    <groupId>freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.8</version>
</dependency>
<!-- 这个是生成驼峰命名的工具 -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>21.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 创建实体类ColumnClass

ColumnClass 用来封装 数据库表元数据的信息,如字段名称,字段类型,字段注释等等。

public class ColumnClass {

    /** 数据库字段名称 **/
    private String columnName;
    /** 数据库字段类型 **/
    private String columnType;
    /** 数据库字段首字母小写且去掉下划线字符串 **/
    private String changeColumnName;
    /** 数据库字段注释 **/
    private String columnComment;

    /**
     * 列的长度
     */
    private int columnSize;

    /**
     * 是否允许为空
     */
    private String nullable;

    /**
     * 主键名
     */
    private String pkName;
    
    ...get/set方法
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  1. 主要代码
package cn.sh.cjvision.CodeGenerator.jdbc;

import cn.sh.cjvision.CodeGenerator.ColumnClass;
import cn.sh.cjvision.CodeGenerator.FreeMarkerTemplateUtils;
import com.google.common.base.CaseFormat;
import org.apache.commons.jexl2.UnifiedJEXL;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
//import com.evada.inno.pm.code.generate.model.ColumnClass;

import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.sql.*;
import java.time.LocalDate;
import java.util.*;

import static cn.sh.cjvision.CodeGenerator.FreeMarkerTemplateUtils.createDir;

public class CodeGenerateUtils
{
    /**
     * 链接地址
     */
    @Value("${spring.datasource.url}")
    private String URL;

    /**
     * 用户名
     */
    @Value("@{spring.datasource.username}")
    private String USER;

    /**
     * 密码
     */
    @Value("@{spring.datasource.password}")
    private String PASSWORD;

    /**
     * 连接驱动
     */
    @Value("@{spring.datasource.driver-class-name}")
    private String DRIVER;

    /**
     * 作者
     */
    private final String AUTHOR = "wowoToffon";

    /**
     * 时间
     */
    private final String CURRENT_DATE = LocalDate.now().toString();

    /**
     * 表名
     */
    private final String tableName = "BOOK";

    /**
     * 包名
     */
    private final String packageName = "cn.sh.cjvision";

    /**
     * 表中文注释
     */
    private final String tableAnnotation = "书";

    /**
     * 生成位置
     */
    private final String diskPath = "E:\\MyProject\\Quartz\\Quartz\\app-quartz\\src\\main\\java\\cn\\sh\\cjvision";

    /**
     * 将类似为 A_TABLE  转换为驼峰命名 aTable
     */
    private final String changeTableName = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);

    /**
     * 获取jdbc链接
     * @return
     * @throws Exception
     */
    public  Connection getConnection() throws Exception
    {
        Class.forName(DRIVER);

        Properties props =new Properties();
        props.put("user", USER);
        props.put("password", PASSWORD);
        // 允许获取注解(这个是重点,在oracle中不加这个,获得注释就是 null)
        props.put("remarksReporting","true");
        Connection connection = DriverManager.getConnection(URL, props);
        return connection;
    }

    public static void main(String[] args) throws Exception
    {
        CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
        codeGenerateUtils.generate();
    }

    public void generate() throws Exception
    {
        Connection connection = getConnection();

        //生成Model文件
        generateModelFile(connection);

        // 生成Controller文件
        generateControllerFile();

        // 生成service文件
        generateServiceFile();
    }

    public List<ColumnClass> setColumnClass(Connection connection) throws SQLException
    {
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        // 获取表中列值信息
        ResultSet resultSet = databaseMetaData.getColumns(null, "%", tableName, "%");
        // 获取表主键信息	
        ResultSet primaryKeys = databaseMetaData.getPrimaryKeys(null, null, "BOOK");
        List<ColumnClass> columnClassList = new LinkedList<>();

        ColumnClass columnClass = null;
        while (resultSet.next())
        {
            columnClass = new ColumnClass();
            //获取字段名称
            columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
            //获取字段类型
            columnClass.setColumnType(resultSet.getString("TYPE_NAME").split("\\(")[0]);
            //转换字段名称,如 sys_name 变成 SysName
            columnClass.setChangeColumnName(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,(resultSet.getString("COLUMN_NAME"))));
            //字段在数据库的注释
            columnClass.setColumnComment(resultSet.getString("REMARKS"));
            // 字段长度
            columnClass.setColumnSize(resultSet.getInt("COLUMN_SIZE"));
            // 是否为必填
            columnClass.setNullable(resultSet.getString("NULLABLE"));

            columnClassList.add(columnClass);
        }

        while (primaryKeys.next())
        {
            int i = 0;
            columnClass = columnClassList.get(i);
            columnClass.setPkName(primaryKeys.getString("PK_NAME"));
            i++;
        }
        return columnClassList;
    }

    private void generateModelFile(Connection connection) throws Exception
    {
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        ResultSet resultSet = databaseMetaData.getColumns(null, "%", tableName, "%");

        String newPath = createDir(diskPath, "bean");
        final String suffix = ".java";
        final String path = newPath + changeTableName + suffix;
        final String templateName = "Model.ftl";
        File mapperFile = new File(path);

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("model_column", setColumnClass(connection));
        generateFileByTemplate(templateName, mapperFile, dataMap);

    }

    private void generateServiceFile() throws Exception
    {
        String newPath = createDir(diskPath, "service");
        final String suffix = "Service.java";
        final String path = newPath + changeTableName + suffix;
        final String templateName = "Service.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateControllerFile() throws Exception
    {
        String newPath = createDir(diskPath, "controller");
        final String suffix = "Controller.java";
        final String path = newPath + changeTableName + suffix;
        final String templateName = "Controller.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateFileByTemplate(final String templateName, File file, Map<String, Object> dataMap) throws Exception
    {
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("table_name_small", tableName);
        dataMap.put("table_name", changeTableName);
        dataMap.put("author", AUTHOR);
        dataMap.put("date", CURRENT_DATE);
        dataMap.put("package_name", packageName);
        dataMap.put("table_annotation", tableAnnotation);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
        template.process(dataMap, out);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  1. FreeMarkerTemplateUtils工具类

    FreeMarkerTemplateUtils工具类用来配置模板所在的路径

    package cn.sh.cjvision.CodeGenerator;
    
    // import com.evada.inno.core.exception.BusinessException;
    import freemarker.cache.ClassTemplateLoader;
    import freemarker.cache.NullCacheStorage;
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import freemarker.template.TemplateExceptionHandler;
    
    import java.io.File;
    import java.io.IOException;
    
    public class FreeMarkerTemplateUtils {
    
        private FreeMarkerTemplateUtils(){}
        private static final Configuration CONFIGURATION = new Configuration();
    
        static{
            //这里比较重要,用来指定加载模板所在的路径
            CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtils.class, "/templates"));
            CONFIGURATION.setDefaultEncoding("UTF-8");
            CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);
        }
    
        public static Template getTemplate(String templateName) throws IOException {
            try {
                return CONFIGURATION.getTemplate(templateName);
            } catch (IOException e) {
                throw e;
            }
        }
    
        public static void clearCache() {
            CONFIGURATION.clearTemplateCache();
        }
    
        /**
         * 创建 文件夹
         * @param FileAddress
         * @param fileName
         * @return
         */
        public static String createDir (String FileAddress, String fileName){
            FileAddress = FileAddress + "/" +fileName + "/";
    
            File file  = new File(FileAddress);
            if(file.exists()){
    
                System.out.println("存在该目录");
                return FileAddress;
            }
    
            /*if (!FileAddress.endsWith(File.separator)) {
                FileAddress = FileAddress + File.separator;
            }*/
    
            if(file.mkdir()){
                System.out.println("创建目录" + FileAddress + "创建成功");
            }else {
                System.out.println("创建失败");
            }
            return FileAddress;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
  2. freemarker 模板文件

    Freemarker的模板文件,后缀都是以ftl结尾的。

    创建Model.ftl

    package ${package_name}.bean;
    
    import cn.sh.cjvision.framework.bean.bean.BaseBean;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import org.hibernate.annotations.GenericGenerator;
    import org.hibernate.validator.constraints.Length;
    import org.hibernate.validator.constraints.NotBlank;
    import cn.sh.cjvision.framework.utils.constant.AppConstants;
    
    import javax.persistence.*;
    import java.util.Date;
    
    /**
    * 描述:${table_annotation}模型
    * @author ${author}
    * @date ${date}
    */
    
    @Entity
    @Table(name = "${table_name_small}")
    @ApiModel
    public class ${table_name} extends BaseBean {
    
    <#if model_column?exists>
    <#list model_column as model>
        /**
        *${model.columnComment!}
        */
        <#if (model.columnType = 'VARCHAR2' || model.columnType = 'VARCHAR' || model.columnType = 'NUMBER' || model.columnType = 'TEXT')>
    
        <#if model.pkName?exists>
        @Id
        @GeneratedValue(generator = "${model.columnName}")
        @GenericGenerator(name = "${model.columnName}", strategy = AppConstants.SEQ_GENERATOR_STR)
        <#else >
        @Column(name = "${model.columnName}")
        <#if (model.nullable = '0')>
        @NotBlank(message = "${model.columnComment!}不能为空")
        @ApiModelProperty(value = "${model.columnComment!}不能为空", required = true)
        </#if>
        </#if>
        @Length(max = ${model.columnSize},message = "最长为${model.columnSize}")
        private String ${model.changeColumnName?uncap_first};
    
        </#if>
        <#if model.columnType = 'TIMESTAMP' >
        <#if (model.nullable = '0')>
        @NotNull(message = "${model.columnComment!}不能为空")
        @ApiModelProperty(value = "${model.columnComment!}不能为空", required = true)
        </#if>
        @Column(name = "${model.columnName}",columnDefinition = "TIMESTAMP")
        private Date ${model.changeColumnName?uncap_first};
    
        </#if>
    </#list>
    </#if>
    
    <#if model_column?exists>
    <#list model_column as model>
        <#if (model.columnType = 'VARCHAR2' || model.columnType = 'TEXT')>
        public String get${model.changeColumnName}() {
            return this.${model.changeColumnName?uncap_first};
        }
    
        public void set${model.changeColumnName}(String ${model.changeColumnName?uncap_first}) {
            this.${model.changeColumnName?uncap_first} = ${model.changeColumnName?uncap_first};
        }
    
        </#if>
        <#if model.columnType = 'TIMESTAMP' >
        public Date get${model.changeColumnName}() {
            return this.${model.changeColumnName?uncap_first};
        }
    
        public void set${model.changeColumnName}(Date ${model.changeColumnName?uncap_first}) {
            this.${model.changeColumnName?uncap_first} = ${model.changeColumnName?uncap_first};
        }
    
        </#if>
    </#list>
    </#if>
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    Service.flt文件

    package ${package_name}.service;
    
    import cn.sh.cjvision.framework.repository.CustomRepository;
    import ${package_name}.bean.${table_name}Bean;
    
    public interface ${table_name}Service extends CustomRepository<${table_name}Bean, String>
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Controller.flt文件

    package ${package_name}.controller;
    
    import ${package_name}.bean.${table_name}Bean;
    import cn.sh.cjvision.framework.annotation.log.LogWrite;
    import cn.sh.cjvision.framework.controller.BaseController;
    import cn.sh.cjvision.framework.utils.out.OutPutJson;
    import ${package_name}.service.${table_name}Service;
    import com.alibaba.fastjson.JSONObject;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import io.swagger.annotations.Api;
    import org.hibernate.validator.constraints.NotBlank;
    import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    
    @RestController
    @RequestMapping("/app/${table_name?uncap_first}")
    @Validated
    @Api(tags = "${table_annotation}")
    public class ${table_name}Controller
    {
        private final static Logger logger = LoggerFactory.getLogger(${table_name}Controller.class);
    
        @Autowired
        private ${table_name}Service ${table_name?uncap_first}Service;
    
        @Autowired
        private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    
        /**
        * 描述:根据Id 查询
        * @param id  ${table_annotation}id
        */
        @PostMapping(value = "get${table_name}ById")
        @LogWrite(moduleName = "获取${table_annotation}", op = LogWrite.OP.QUERY)
        public JSONObject findById(@NotBlank(message = "ID不能为空") String id)throws Exception {
            JSONObject obj = new JSONObject();
    
            ${table_name}Bean ${table_name?uncap_first}Bean = ${table_name?uncap_first}Service.findOne(id);
    
            obj.put("${table_name?uncap_first}Bean", ${table_name?uncap_first}Bean);
            return OutPutJson.success("获取成功", obj);
        }
    
        /**
        * 描述:创建${table_annotation}
        * @param
        */
        @PostMapping(value = "add${table_name}")
        @LogWrite(moduleName = "新增${table_annotation}", op = LogWrite.OP.ADD)
        public JSONObject add${table_name}(@Validated ${table_name}Bean ${table_name?uncap_first}Bean) throws Exception {
    
            JSONObject obj = new JSONObject();
            try{
                ${table_name}Bean ${table_name?uncap_first}Save = ${table_name?uncap_first}Service.save(${table_name?uncap_first}Bean);
    
                obj.put("${table_name?uncap_first}Bean", ${table_name?uncap_first}Save);
                return OutPutJson.success("新增成功", obj);
            } catch (Exception e){
                logger.error("URL:/app/${table_name?uncap_first}/add${table_name} 异常 " + e.getMessage(), e);
                return OutPutJson.failure("新增失败:" + e.getMessage());
            }
        }
    
        /**
        * 描述:删除${table_annotation}
        * @param id ${table_annotation}id
        */
        @PostMapping(value = "del${table_name}ByIds")
        @LogWrite(moduleName = "删除${table_annotation}", op = LogWrite.OP.DELETE)
        public JSONObject del${table_name}ByIds(@RequestBody List<String> ids) throws Exception {
            Map<String, Object> map = new HashMap<>(1);
    
            if(ids.size() > 0){
                map.put("ids", ids);
                namedParameterJdbcTemplate.update("DELETE FROM ${date} WHERE RWRY_ID IN (:ids)", map);
            }
    
            return OutPutJson.success("移除成功");
        }
    
        /**
        * 描述:编辑${table_annotation}
        * @param
        */
        @PostMapping(value = "update${table_name}")
        @LogWrite(moduleName = "编辑${table_annotation}", op = LogWrite.OP.UPDATE)
        public JSONObject update${table_name}(@Validated ${table_name}Bean ${table_name?uncap_first}Bean) throws Exception {
    
            JSONObject obj = new JSONObject();
            try{
                ${table_name}Bean ${table_name?uncap_first}Update = ${table_name?uncap_first}Service.saveAndFlush(${table_name?uncap_first}Bean);
    
                obj.put("${table_name?uncap_first}Bean", ${table_name?uncap_first}Update);
                return OutPutJson.success("编辑成功", obj);
            } catch (Exception e){
                logger.error("URL:/app/${table_name?uncap_first}/update${table_name} 异常 " + e.getMessage(), e);
                return OutPutJson.failure("编辑失败:" + e.getMessage());
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112

注意:

  1. 在连接数据库的时候一定要 remarksReporting 设置为true,不然获取不到注解
  2. 在JDBC元数据的操作是很消耗性能的,有点慢
  3. JDBC获取信息有7中方法,每个方法获取的信息不一样,就是这个东西,databaseMetaData.getColumns是获取不到主键信息的,获主键的时候一直说的是“列名不存在” 有点蛋疼,需要单独的获取主键信息。详情
  4. freemarker 开上面写的应该能看懂。

参考:

JDBC元数据操作(一)-- DatabaseMetaData接口详解

Java之利用Freemarker模板引擎实现代码生成器,提高效率(我主要看的这篇,在他的基础上加了生成文件夹, 没有用他的驼峰名)

java 驼峰字符和下划线字符相互转换工具类

Freemarker操作字符串

Freemarker官网

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/178681
推荐阅读
相关标签
  

闽ICP备14008679号