在工作中,程序员很多时候都是在写类似的代码。数不尽的CRUD操作何时是个头。作为后端程序员总是为了基础的分层,创建各层的类花费很多时间,其实这些都是很多操作都是固定的,为了提供工作的效率。我选择使用
mybatis-plus-generator
来自动完成那些操作。
不是我打广告,自动化一些常用的操作对于自身能力的提高和工作效率的提高都是很重要的。
项目目录结构
下面开始贴代码了:
package cn.infomany;
import cn.infomany.constant.Resource;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.BeetlTemplateEngine;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.*;
/**
* 执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
*
* @author zjb
*/
public class CodeGenerator {
public static void main(String[] args) throws FileNotFoundException, IllegalAccessException {
Properties properties = loadProperties();
Parameter parameter = new Parameter();
JCommander jCommander = JCommander.newBuilder().addObject(parameter).build();
try {
jCommander.parse(args);
} catch (ParameterException e) {
System.out.println(e.getMessage());
jCommander.usage();
return;
}
// 打印帮助信息
if (parameter.isHelp()) {
jCommander.usage();
return;
}
copy(properties, parameter);
/* 代码生成器 */
AutoGenerator mpg = new AutoGenerator();
/* 全局配置 */
GlobalConfig gc = new GlobalConfig()
.setOutputDir(parameter.getProjectPath())
.setAuthor(parameter.getAuthor())
.setFileOverride(parameter.isFileOverride())
.setBaseResultMap(parameter.isBaseResultMap())
.setDateType(DateType.ONLY_DATE)
.setOpen(parameter.isOpen());
mpg.setGlobalConfig(gc);
/* 数据源配置 */
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl(parameter.getUrl())
.setDriverName(parameter.getDriverName())
.setUsername(parameter.getUsername())
.setPassword(parameter.getPassword());
mpg.setDataSource(dsc);
/* 包配置 */
PackageConfig pc = new PackageConfig()
.setModuleName(parameter.getModuleName())
.setController(Resource.CONTROLLER)
.setParent(parameter.getParent());
mpg.setPackageInfo(pc);
/*
* 模板中的变量,这里最好不要和内置冲突
* 在模板中引用方式:${cfg.`key`},key就是map的key值
*/
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<>(1);
setMap(map);
}
};
/* 自定义输出配置 */
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig(parameter.getDao() + Resource.DOT_BTL) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
String parent = parameter.getParent();
String replaceParent = "";
if (StringUtils.isNotBlank(parent)) {
replaceParent = parent.replace(".", "/") + "/";
}
return parameter.getProjectPath() + "/" + replaceParent + pc.getModuleName() + "/dao/"
+ tableInfo.getEntityName() + "Dao" + StringPool.DOT_JAVA;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
/* 配置模板 */
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setController(parameter.getController())
.setService(parameter.getService())
.setServiceImpl(parameter.getServiceImpl())
.setMapper(parameter.getMapper())
.setEntity(parameter.getEntity())
.setXml(parameter.getXml());
mpg.setTemplate(templateConfig);
/* 策略配置 */
StrategyConfig strategy = new StrategyConfig();
// 设置驼峰命名法
strategy.setNaming(NamingStrategy.underline_to_camel)
.setColumnNaming(NamingStrategy.underline_to_camel)
.setEntityLombokModel(parameter.isEntityLombokModel())
.setRestControllerStyle(parameter.isRestControllerStyle())
.setInclude(parameter.getInclude())
.setChainModel(parameter.isChainModel())
.setLogicDeleteFieldName(parameter.getLogicDeleteFieldName())
.setVersionFieldName(parameter.getVersionFieldName())
.setControllerMappingHyphenStyle(false)
.setTablePrefix(parameter.getTablePrefix());
mpg.setStrategy(strategy);
/* 设置模板引擎 */
BeetlTemplateEngine beetlTemplateEngine = new BeetlTemplateEngine();
mpg.setTemplateEngine(beetlTemplateEngine);
mpg.execute();
}
private static void copy(Properties properties, Parameter parameter) throws IllegalAccessException {
Field[] declaredFields = Parameter.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
String name = declaredField.getName();
Object value = properties.get(name);
if (Objects.isNull(value)) {
continue;
}
if (value instanceof String && StringUtils.isBlank((String) value)) {
continue;
}
if (declaredField.getType().isArray()) {
String[] vacs = value.toString().split("\\s?,\\s?");
declaredField.set(parameter, vacs);
} else {
declaredField.set(parameter, value);
}
}
}
private static Properties loadProperties() throws FileNotFoundException {
// 获取内置属性
InputStream resourceAsStream =
CodeGenerator.class.getResourceAsStream("/application.properties");
assert !Objects.isNull(resourceAsStream);
// 检测是否有外部属性文件
File appProperties = new File("application.properties");
if (!appProperties.exists()) {
throw new FileNotFoundException("application.properties配置文件没有找到");
}
InputStream appPropertiesInputStream = new FileInputStream(appProperties);
Properties properties = new Properties();
try {
// 先加载内部的文件,然后加载外部的,外部优先级高
properties.load(resourceAsStream);
properties.load(appPropertiesInputStream);
return properties;
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}
上面是主方法,基本上那就是全部的代码了。
下面展示一些自定义的各层的模板吧:
<%
var uncapEntity = uncapFirst(entity);
%>
package ${package.Controller};
import cn.infomany.common.domain.PageParamDTO;
import org.springframework.web.bind.annotation.RequestMapping;
:: if(restControllerStyle){
import org.springframework.web.bind.annotation.RestController;
:: }else{
import org.springframework.stereotype.Controller;
:: }
:: if(isNotEmpty(superControllerClassPackage)){
import ${superControllerClassPackage};
:: }
/**
* <p>
* ${table.comment!} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
@Slf4j
@Validated
:: if(restControllerStyle){
@RestController
:: }else{
@Controller
:: }
:: if(isNotEmpty(package.ModuleName)){
@RequestMapping("/${package.ModuleName}/${table.entityPath}")
:: } else {
@RequestMapping("/${table.entityPath}")
:: }
:: if(isNotEmpty(superControllerClass)){
public class ${table.controllerName} extends ${superControllerClass} {
:: }else{
public class ${table.controllerName} {
:: /* 将服务注入进来 */
@Autowired
private I${entity}Service ${uncapEntity}Service;
/**
* 分页列表查询
*
* @param ${uncapEntity}PageListDTO
* @param pageParamDto
* @return
*/
@GetMapping(value = "/list")
public Result queryPageList(@Valid @RequestBody PageList${entity}DTO pageList${entity}DTO,
@Valid @RequestBody PageParamDTO pageParamDto) {
return ${uncapEntity}Service.page${entity}(pageList${entity}DTO, pageParamDto);
}
/**
* 添加
*
* @param ${uncapEntity}
* @return
*/
@PostMapping
public Result add(@Valid @RequestBody Add${entity}DTO add${entity}DTO) {
return ${uncapEntity}Service.save${entity}(add${entity}DTO);
}
/**
* 编辑
*
* @param ${uncapEntity}
* @return
*/
@PutMapping
public Result edit(@Valid @RequestBody Edit${entity}DTO edit${entity}DTO) {
${uncapEntity}Service.update${entity}(edit${entity}DTO);
return Result.success();
}
/**
* 通过id删除
*
* @param id
* @return
*/
@DeleteMapping
public Result delete(@NotNull(message = "id不能为空") @RequestParam String id) {
${uncapEntity}Service.remove${entity}ById(id);
return Result.success();
}
/**
* 批量删除
*
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result deleteBatch(@NotNull(message = "ids不能为空")
@Size(min = 1,message = "删除数量不能小于1")
@RequestParam String[] ids) {
this.${uncapEntity}Service.remove${entity}ByIds(ids);
return Result.success();
}
/**
* 通过id查询
*
* @param id
* @return
*/
@GetMapping
public Result queryById(@NotNull(message = "id不能为空") @RequestParam String id) {
return ${uncapEntity}Service.find${entity}ById(id);
}
}
:: }
在模板代码中可以看到很多${veriableName}
,这是使用beetl
的语法将数据和模板解析的方式。那veriableName
可以是名字呢?这里我就不卖关子了。断点调试到下面的代码。模板中获取的就是变量objectMap的值。
其他代码我就不展示了,直接贴gitee地址
网友评论