代码生成器
根据Mybatis generator(MBG)结合freemarker写了一个代码生成器,可以直接生成Controller,Service,Dao,bean,以及对应的mapper.xml文件。
准备材料: 几个模板,mybatis-generator-core-1.3.2.jar。
注意事项:各个公司的文件结构可能不尽相同,所以请根据实际情况自行采用。
public class MapperGeneratorTest {
/**
*
*/
private static final String BASEPATH = "C:\tmp\generator\";
// 获取项目路径
private static final String ROOTPATH = System.getProperty("user.dir") + "/src/main";
private final String WEBPATH = "这里写上你生成文件的上一级目录";
/**
* 一键生成
*/
@Test
public void generateTest() {
// 要生成的bean
String[] entities = new String[]{"value"};
// 对应的表
String[] tables = new String[]{"value"};
// Mapper.java文件路径
String path = ROOTPATH + WEBPATH + "*/dao/mapper/?Mapper.java";
// baseMapper全限定名
String baseMapperQfName = "这里写上baseMapper的全限定名";
generate(entities, tables, path, baseMapperQfName);
}
/**
* 生成Controller,Service, Mapper,xml,bean及其实现
*
* @param entities bean数组
* @param tables 生成的表数组
* @param mapperPath *的位置代表entity, ?代表对于的大写格式
* @param baseMapperQfName baseMapper全限定名
*/
private void generate(String[] entities, String[] tables, String mapperPath, String baseMapperQfName) {
for (int i = 0; i < entities.length; i++) {
System.err.println("==================开始执行第" + (i + 1) + "次=====================");
String entity = entities[i];
// 生成好对应的xml文件
generateForOne(entity, tables[i]);
// 如果basePath不存在的话则创建
File file = new File(BASEPATH);
if (!file.exists()) {
file.mkdirs();
}
// 首先写好要运行的bat文件
writeBat(entity, BASEPATH + entity + ".bat");
String path = mapperPath.replace("*", entity).replace("?", StringUtil.capitalize(entity));
processMapper(path, entity, baseMapperQfName, !new File(path).exists());
generateCtrSerDao(entity);
System.err.println("==================结束执行第" + (i + 1) + "次=====================");
}
}
/**
* 执行bat命令
*
* @param batPath bat文件路径
*/
private Process runCmd(String batPath) {
Process process = null;
try {
process = Runtime.getRuntime().exec("cmd /c C: && start " + batPath);
// InputStream input = process.getInputStream();
// BufferedReader reader = new BufferedReader(new InputStreamReader(input));
// String szline;
// while ((szline = reader.readLine())!= null) {
// System.out.println(szline);
// }
// reader.close();
process.waitFor();
if (process.exitValue() == 0) {
System.err.println("执行bat命令成功");
}
// 执行成功之后再destroy
process.destroy();
// 执行完毕,关闭本窗口
Runtime.getRuntime().exec("cmd.exe /C start wmic process where name='cmd.exe' call terminate");
} catch (Exception e) {
e.printStackTrace();
}
return process;
}
/**
* 将命令写入bat文件
*
* @param entityName 实体名字
* @param path 生成bat的路径
*/
private void writeBat(String entityName, String path) {
String cmd = "java -jar C:\tmp\mybatis-generator-core-1.3.2.jar -configfile C:\tmp\xml\" + entityName + ".xml -overwrite";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File(path));
fileOutputStream.write(cmd.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
StreamUtil.close(fileOutputStream);
}
}
// 根据模板生成对应的xml
private void generateForOne(String entityName, String tableName) {
String outputPath = "C:\tmp\xml";
if (!new File(outputPath).exists()) {
boolean createDirectoryFlag = new File(outputPath).mkdirs();
if (!createDirectoryFlag) {
System.err.println("========Danger: mkdirs() error!=========");
}
}
// 获取对应的版本配置
Configuration configuration = new Configuration(Configuration.VERSION_2_3_21);
String ftlPath = ROOTPATH + "\resources\freemarker";
File ftlFilePath = new File(ftlPath);
try {
// 设置模板文件上级路径
configuration.setDirectoryForTemplateLoading(ftlFilePath);
configuration.setDefaultEncoding("UTF-8");
// 设置异常处理器
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// 构建数据模型
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("entity", entityName);
dataMap.put("domain", StringUtil.capitalize(entityName));
// 解决不规范命名问题
dataMap.put("table", tableName);
// 获取模板
Template generatorTemplate = configuration.getTemplate("mapper-generator.ftl");
// 设置输出路径
FileOutputStream fileOutputStream = new FileOutputStream(outputPath + File.separator + entityName + ".xml");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
generatorTemplate.process(dataMap, outputStreamWriter);
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
}
/**
* 处理mapper.java文件
*
* @param path mapper.java所在路径
* @param entityName
* @param baseMapperQfName
* @param flag 是否是第一次生成
*/
private void processMapper(String path, String entityName, String baseMapperQfName, boolean flag) {
String backFileName = path + "_backup";
if (!flag) {
// 首先备份原来的mapper文件
FileUtil.copyFile(path, backFileName);
}
Process process = runCmd(BASEPATH + entityName + ".bat");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String mapperContent = getMapperContent(path, entityName, baseMapperQfName, flag);
// System.err.println("生成的Mapper.java文件内容为:
" + mapperContent);
// 将修改后的mapper写入文件
FileUtil.writeToFile(path, mapperContent);
File backFile = new File(backFileName);
if (backFile.exists()) {
boolean delete = backFile.delete();
if (!delete) {
System.err.println("删除" + backFileName + "失败!");
}
}
}
/**
* 第一次生成, 返回自动产生Mapper文件中的内容,
* 非首次生成, 保存原来Mapper.java文件中的方法, 如果未继承BaseMapper, 则处理为继承BaseMapper
*
* @param path mapper.java 路径
* @param entityName beanName
* @param baseMapperQfName baseMapper全限定名
* @param flag 是否是第一次生成
* @return 返回生成的Mapper中的String内容
*/
private String getMapperContent(String path, String entityName, String baseMapperQfName, boolean flag) {
// Mapper.java文件路径
String domainName = StringUtil.capitalize(entityName);
String url = path + (flag ? "" : "_backup");
String separator = System.getProperty("line.separator");
// 存储改动过后的string
StringBuilder buffer = new StringBuilder();
FileInputStream fis = null;
InputStreamReader reader = null;
BufferedReader bufferedReader = null;
try {
fis = new FileInputStream(new File(url));
reader = new InputStreamReader(fis);
bufferedReader = new BufferedReader(reader);
String str;
while ((str = bufferedReader.readLine()) != null) {
// 已经import了BaseMapper跳过
if (str.contains("mapper.BaseMapper")) continue;
// 如果是第一次生成的话
if (str.contains("interface")) {
buffer.append("import ").append(baseMapperQfName).append(";");
// 插入系统的换行符
buffer.append(separator);
// 格式处理, import 和interface之间添加空行
buffer.append(separator);
// 处理存在Mapper文件, 但是没有抽取继承的情况
if (!str.contains("extends BaseMapper")) {
String changedText = str.replace(domainName + "Mapper", domainName + "Mapper extends BaseMapper<" + domainName + ">");
buffer.append(changedText);
}
if (flag) {
buffer.append(separator);
buffer.append("}");
break;
}
}
buffer.append(str);
buffer.append(separator);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
StreamUtil.close(bufferedReader, reader, fis);
}
return buffer.toString();
}
/**
* 生成controller,service,dao
*
* @param entityName beanName
*/
private void generateCtrSerDao(String entityName) {
// 所有模板
String[] templateNames = new String[]{"BeanController.ftl", "IBeanService.ftl", "BeanServiceImpl.ftl", "IBeanDao.ftl", "BeanDaoImpl.ftl"};
String[] paths = new String[]{"controller/", "service", "service/impl", "dao", "dao/impl"};
String[] names = new String[]{"Controller", "Service", "ServiceImpl", "Dao", "DaoImpl"};
String domainName = StringUtil.capitalize(entityName);
// 获取对应的版本配置
Configuration configuration = new Configuration(Configuration.VERSION_2_3_21);
String ftlPath = ROOTPATH + "\resources\freemarker";
File ftlFilePath = new File(ftlPath);
FileOutputStream fileOutputStream = null;
OutputStreamWriter outputStreamWriter = null;
try {
// 设置模板文件上级路径
configuration.setDirectoryForTemplateLoading(ftlFilePath);
configuration.setDefaultEncoding("UTF-8");
// 设置异常处理器
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// 构建数据模型
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("entity", entityName);
dataMap.put("domain", domainName);
for (int i = 0; i < templateNames.length; i++) {
String currFtl = templateNames[i];
// 获取模板
Template generatorTemplate = configuration.getTemplate(currFtl);
// 设置输出路径
String outputPath = ROOTPATH + WEBPATH + entityName + "/" + paths[i] + "/" + (i % 2 == 0 ? (domainName + names[i]) : ("I" + domainName + names[i])) + ".java";
File file = new File(outputPath);
// 判断一下是否对应的文件是否已经存在,存在的话,不进行替换
if (file.exists()) {
System.err.println("[" + outputPath + "]" + "已经存在, 不替换");
continue;
}
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
boolean createDirectoryFlag = parentFile.mkdirs();
if (!createDirectoryFlag) {
System.err.println("========Danger: mkdirs() error!=========");
}
}
fileOutputStream = new FileOutputStream(outputPath);
outputStreamWriter = new OutputStreamWriter(fileOutputStream);
generatorTemplate.process(dataMap, outputStreamWriter);
System.err.println("-----" + outputPath + "生成成功" + "-----");
}
} catch (IOException | TemplateException e) {
e.printStackTrace();
} finally {
// 关闭流
StreamUtil.close(outputStreamWriter, fileOutputStream);
}
}
}
时间展示处理
这里仅处理两种不同的日期显示格式,如果有需要执行配置即可
public class JsonObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
public JsonObjectMapper() {
super();
// 空值处理为空串
this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
@Override
public void serialize(Object value, JsonGenerator jg, SerializerProvider sp) throws IOException {
jg.writeString("");
}
});
//设置JSON时间格式
SimpleModule module = new SimpleModule();
module.addSerializer(Date.class, new JsonSerializer<Date>() {
@Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String zero = "00:00:00";
if (zero.equals(sdf.format(value).split(" ")[1])) {
sdf = new SimpleDateFormat("yyyy-MM-dd");
}
jgen.writeString(sdf.format(value));
}
});
this.registerModule(module);
}
}
同时在spingmvc配置文件中配置:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="这里写JsonObjectMapper全限定名"></bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>