前言:
新业务的开发总是少不了相应的增删查改,而这些功能与其他业务的增删查改又是大径相同,所以为了解决这种纯粹的体力劳动,提高开发效率,开发一个增删查改的代码自动生成是非常有必要的。
技术:freemarker模板
生成的目标文件:entity,dao,controller,service,.sql等五个文件
依赖包:freemarker-2.3.16.jar
commons.io-2.4.jar
主体代码:
import freemarker.template.Template; import org.apache.commons.lang3.StringUtils; import com.arvin.entity.CodeAuto; import com.arvin.entity.Column; import org.apache.commons.io.FileUtils; import java.io.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class CodeAutoUtil { public Map<String, Object> getCodeAutoData(CodeAuto codeAuto) { Map<String, Object> dataMap = new HashMap<String , Object>(); dataMap.put("name", codeAuto.name); dataMap.put("entityName", StringUtils.capitalize(codeAuto.name)); dataMap.put("controllerName", StringUtils.capitalize(codeAuto.name) + "Controller"); dataMap.put("daoName", StringUtils.capitalize(codeAuto.name) + "Dao"); dataMap.put("serviceName", StringUtils.capitalize(codeAuto.name) + "Service"); // endpoint 功能 dataMap.put("funs",codeAuto.funs); // domain 列 List<String> stringList = new ArrayList<String>(); List<String> strs = new ArrayList<String>(); for(Column column : codeAuto.columns){ String columnStr = "public"+" "+ column.type + " " + column.name +";"; //格式: public String name; String str = "`"+column.name+"`"+column.type+"("+parseColumnLength(column.type)+")"+" "+"NULL,"; //格式: `name` varchar(255) NULL, stringList.add(columnStr); strs.add(str); } dataMap.put("params",stringList); //sql 建表文件 dataMap.put("colomns",strs); return dataMap; } public boolean create(CodeAuto codeAuto) throws Exception{ Map<String, Object> dataMap = getCodeAutoData(codeAuto); Template template = FreeMarkerTemplateUtils.getTemplate("Endpoint.ftl"); File file = FileUtils.getFile(codeAuto.path, codeAuto.name); if (!file.exists()){ file.mkdir(); } Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(FileUtils.getFile(codeAuto.path, codeAuto.name, dataMap.get("controllerName") + ".java")), "utf-8"),10240); template.process(dataMap,out); template = FreeMarkerTemplateUtil.getTemplate("Dao.ftl"); out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(FileUtils.getFile(codeAuto.path, codeAuto.name, dataMap.get("daoName") + ".java")), "utf-8"),10240); template.process(dataMap,out); template = FreeMarkerTemplateUtil.getTemplate("Domain.ftl"); out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(FileUtils.getFile(codeAuto.path, codeAuto.name, dataMap.get("entityName") + ".java")), "utf-8"),10240); template.process(dataMap,out); template = FreeMarkerTemplateUtil.getTemplate("Service.ftl"); out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(FileUtils.getFile(codeAuto.path, codeAuto.name, dataMap.get("serviceName") + ".java")), "utf-8"),10240); template.process(dataMap,out); template = FreeMarkerTemplateUtil.getTemplate("Sql.ftl"); out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(FileUtils.getFile(codeAuto.path, codeAuto.name,dataMap.get("entityName") + ".sql")), "utf-8"),10240); template.process(dataMap,out); return true; } //数据库字段类型转换为java类型 private int parseColumnLength(String type) { int ret; switch (type) { case "varchar":ret = 255;break; case "char": ret = 255;break; case "text": ret = 1024;break; case "bigint": ret = 11;break; case "tinyint":ret = 4;break; default:ret = 255; } return ret; } }
测试代码:
import java.util.ArrayList; import java.util.List; import com.arvin.entity.CodeAuto; import com.arvin.entity.Column; public class Test { public static void main(String[] args) throws Exception { //Entity的字段 Column columnOne = new Column("username","varchar"); Column columnTwo = new Column("password","varchar"); Column columnThree = new Column("sex","tinyint"); List<Column> columns = new ArrayList<>(); columns.add(columnOne); columns.add(columnTwo); columns.add(columnThree); //Controller的方法 String[] fun = {"add","delete","query","update"}; CodeAuto codeAuto = new CodeAuto(); codeAuto.name = "test"; codeAuto.diskPath = "E:\\codeAuto\\"; codeAuto.funs = fun; codeAuto.columns = columns; CodeAutoUtil cdeAutoUtil = new CodeAutoUtil(); cdeAutoUtil.create(codeAuto); } }
import org.apache.commons.lang3.builder.ToStringBuilder; import java.util.List; public class CodeAuto { public String name; public String path; public List<Column> columns; //entity字段 public String[] funs; // 功能点(增删查改) @Override public String toString() { return ToStringBuilder.reflectionToString(this); } }
public class Column { public String name;//字段名 public String type;//字段类型 public Column(String name,String type) { this.name = name; this.type = type; } }
freemarker配置:
import freemarker.cache.ClassTemplateLoader; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateExceptionHandler; import java.io.IOException; public class FreeMarkerTemplateUtil { private static final Configuration Configuration = new Configuration(); static{ Configuration.setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtil.class, "/templates"));//模板所在路径 Configuration.setDefaultEncoding("UTF-8"); Configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); } public static Template getTemplate(String templateName) throws IOException { try { return Configuration.getTemplate(templateName); } catch (IOException e) { throw e; } } }
Dao.ftl模板:
package ${name}; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.JpaRepository; public interface ${entityName}Dao extends JpaRepository<${entityName}, Long> { Page<${entityName}> findAll(Specification<${entityName}> specification, Pageable pageable); }Entity.ftl模板:
package ${name}; import org.apache.commons.lang3.builder.ToStringBuilder; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class ${entityName} { // JPA 主键标识, 策略为由数据库生成主键 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long id; public Date updateTime; public Date createTime; <#list params as x> ${x} </#list> public ${entityName}() {} @Override public String toString() { return ToStringBuilder.reflectionToString(this); } }Controller.ftl模板:
package ${name}; import org.carrot.config.support.SuccessResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springside.modules.constants.MediaTypes; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; @RestController @RequestMapping(value="/api/${name}") public class ${entityName}Controller { @Autowired private ${entityName}Service ${name}Service; <#list funs as x> <#if x?contains("hasQuery")> @RequestMapping(value = "/list", method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8) public SuccessResult list(@RequestHeader(value = "token") String token, @RequestParam(required=false) String searchValue, @PageableDefault(sort="updateTime",direction=Sort.Direction.DESC) Pageable pageable) throws Exception { return new SuccessResult(${name}Service.list(searchValue,pageable)); } </#if> <#if x?contains("hasAdd")> @RequestMapping(value = "/add", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8) public SuccessResult add(@RequestHeader(value = "token") String token, @RequestBody ${entityName} ${name}) throws Exception { return new SuccessResult(${name}Service.add(${name})); } </#if> <#if x?contains("hasDelete")> @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8) public SuccessResult delete(@RequestHeader(value = "token") String token, @PathVariable(value = "id") Long id) throws Exception { return new SuccessResult(${name}Service.delete(id)); } </#if> <#if x?contains("hasUpdate")> @RequestMapping(value = "/update/{id}", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8) public SuccessResult update(@RequestHeader(value = "token") String token, @PathVariable(value = "id") Long id, @RequestBody ${entityName} ${name}) throws Exception { return new SuccessResult(${name}Service.update(id, ${name})); } </#if> <#if x?contains("hasQuery")> @RequestMapping(value = "/detail/{id}", method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8) public SuccessResult detail(@RequestHeader(value = "token") String token, @PathVariable(value = "id") Long id) throws Exception { return new SuccessResult(${name}Service.detail(id)); } </#if> </#list> }Service.ftl模板:
package ${name}; import java.util.List; import java.util.Map; import com.google.common.collect.Lists; import org.carrot.util.PojoUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.google.common.collect.Maps; import javax.persistence.criteria.*; @Service public class ${entityName}Service { @Autowired private ${entityName}Dao ${name}Dao; //根据条件查询全部 @Transactional() public Map<String, Object> list( String searchValue,Pageable pageable) { Map<String, Object> maps = new HashMap<String , Object>(); Page<${entityName}> page${entityName} = ${name}Dao.findAll(new Specification<${entityName}>() { public Predicate toPredicate(Root<${entityName}> root, CriteriaQuery<?> query, CriteriaBuilder cb) { // 根据条件获取任务列表 List<Predicate> predicates = Lists.newArrayList(); Predicate[] predicateArr = new Predicate[predicates.size()]; query.where(predicates.toArray(predicateArr)); return null; } }, pageable); maps.put("list", page${entityName}.getContent()); maps.put("total", page${entityName}.getTotalElements()); return maps; } @Transactional public boolean add( ${entityName} ${name}) { ${name}Dao.save(${name}); return true; } @Transactional public Object delete( Long id) { ${entityName} temp${entityName} = ${name}Dao.findOne(id); if(temp${entityName} != null){ ${name}Dao.delete(id); return true; } return false; } @Transactional public Object update( Long id, ${entityName} ${name}) throws Exception { ${entityName} temp${entityName} = ${name}Dao.findOne(id); if (temp${entityName} != null) { PojoUtil.copyProperties(temp${entityName}, ${name}); ${name}Dao.save(temp${entityName}); return true; } return false; } @Transactional(readOnly = true) public Object detail( Long id) { ${entityName} ${name} = ${name}Dao.findOne(id); if(${name} != null) { return ${name}; } return false; } }Sql.ftl模板:
CREATE TABLE if not EXISTS `${name}` ( `id` bigint(11) NOT NULL AUTO_INCREMENT, <#list colomns as x> ${x} </#list> `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) , );