介绍
后端项目开发过程中,对于一些实体映射数据库表的操作经常会写一些重复行代码。本文介绍使用Velocity模板引擎根据实体对象生成JPA框架下对应的Repository类以及Service类,减少一些重复的板砖工作。
可根据具体项目情况添加修改模板文件生成对应代码.
pom.xml文件引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.2</version>
</dependency>
<!--模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
引入springboot、jpa以及velocity相关依赖
generateCode.properties配置文件
OutputDirRepository=D:\\WorkCoding\\AnTech\\src\\main\\java\\com\\antech\\repository
OutputDirService=D:\\WorkCoding\\AnTech\\src\\main\\java\\com\\antech\\service
entityPackege=com.antech.entity
repositoryPackege=com.antech.repository
servicePackege=com.antech.service
velocity模板文件
repository.java.vm
package ${packagePath};
import com.antech.entity.${entity};
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ${entity}Repository extends JpaRepository<${entity},${idType}> {
}
service.java.vm
package ${packagePath};
import com.antech.repository.${entity}Repository;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
@Log4j2
public class ${entity}Service {
@Autowired
private ${entity}Repository ${lowerEntity}Repository;
}
GenerateCode.java生成代码工具类
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.*;
/**
* 读取properties/generateCode.properties中的entityPackege包路径下的所有实体对象生成对应mapper/service类
*/
@Log4j2
public class GenerateCode {
public static void main(String[] args) throws IOException {
ResourceBundle rb = ResourceBundle.getBundle("properties/generateCode");
Set<Class<?>> classList = ClassUtil.scanPackage(rb.getString("entityPackege"));
Set<Class<?>> repositoryClassList = ClassUtil.scanPackage(rb.getString("repositoryPackege"));
Set<Class<?>> serviceClassList = ClassUtil.scanPackage(rb.getString("servicePackege"));
Map<String,Boolean> repositoryMap = new HashMap<>();
Map<String,Boolean> serviceMap = new HashMap<>();
for(Class clazz : repositoryClassList){
String[] arr = clazz.getName().split("\\.");
if(arr.length>0) repositoryMap.put(arr[arr.length-1],true);
}
for(Class clazz : serviceClassList){
String[] arr = clazz.getName().split("\\.");
if(arr.length>0) serviceMap.put(arr[arr.length-1],true);
}
for(Class clazz : classList){
String[] nameArr =clazz.getName().split("\\.");
String name = nameArr[nameArr.length-1];
Map<String, Field> fieldMap = ReflectUtil.getFieldMap(clazz);
Set<String> set=fieldMap.keySet();
Field field = null;
for(String key :set){
Field field1 = fieldMap.get(key);
if(field1.isAnnotationPresent(javax.persistence.Id.class)){
field=field1;
break;
}
}
String[] fieldNameArr=field.getType().getName().split("\\.");
String idType = fieldNameArr[fieldNameArr.length-1];
if(!repositoryMap.containsKey(name+"Repository")) generateRepository(rb,new VelocityEngine(),name,idType);
if(!serviceMap.containsKey(name+"Service")) generateService(rb,new VelocityEngine(),name);
}
}
/**
* 生成Repository类
*/
public static boolean generateRepository(ResourceBundle properties,VelocityEngine ve,String entity,String idType) {
try{
ve.setProperty(org.apache.velocity.runtime.RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.init();// 初始化
Template template = ve.getTemplate("templates/repository.java.vm");//导入模板
VelocityContext ctx = new VelocityContext();
ctx.put("packagePath", "com.antech.repository");
ctx.put("entity", entity);
ctx.put("idType", idType);
StringWriter sw = new StringWriter();
template.merge(ctx, sw);
String r = sw.toString();
File file = new File(properties.getString("OutputDirRepository")+"/"+entity+"Repository.java");
FileWriter fileWriter = new FileWriter(file);
fileWriter.append(r);
fileWriter.flush();
fileWriter.close();
log.info(entity+"Repository.java生成成功");
return true;
}catch (Exception e){
log.error(entity+"Repository.java生成失败",e);
return false;
}
}
/**
* 生成Service类
*/
public static boolean generateService(ResourceBundle properties,VelocityEngine ve,String entity) {
try{
ve.setProperty(org.apache.velocity.runtime.RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.init();// 初始化
Template template = ve.getTemplate("templates/service.java.vm");//导入模板
VelocityContext ctx = new VelocityContext();
String lowerName=StrUtil.lowerFirst(entity);
ctx.put("packagePath", "com.antech.service");
ctx.put("entity", entity);
ctx.put("lowerEntity", lowerName);
StringWriter sw = new StringWriter();
template.merge(ctx, sw);
String r = sw.toString();
File file = new File(properties.getString("OutputDirService")+"/"+entity+"Service.java");
FileWriter fileWriter = new FileWriter(file);
fileWriter.append(r);
fileWriter.flush();
fileWriter.close();
log.info(entity+"Service.java生成成功");
return true;
}catch (Exception e){
log.error(entity+"Service.java生成失败",e);
return false;
}
}
}
使用方式
修改generateCode.properties配置文件中entityPackage值(项目实体类所再的包路径),扫描此包下的实体类生成对应的repository类以及service类,修改repositoryPackage值为需要生成的repository类的目的路径,修改servicePackage值为需要生成的service类的目的路径,修改OutputDirRepository值为需要生成的repository类的文件在计算机中的绝对路径,修改OutputDirService值为需要生成的service类的文件在计算机中的绝对路径。
运行GenerateCode工具类方法,生成实体对应repository文件以及service文件。生成策略:存在即不生成(可根据对应需求修改GenerateCode.java代码,最后的两个if做对那个修改);项目使用了hutool工具类,因此pom文件中hutool依赖必须引入。
评论区