java 简单代码生成器

本贴最后更新于 2523 天前,其中的信息可能已经时移世异
  • 一个简单的代码生成器实现。

  • 代码如下:
/**
 * 测试
 * Created by GN on 2016/11/27.
 */
public class GnTest {

    @Test
    public void testGn() throws IOException {
        GnContext gnContext = new GnContext();
        gnContext.put("domain","User");
        gnContext.put("lowerDomain","user");
        String path = "E:\\WorkSpace\\Idea\\ztx\\gn-cc\\src\\main\\resources\\DaoImpl.java";
        Template template = GnUtil.getTemplate(path);
        String target = "G:\\DaoImpl.java";
        File file = new File(target);
        template.merge(gnContext,file);
    }

}
/**
 * 定义模板插入值
 * Created by GN on 2016/11/27.
 */
public class GnContext {

    /**
     * 存储模板值
     */
    private Map<String, String> context = new HashMap<>();

    public GnContext() {

    }

    public GnContext(Map<String, String> context) {
        this.context = context;
    }

    public void put(String key, String value) {
        context.put(key, value);
    }

    public String get(String key) {
        return context.get(key);
    }

}
/**
 * Created by GN on 2016/11/27.
 */
public abstract class GnUtil {

    /**
     * 获取模板信息
     * @param filePath 模板路径
     * @return
     */
    public static Template getTemplate(String filePath) throws IOException {
        if (!StringUtil.hasLength(filePath)){
            throw new IllegalArgumentException("模板路径不能为空");
        }
        File file = new File(filePath);
        if (!file.isFile() || !file.exists()){
            throw new IllegalArgumentException("无法找到指定文件:"+filePath);
        }
        return new Template(file);
    }

}
/**
 * 模板处理
 * Created by GN on 2016/11/27.
 */
public class Template {

    private static final String TAG_PREFIX = "${";
    private static final String TAG_POSTFIX = "}";

    /**
     * 模板信息
     */
    private BufferedReader reader;
    private File file;
    /**
     * 模板标签,eg:${domain}:key=domain,value=${domain}
     */
    private Map<String, String> tag = new HashMap<>();

    public Template(File file) throws IOException {
        this.file = file;
        //初始化模板输入流
        initReader();
    }

    private void initReader() {
        if (file == null) {
            throw new IllegalArgumentException("获取模板失败");
        }
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
            this.reader = new BufferedReader(inputStreamReader);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理标签到tag中
     *
     * @param text
     */
    private void initTag(String text) {
        if (!StringUtil.hasLength(text)) {
            return;
        }
        String tagFlag = getTagFlag(text);
        String tagText = getTagText(text);
        this.tag.put(tagText, tagFlag);
        //递归解析一行中的多个标签
        int prefix = text.indexOf(TAG_PREFIX);
        String subText = text.substring(prefix + 2 + tagText.length());
        if (hasTag(subText)) {
            initTag(subText);
        }
    }

    /**
     * 获取标签,${domain}
     *
     * @param text
     * @return
     */
    private String getTagFlag(String text) {
        int prefix = text.indexOf(TAG_PREFIX);
        int postfix = text.indexOf(TAG_POSTFIX);
        return text.substring(prefix, postfix + 1);
    }

    /**
     * 获取标签中的内容,${domain} --> domain
     *
     * @param text
     * @return
     */
    private String getTagText(String text) {
        String tagFlag = getTagFlag(text);
        return tagFlag.substring(2, tagFlag.length() - 1);
    }

    /**
     * 判断文本中是否含有标签
     *
     * @param text
     * @return
     */
    private boolean hasTag(String text) {
        if (!StringUtil.hasLength(text)) {
            return Boolean.FALSE;
        }
        return text.indexOf(TAG_PREFIX) > 0 && text.indexOf(TAG_POSTFIX) > 0;
    }

    /**
     * 生成模板
     *
     * @param context 模板值定义
     * @param target  目标生成文件
     */
    public void merge(GnContext context, File target) throws IOException {
        if (reader == null) {
            throw new IllegalArgumentException("读取模板失败");
        }
        if (context == null) {
            throw new IllegalArgumentException("获取GnContext失败");
        }
        if (target == null) {
            throw new IllegalArgumentException("获取输出流失败");
        }
        String temp;
        FileWriter writer = new FileWriter(target, true);
        while ((temp = reader.readLine()) != null) {
            if (hasTag(temp)) {
                //解析出所有的标签
                List<String> tagTextList = findTagTextList(temp);
                if (!tagTextList.isEmpty()) {
                    for (String text : tagTextList) {
                        String value = context.get(text);
                        if (StringUtil.hasLength(value)){
                            temp = temp.replace(TAG_PREFIX + text + TAG_POSTFIX, value);
                        }
                    }
                }
            }
            writer.write(temp + "\n");
            writer.flush();
        }
        writer.close();
    }

    /**
     * 获取文本中的标签
     *
     * @param lineText
     * @return
     */
    private List<String> findTagTextList(String lineText) {
        List<String> tagTextList = new ArrayList<>();
        if (StringUtil.hasLength(lineText) && hasTag(lineText)) {
            String tmp = lineText;
            while (hasTag(tmp)) {
                String tagText = findTagText(tmp);
                if (!tagTextList.contains(tagText)) {
                    tagTextList.add(tagText);
                }
                int begin = tmp.indexOf(tagText);
                tmp = tmp.substring(begin + tagText.length()+1);
            }
        }
        return tagTextList;
    }

    /**
     * 获取文本中的单个标签
     *
     * @param text
     * @return
     */
    private String findTagText(String text) {
        if (!StringUtil.hasLength(text)) {
            return null;
        }
        return getTagText(text);
    }

}

  • 一下为测试使用模板 :
/**
 * Created by GNon 2016/9/8.
 */
@Service
@Transactional
public class ${domain}ServiceImpl implements I${domain}Service {

    @Autowired
    private ${domain}Dao dao;

    @Override
    public void save(${domain} ${lowerDomain}) {
        dao.save(${lowerDomain});
    }

    @Override
    public void update(${domain} ${lowerDomain}) {
        dao.update(${lowerDomain});
    }

    @Override
    public void delete(Serializable id) {
        dao.delete(id);
    }

    @Override
    public ${domain} findById(Serializable id) {
        return dao.findById(id);
    }

    @Override
    public List<${domain}> findAll() {
        return dao.findAll();
    }

    @Override
    public PageData findListByPage(PageData pageData) {
        return dao.findListByPage(pageData);
    }
}
  • 以下是通过上述代码实现的简单生成器
/**
 * 代码生成器
 * Created by GN on 2016/11/28.
 */
public class GnCreator {

    /**
     * 实体
     */
    private List<String> domains = new ArrayList<>();
    /**
     * 模板基础路径
     */
    private String baseTemplatePath = "E:\\WorkSpace\\demo\\src\\main\\resources\\";
    /**
     * 生成文件保存基本路径
     */
    private String baseSavePath = "E:\\WorkSpace\\demosrc\\main\\java\\com\\gn\\demo\\";
    /**
     * 模板
     */
    private List<String> templates = new ArrayList<>();

    private final String DAOIMPL = "Dao.java";
    private final String SERVICE = "Service.java";
    private final String SERVICEIMPL = "ServiceImpl.java";

    public GnCreator() {
        //初始化生成器信息
        //初始化实体集合
        String[] domainList = {"User"}; //如果实体很多,可以通过注解扫描的方式去获取,不用一个一个的去写
        List<String> asList = Arrays.asList(domainList);
        domains.addAll(asList);
        //初始化模板
        templates.add(DAOIMPL);
        templates.add(SERVICE);
        templates.add(SERVICEIMPL);
    }

    public void create() throws IOException {
        System.out.println("代码生成器开始执行>>>>>>>>>>>>>>>>>>>>");
        for (String domain : domains) {
            System.out.println("开始生成实体【"+domain+"】代码...............");
            //模板值定义
            GnContext gnContext = new GnContext();
            gnContext.put("domain",domain);
            gnContext.put("lowerDomain",domain.toLowerCase());
            //根据模板生成代码
            for (String tp : templates) {
                String templatePath = baseTemplatePath+tp;
                Template template = GnUtil.getTemplate(templatePath);
                //根据不同的模板保存到不同的目录
                String targetFilePath = "";
                String targetFileName = "";
                if (tp.equals(DAOIMPL)){
                    targetFilePath = baseSavePath+"dao\\impl\\";
                    targetFileName = domain+DAOIMPL;
                }else if (tp.equals(SERVICE)){
                    targetFilePath = baseSavePath+"service\\";
                    targetFileName = "I"+domain+SERVICE;
                }else if (tp.equals(SERVICEIMPL)){
                    targetFilePath = baseSavePath + "service\\impl\\";
                    targetFileName = domain+SERVICEIMPL;
                }
                //判断目录是否存在,如果不存在则创建
                File file = new File(targetFilePath);
                if (!file.exists()){
                    file.mkdirs();
                }
                File targetFile = new File(targetFilePath+targetFileName);
                template.merge(gnContext,targetFile);
            }
            System.out.println("生成实体【"+domain+"】代码完成...............");
        }
        System.out.println("代码生成器执行完毕>>>>>>>>>>>>>>>>>>>>>>>>");
    }

}

  • 以上为所有代码,仅为适用自己的需求,如果能帮助到其他人更好,说下简单思路:
    代码主要实现功能是获取模板中的 ${domain} ,然后通过替换的方式把传入的 GnContext 所对应的值,最终实现代码生成。替换一处我用的是直接查询替换,如果你愿意也可以用正则表达式去处理,这样也许会简洁很多。
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    15 引用 • 122 回帖
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    86 引用 • 122 回帖 • 625 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 4 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    47 引用 • 25 回帖
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 51 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    198 引用 • 550 回帖
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 154 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    105 引用 • 127 回帖 • 382 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    149 引用 • 257 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 529 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖 • 1 关注
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 27 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    190 引用 • 1057 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 5 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    85 引用 • 139 回帖 • 1 关注
  • 安全

    安全永远都不是一个小问题。

    199 引用 • 816 回帖 • 1 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 629 关注
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 65 回帖 • 437 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    69 引用 • 372 回帖
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    180 引用 • 400 回帖
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 700 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖 • 43 关注
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 787 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖