栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

maven插件实现代码生成

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

maven插件实现代码生成

一 生成原理

 

1 先编写一套模版代码

2 在模版代码中加入特殊占位符

3 连接数据库读表和字段,对占位符做替换

二 具体实现

1 编写maven代码

2 集成到maven插件 引入pom.xml文件

3 双击运行可生成代码

三 实现代码解析

项目结构如下所示 上面是代码下面是模版插件

1 定义模版我这里用的是mybatis-plus所以有那么几个文件是需要自动生成的,这个根据大家自己所需要的自己根据自己公司的需要定制自己的模版就可以了.

dao

package packagePrefix:.dao;

import packagePrefix:.entity.${entity};
import com.baomidou.mybatisplus.extension.service.IService;

public interface ${entity}Dao: extends IService<${entity}> {
}

如上所示 entityName数据库中表的下滑线转驼峰的方式.

entity

package packagePrefix:.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;

import java.util.Date;

@Data
@Builder
@TableName("${table}")
public class ${entity} {
 ${entityContent}
}

impl

package packagePrefix:.dao.impl;

import packagePrefix:.dao.${entity}Dao;
import packagePrefix:.dao.mapper.${entity}Mapper;
import packagePrefix:.entity.${entity}:;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class ${entity}DaoImpl extends ServiceImpl<${entity}Mapper, ${entity}> implements ${entity}Dao {
}

mapper

package packagePrefix:.dao.mapper;

import packagePrefix:.entity.${entity}:;

import com.baomidou.mybatisplus.core.mapper.baseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface ${entity}Mapper extends baseMapper<${entity}> {

}

generatorConfig.xml



    
        
            com.mysql.cj.jdbc.Driver
            jdbc:mysql://192.168.106.101:3306/test_hll_premier_driver
            user_hllop
            BicfmqsrEBUjZU6tSnp25AqaA99B62vb
            cn.worn.risk.driver.access
            xxx/src/main/java
        
        
            
                    
                
                    
                

 配置文件对应的类

DalRelevant.java
@Data
public class DalRelevant {
    private String driverName;
    private String url;
    private String user;
    private String password;
    private String packagePrefix;
    private String dirPrefix;
    private List tables;
}
Table.java
@Data
public class Table {
    private String tableName;
    private String fileName;
    private Integer lineToHump;
    private Map fieldTypeMap;
    private Map columnTypeMap;
}

1 定义maven插件

abstract class AutoCreateFile extends AbstractMojo {

    @Parameter(property = "configurationFile",
            defaultValue = "${project.basedir}/src/test/java/generatorConfig.xml", required = true)
    protected File configurationFile;
    protected DalRelevant dalRelevant = new DalRelevant();
    protected JsonToObject jsonToObject = new JsonToObject();

    protected  void readXMLConfig() throws MojoExecutionException {
        System.out.printf("=====configurationFile文件:%s", configurationFile);
        if (configurationFile == null) {
            throw new MojoExecutionException("configurationFile 配置不能为空");
        }

        if (!configurationFile.exists()) {
            throw new MojoExecutionException("configurationFile 不是一个文件");
        }

        System.out.println("======当前调用类:"+this.getClass());
        try {
            SAXReader saxReader = new SAXReader();
            document document = saxReader.read(configurationFile);
            Element rootElement =  document.getRootElement();

            //dal
            if (rootElement.element("dalRelevant") != null && this.getClass() == DalRelevantMojo.class) {
                //获取DB配置
                if (rootElement.element("dalRelevant").element("commonConfig") == null ||
                        rootElement.element("dalRelevant").element("commonConfig").element("driverName") == null ||
                        rootElement.element("dalRelevant").element("commonConfig").element("url") == null ||
                        rootElement.element("dalRelevant").element("commonConfig").element("user") == null ||
                        rootElement.element("dalRelevant").element("commonConfig").element("password") == null ||
                        rootElement.element("dalRelevant").element("commonConfig").element("packagePrefix") == null ||
                        rootElement.element("dalRelevant").element("commonConfig").element("dirPrefix") == null
                ) {
                    throw new MojoExecutionException("commonConfig 必填参数缺失!");
                }

                Element dbConfig = rootElement.element("dalRelevant").element("commonConfig");
                dalRelevant.setDriverName(dbConfig.elementText("driverName"));
                dalRelevant.setUrl(dbConfig.elementText("url"));
                dalRelevant.setUser(dbConfig.elementText("user"));
                dalRelevant.setPassword(dbConfig.elementText("password"));
                dalRelevant.setPackagePrefix(dbConfig.elementText("packagePrefix"));
                dalRelevant.setDirPrefix(dbConfig.elementText("dirPrefix"));
                System.out.printf("=====数据库配置:%s", dalRelevant);

                //tables
                List listTables = rootElement.element("dalRelevant").element("tables").elements("table");
                List
tableList = new ArrayList<>(); for (Element table: listTables) { if (table.attribute("name") == null || StringUtils.isBlank(table.attribute("name").getValue())) { continue; } Table tableConfigMap = new Table(); tableConfigMap.setTableName(table.attribute("name").getValue()); if (table.attribute("fileName") != null) { tableConfigMap.setFileName(table.attribute("fileName").getValue()); } if (table.attribute("lineToHump") != null && StringUtils.isNotBlank(table.attribute("lineToHump").getValue())) { tableConfigMap.setLineToHump(Integer.parseInt(table.attribute("lineToHump").getValue())); } if (table.element("fieldTypeMap") != null && table.element("fieldTypeMap").elements("element") != null) { Map fieldTypeMap = new HashMap<>(); List fieldTypeElements = table.element("fieldTypeMap").elements("element"); for (Element fieldTypeElement: fieldTypeElements) { fieldTypeMap.put(fieldTypeElement.attribute("field").getValue(), fieldTypeElement.attribute("type").getValue()); } tableConfigMap.setFieldTypeMap(fieldTypeMap); } if (table.element("columnTypeMap") != null && table.element("columnTypeMap").elements("element") != null) { Map columnTypeMap = new HashMap<>(); List columnTypeElements = table.element("columnTypeMap").elements("element"); for (Element columnTypeElement: columnTypeElements) { columnTypeMap.put(columnTypeElement.attribute("origin").getValue(), columnTypeElement.attribute("target").getValue()); } tableConfigMap.setColumnTypeMap(columnTypeMap); } tableList.add(tableConfigMap); } if (tableList != null) { dalRelevant.setTables(tableList); } } System.out.printf("====结果%s", dalRelevant); //jsonToObject if (rootElement.element("jsonToObject") != null && this.getClass() == JsonToObjectMojo.class) { if (rootElement.element("jsonToObject").element("jsonString") == null || rootElement.element("jsonToObject").element("lineToHump") == null || rootElement.element("jsonToObject").element("fileName") == null || rootElement.element("jsonToObject").element("packagePrefix") == null || rootElement.element("jsonToObject").element("dirPrefix") == null ) { throw new MojoExecutionException("jsonToObject 必填参数缺失!"); } jsonToObject.setJsonString(rootElement.element("jsonToObject").element("jsonString").getStringValue()); jsonToObject.setLineToHump(Integer.parseInt(rootElement.element("jsonToObject").element("lineToHump").getText())); jsonToObject.setFileName(rootElement.element("jsonToObject").element("fileName").getStringValue()); jsonToObject.setPackagePrefix(rootElement.element("jsonToObject").element("packagePrefix").getStringValue()); jsonToObject.setDirPrefix(rootElement.element("jsonToObject").element("dirPrefix").getStringValue()); } } catch (Exception e) { e.printStackTrace(); throw new MojoExecutionException("解析xml失败:".concat(e.getMessage())); } } protected static void render(String templateName, Map replaceMap, String extDir) throws Exception { InputStream templateStream = Objects.requireNonNull(AutoCreateFile.class.getClassLoader().getResource("template/"+templateName)).openStream(); String implDir = replaceMap.get("completeDir"); if (extDir != null) { implDir = implDir.concat(extDir); } String outFile = implDir.concat(replaceMap.get("fileName")).concat(".java"); BufferedWriter bw= new BufferedWriter(new FileWriter(outFile)); InputStreamReader in = new InputStreamReader(templateStream); BufferedReader bufIn = new BufferedReader(in); String line = null; StringBuilder stringBuilder=new StringBuilder(); while ((line = bufIn.readLine()) != null) { stringBuilder.append(line); stringBuilder.append(System.getProperty("line.separator")); } String template = stringBuilder.toString(); TokenHandler handler = content -> (String) replaceMap.get(content); GenericTokenParser parser = new GenericTokenParser("${", "}", handler); String file = parser.parse(template); bw.write(file); bw.flush(); in.close(); bw.close(); } protected static String getCompleteDir(String dirPrefix, String packagePrefix) { String completeDir = ""; if (!StringUtils.isBlank(dirPrefix)) { completeDir = dirPrefix.concat("."); } completeDir = completeDir.concat(packagePrefix); if (!completeDir.endsWith("/")) { completeDir = completeDir.concat("/"); } return completeDir.replaceAll("\.", "/"); } }

如上代码所示抽象插件对象,

1  主要负责获取类路径下面的generatorConfig.xml文件,读取文件中配置的数据库连接,生成的包名称,生成的包路径,生成的表名什么的.

2  负责按照配置的制定路径对模版文件进行渲染,输出到指定的配置路径下面

DalRelevantMojo 核型类
@Mojo(name = "risk-commons",defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true)
public class DalRelevantMojo extends AutoCreateFile{
    private static final Map fieldTypeMapConfig = new HashMap() {
        {
            put("BIGINT", "Long");
            put("INT", "Integer");
            put("TINYINT", "Integer");
            put("VARCHAR", "String");
            put("DATETIME", "Date");
            put("CHAR", "String");
            put("TEXT", "String");
        }
    };

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        readXMLConfig();
        try {
            //1.加载驱动程序
            Class.forName(dalRelevant.getDriverName());
            //2. 获得数据库连接
            Connection conn = DriverManager.getConnection(dalRelevant.getUrl(), dalRelevant.getUser(), dalRelevant.getPassword());
            //3.操作数据库,实现增删改查
            DatabasemetaData metaData = conn.getmetaData();

            Map replaceMap = new HashMap<>();
            String completeDir = getCompleteDir(dalRelevant.getDirPrefix(), dalRelevant.getPackagePrefix());
            replaceMap.put("packagePrefix:", dalRelevant.getPackagePrefix());
            replaceMap.put("completeDir", completeDir);

            for (Table table: dalRelevant.getTables()) {
                try {
                    Map fieldTypeMap = table.getFieldTypeMap();
                    Map columnTypeMap = table.getColumnTypeMap();
                    ResultSet rs = metaData.getColumns(null, "%", table.getTableName(), "%");
                    //如果有数据,rs.next()返回true
                    StringBuilder entityContent = new StringBuilder();
                    while(rs.next()){
                        String columnType = rs.getString("TYPE_NAME");
                        String fieldType = fieldTypeMapConfig.getOrDefault(columnType, "String");
                        String field = (table.getLineToHump() == null || table.getLineToHump().equals(1)) ? HumpLineUtil.lineToHump(rs.getString("COLUMN_NAME")) : rs.getString("COLUMN_NAME");
                        if (fieldTypeMap != null && fieldTypeMap.containsKey(field)) {
                            fieldType = fieldTypeMap.get(field);
                        } else if (columnTypeMap != null && columnTypeMap.containsKey(fieldType)) {
                            fieldType = columnTypeMap.get(fieldType);
                        }
                        entityContent.append("t").append("private ").append(fieldType).append(" ").append(field).append(";").append(System.getProperty("line.separator"));
                    }

                    //强迫症 去除最后一个换行
                    entityContent.deleteCharAt(entityContent.length()-1);

                    String entityName;
                    if (table.getFileName() != null && StringUtils.isNotBlank(table.getFileName())) {
                        entityName = table.getFileName();
                    } else {
                        String entityNameHump = HumpLineUtil.lineToHump(table.getTableName());
                        entityName = entityNameHump.substring(0,1).toUpperCase().concat(entityNameHump.substring(1));
                    }

                    replaceMap.put("entity", entityName);
                    replaceMap.put("table", table.getTableName());
                    replaceMap.put("entityContent", entityContent.toString());

                    System.out.printf("======dalRelevantFiles参数%s", replaceMap);

                    //处理entity
                    replaceMap.put("fileName", entityName);
                    render("entity", replaceMap, "/entity/");

                    //处理mapper
                    replaceMap.put("fileName", entityName.concat("Mapper"));
                    render("mapper", replaceMap, "/dao/mapper/");

                    //处理dao
                    replaceMap.put("fileName", entityName.concat("Dao"));
                    render("dao", replaceMap, "/dao/");

                    //处理impl
                    replaceMap.put("fileName", entityName.concat("DaoImpl"));
                    render("impl", replaceMap, "/dao/impl/");
                } catch (Exception e) {
                    System.out.printf("====【%s】创建失败%s", table.getTableName(), e.getMessage());
                }
            }
        } catch (Exception e) {
            System.out.printf("dal相关文件自动创建失败:%s", e.getMessage());
        }
    }
}

如上所示是一个maven 插件的实现类,可以看到代码主要就是通过jdbc连接数据库获取表名,字段名进行解析然后生成对应的实体名放到一个map里面调用父类的渲染方法,替换模版中的关键子,把文件输出到指定路径下面.这里面两个工具比较重要说一下

1 驼峰下滑线转化

public class HumpLineUtil {
    private static Pattern linePattern = Pattern.compile("_(\w)");
    private static Pattern humpPattern = Pattern.compile("[A-Z]");

    
    public static String lineToHump(String str) {
        str = str.toLowerCase();
        Matcher matcher = linePattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    
    public static String humpToLine(String str) {
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }
}

2 模版替换来自Mybatis源码

inal Map mapper = new HashMap();
        mapper.put("name", "张三");
        mapper.put("pwd", "123456");
     
        //先初始化一个handler
        TokenHandler  handler = new TokenHandler() {
            @Override
            public String handleToken(String content) {
                System.out.println(content);
                   return (String) mapper.get(content);
            }
        };
        GenericTokenParser parser = new GenericTokenParser("${", "}", handler);
        System.out.println("************" + parser.parse("用户:${name},你的密码是:${pwd}"));

至此整个代码生成插件就已经处理完了. 

四 使用方式
#pom.xml 添加以下内容  
 
        
            
                cn.xxxx.risk.generator
                risk-common-maven-plugins
                0.0.2
                
                    /Users/worn/code/risk-common-boot-starter/src/test/java/generatorConfig.xml
                
            
        

    
    
#/Users/worn/code/risk-common-boot-starter/src/test/java/generatorConfig.xml# 内容


    
        
            com.mysql.cj.jdbc.Driver
            jdbc:mysql://192.168.106.101:3306/test_hll_premier_driver
            user_hllop
            BicfmqsrEBUjZU6tSnp25AqaA99B62vb
            cn.xxxx.risk.driver.access
            xxxxx/src/main/java
        
        
            

正如你所期待的双击就可以生成你不想重复写来写去的代码了

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/695408.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号