Freemaker之代码生成

今天是年后的第一天上班,年前开始研究代码生成,年前先后研究了ASM,JAVASSIST等框架,发现各有各的特点,今天我们研究模板式的代码生成,那就不得不说Freemaker了,我们先看看官网是如何介绍Freemaker的。
Apache FreeMarker™ is a template engine: a Java library to generate text output 
(HTML web pages, e-mails, configuration files, source code, etc.) 
based on templates and changing data. Templates are written in the FreeMarker Template Language (FTL), which is a simple, 
specialized language (not a full-blown programming language like PHP). Usually, a general-purpose
 programming language (like Java) 
is used to prepare the data (issue database queries, do business calculations). Then, 
Apache FreeMarker displays that prepared data using templates. 
In the template you are focusing on how to present the data, 
and outside the template you are focusing on what data to present.

常用的HTML页面,电子邮件,配置文件,资源代码都能输出,是不是很方便,也很强大。今天我们只说其中的一条信息,就是如何生成JAVA代码。我们开发系统有很多基础的工作是重复性的劳动,比如CRUD,很耗费体力,也很耗时,而且没有什么技术含量,特别是业务系统,假如我们有1000张表,那就会最少有1000个CRUD对应的操作,而且我们开发系统都是按照MVC框架来开发的,针对每个表在没有复杂也得情况,就需要建立Controller,Service,Dao,Bean以及对应的CRUD方法。我们能不能自动生成对应的代码呢。答案当然是能。我们今天就来研究一下如何来思考及设计我们的代码生成器呢?我们目前主要开发的都是企业级的业务系统,主要目标就是操作数据,存储在数据库中的数据,企业往往随着业务由线下迁往线上的过程中,不断会添加越来越多的数据,这些数据最终都是以表的形式存储于数据库。而我们的业务人员不能直接操作数据库,但是填写表单,设计类型这些操作是可以操作的,而面相对象设计恰恰是以对象来设计,用人能最直接的理解方式来设计,多以我们在设计的时候Bean就是我们最直接的和数据库一一对应的对象。因为代码生成器也是有针对性的定制化设计,所以我们今天的代码生成设计时基于Spring MVC,Spring,Hibernate框架的代码生成。其实代码生成的过程也是面相对象三大特性的集中应用,封装,多态,继承,我们必须时刻关注我们的项目那些是通用的可以设计成模板,那些是特例的需要特殊设计,不断完善。好了我们开始上实例,我们先分别上控制器和Bean的模板,控制器非常简单,Bean也不是很复杂。

1.Controller

package ${packageName};

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ${className}{

    @RequestMapping("${requestMapping}")
	@ResponseBody
	public String ${method_add}(${beanType} ${beanName}) {
		Logger logger = LogManager.getLogger(${className}.class);
		logger.info("This is the Log4J2 first log");
		System.out.println("Hello Word");
		return "Hello Word";
	}

}
package com.demo.freemaker;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

public class Bbb {

	public static void main(String[] args) throws IOException, TemplateException {
		String dir="C:\\Users\\Administrator\\workspace\\Test\\src\\com\\demo\\freemaker";
		Configuration cfg = new Configuration(Configuration.VERSION_2_3_27);
		cfg.setDirectoryForTemplateLoading(new File(dir));
		cfg.setDefaultEncoding("UTF-8");
		cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
		cfg.setLogTemplateExceptions(false);
		cfg.setWrapUncheckedExceptions(true);
		Map<String, Object> root = new HashMap<String, Object>();

                root.put("packageName", "com.demo.freemaker");
                root.put("className", "PersonController");
                root.put("author", "tudou");
                root.put("requestMapping", "addPerson");
                root.put("method_add", "addPerson");
                root.put("beanType", "Person");
                root.put("beanName", "person");
        
                Template temp = cfg.getTemplate("controller.ftl");
                OutputStream fos = new  FileOutputStream( new File(dir, "PersonController.java"));  
                Writer out = new OutputStreamWriter(fos);
                temp.process(root, out);

                fos.flush();  
                fos.close();
		
	}

}

2.Bean

package ${packageName};

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

/**
 *  @author ${author}
 */
@Entity
@Table(name = "${table_name}")
public class ${className} {
    <#list attrs as attr> 
    <#if attr.name="fid">
    @Id
    @SequenceGenerator(name = "seq${className}", sequenceName = "${seq_name}",initialValue=1,allocationSize=1)
	@GeneratedValue(generator = "seq${className}", strategy = GenerationType.SEQUENCE)
    </#if>
    @Column(name = "${attr.name}")
    private ${attr.type} ${attr.name};
    </#list>

    <#list attrs as attr>
    public void set${attr.name?cap_first}(${attr.type} ${attr.name}){
        this.${attr.name} = ${attr.name};
    }
    public ${attr.type} get${attr.name?cap_first}(){
        return this.${attr.name};
    }

    </#list>
}
package org.dbzy.freemaker;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

public class Aaa {

	public static void main(String[] args) throws IOException, TemplateException {
		
		//String dir=Aaa.class.getResource("").toString();
		String dir="C:\\Users\\Administrator\\workspace\\Test\\src\\com\\demo\\freemaker";
		Configuration cfg = new Configuration(Configuration.VERSION_2_3_27);
		cfg.setDirectoryForTemplateLoading(new File(dir));
		cfg.setDefaultEncoding("UTF-8");
		cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
		cfg.setLogTemplateExceptions(false);
		cfg.setWrapUncheckedExceptions(true);
		
		Map<String, Object> root = new HashMap<String, Object>();

                root.put("packageName", "com.demo.freemaker");
                root.put("className", "Person");
                root.put("author", "tudou");
                root.put("table_name", "t_test");
                root.put("seq_name", "q_test");
                List<Attribute> attr_list = new ArrayList<Attribute>();
                attr_list.add(new Attribute("fid", "Long"));
                attr_list.add(new Attribute("name", "String"));
                attr_list.add(new Attribute("age", "Integer"));
                attr_list.add(new Attribute("hobby", "List<String>"));
                root.put("attrs", attr_list);
        
                Template temp = cfg.getTemplate("demo.ftl");
                OutputStream fos = new  FileOutputStream( new File(dir, "Person.java"));  
                Writer out = new OutputStreamWriter(fos);
                temp.process(root, out);

                fos.flush();  
                fos.close();
	}

}
package com.demo.freemaker;

public class Attribute {
	
	private String name;
	private String type;
	public Attribute(String name,String type){
		this.name=name;
		this.type=type;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	

}
是不是很清晰明了,如果你做过开发,应该一看就会明白,这里需要注意的地方是引用,就是需要手工import需要引用的类,这个东西需要后续设计。这只是一个很简单的入门demo,后续更深入的设计需要不断深入的学习。新的一年Fightting.



猜你喜欢

转载自blog.csdn.net/u013560667/article/details/79346746