前言
之前在集成mybatis plus的时候有稍微写了下代码生成器的用法,现在这边稍微调整和优化一下,让后面生成基本的接口代码更加的方便,减少工作量啊,偷懒果然是爽啊。
实现
模板支持
mybatis plus的代码生成器是需要模板引擎的,默认使用的是velocity
模板,项目里也已经引用了。
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
当然也支持Freemarker
和Beetl
模板,看个人喜好,这边使用默认的。
自定义模板内容
可以看到mubatit-plus-generator
包templates
下存放着三种模板。
.vm
是velocity
模板, .ftl
和.btl
分别代表Freemarker
和Beetl
模板
在自己的项目下建立templates
文件夹,把mubatit-plus-generator
下的模板文件copy过来就可以自定义模板内容了。生成代码的时候会覆盖默认的模板,这边分别对controller
、service
、serviceImpl
进行编写
controller.java.vm
package ${package.Controller};
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicParameters;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.fastjson.JSONObject;
import com.ify.sampleAdmin.root.ResResult;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
#if(${restControllerStyle})
#else
import org.springframework.stereotype.Controller;
#end
#if(${superControllerClassPackage})
import ${superControllerClassPackage};
#end
import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
/**
* @description $!{cfg.description}
*
* @author ${author}
* @since ${date}
*/
#if(${restControllerStyle})
@RestController
#else
@Controller
#end
@RequestMapping("${cfg.moduleName}")
#if(${swagger2})
@Api(tags = "${entity}Api(${table.comment})", value = "${table.comment}")
#end
#if(${kotlin})
class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end
#else
#if(${superControllerClass})
public class ${table.controllerName} extends ${superControllerClass} {
#else
public class ${table.controllerName} {
#end
@Autowired
private ${table.serviceName} ${table.entityPath}Service;
@PostMapping(value = "/${table.entityPath}s")
@ApiOperation(value = "新增", notes = "接口描述")
@DynamicParameters(name = "save${entity}", properties = {
#foreach($field in ${table.fields})
@DynamicParameter(name = "${field.propertyName}", value = "${field.comment}", example = "", required = false, dataTypeClass = ${field.propertyType}.class),
#end
})
public ResResult save${entity}(@RequestBody JSONObject param){
return this.${table.entityPath}Service.save${entity}(param.toJavaObject(${entity}.class));
}
@PutMapping(value = "/${table.entityPath}s")
@ApiOperation(value = "更新", notes = "接口描述")
@DynamicParameters(name = "update${entity}", properties = {
#foreach($field in ${table.fields})
@DynamicParameter(name = "${field.propertyName}", value = "${field.comment}", example = "", required = false, dataTypeClass = ${field.propertyType}.class),
#end
})
public ResResult update${entity}(@RequestBody JSONObject param){
return this.${table.entityPath}Service.update${entity}(param.toJavaObject(${entity}.class));
}
@DeleteMapping(value = "/${table.entityPath}s/{id}")
@ApiOperation(value = "删除(单条)", notes = "接口描述")
public ResResult delete${entity}ById(@PathVariable("id") String id){
return this.${table.entityPath}Service.deleteById(id);
}
@PostMapping(value = "/${table.entityPath}s/batch")
@ApiOperation(value = "删除(批量)", notes = "接口描述")
@DynamicParameters(name = "delete${entity}ByIds", properties = {
@DynamicParameter(name = "ids", value = "id字符串", example = "id1,id2...", required = false, dataTypeClass = String.class),
})
public ResResult delete${entity}ByIds(@RequestBody JSONObject param){
return this.${table.entityPath}Service.deleteBatch(param.getString("ids"));
}
@GetMapping(value = "/${table.entityPath}s/{id}")
@ApiOperation(value = "查询(单条)", notes = "接口描述")
public ResResult get${entity}(@PathVariable("id") String id){
return this.${table.entityPath}Service.get${entity}ById(id);
}
@PostMapping(value = "/${table.entityPath}s/page")
@ApiOperation(value = "分页查询", notes = "接口描述")
@DynamicParameters(name = "find${entity}Page", properties = {
#foreach($field in ${table.fields})
@DynamicParameter(name = "${field.propertyName}", value = "${field.comment}", example = "", required = false, dataTypeClass = ${field.propertyType}.class),
#end
@DynamicParameter(name = "page", value = "分页对象", example = "{}", required = true, dataTypeClass = Page.class),
})
public ResResult find${entity}Page(@RequestBody JSONObject param){
return this.${table.entityPath}Service.findPage(param.toJavaObject(${entity}.class));
}
}
#end
这个文件主要生成controller代码,在基础接口上面增加swagger的注释文档,开发的时候看清空删减。
service.java.vm
package ${package.Service};
import ${package.Entity}.${entity};
import ${superServiceClassPackage};
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ify.sampleAdmin.root.ResResult;
/**
*
* $!{table.comment} 服务类
*
*
* @author ${author}
* @since ${date}
*/
#if(${kotlin})
interface ${table.serviceName} : ${superServiceClass}<${entity}>
#else
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
ResResult save${entity}(${entity} ${table.entityPath});
ResResult update${entity}(${entity} ${table.entityPath});
ResResult deleteById(String id);
ResResult deleteBatch(String ids);
ResResult get${entity}ById(String id);
ResResult findPage(${entity} ${table.entityPath});
}
#end
serviceImpl.java.vm
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.transaction.annotation.Transactional;
import com.ify.sampleAdmin.root.ResResult;
/**
*
* @description $!{table.comment} 服务实现类
* @author ${author}
* @since ${date}
*/
@Service
@Transactional(rollbackFor = Exception.class)
#if(${kotlin})
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {
}
#else
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}>implements ${table.serviceName} {
@Override
public ResResult save${entity}(${entity} ${table.entityPath}){
return null;
}
@Override
public ResResult update${entity}(${entity} ${table.entityPath}){
return null;
}
@Override
public ResResult deleteById(String id){
return null;
}
@Override
public ResResult deleteBatch(String ids){
return null;
}
@Override
public ResResult get${entity}ById(String id){
return null;
}
@Override
public ResResult findPage(${entity} ${table.entityPath}){
return null;
}
}
#end
代码生成器配置逻辑
@RestController
@RequestMapping("/sys")
@Api(tags = "GenApi(代码生成表)", value = "代码生成表")
public class GenController extends BaseController {
@Autowired
private GenService genService;
@PostMapping(value = "/gen/code")
@ApiOperation(value = "代码生成", notes = "接口描述")
@DynamicParameters(name = "generatorCode", properties = {
@DynamicParameter(name = "tableName", value = "表名", example = "", required = true, dataTypeClass = String.class),
@DynamicParameter(name = "tablePrefix", value = "表名前缀 填写前缀,生成实体不包含前缀", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "module", value = "模块名称 模块名称用来分类", example = "", required = true, dataTypeClass = String.class),
@DynamicParameter(name = "description", value = "功能描述", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "author", value = "作者", example = "", required = false, dataTypeClass = String.class),
})
public ResResult generatorCode(@RequestBody JSONObject param) {
this.genService.codeGenerator(param.toJavaObject(Gen.class));
return ResResult.success();
}
}
public interface GenService extends IService<Gen> {
/**
* 生成代码
* @param gen
*/
void codeGenerator(Gen gen);
}
/**
* <p>
* 代码生成表 服务实现类
* </p>
*
* @author ify
* @since 2021-01-28
*/
@Service
public class GenServiceImpl extends ServiceImpl<GenDao, Gen> implements GenService {
@Value("${spring.datasource.druid.driver-class-name}")
private String dbDriverName;
@Value("${spring.datasource.druid.url}")
private String dbUrl;
@Value("${spring.datasource.druid.username}")
private String dbUsername;
@Value("${spring.datasource.druid.password}")
private String dbPassword;
@Override
public void codeGenerator(Gen gen) {
String projectPath = System.getProperty("user.dir");
// 1、声明代码生成器
AutoGenerator generator = new AutoGenerator();
// 2、全局信息配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig
// 输出目录
.setOutputDir(projectPath + "/src/main/java")
// 是否覆盖原有文件 默认false
.setFileOverride(true)
// 是否打开输出目录 默认true
.setOpen(false)
// 作者
.setAuthor(StrUtil.isEmpty(gen.getAuthor()) ? " " : gen.getAuthor())
// 设置实体类名称
.setEntityName("%s")
// 设置mapper 命名方式
.setMapperName("%sDao")
// Mapper xml 命名方式
.setXmlName("%sDao")
//service 命名方式
.setServiceName("%sService")
//service impl 命名方式
.setServiceImplName("%sServiceImpl")
//controller 命名方式
.setControllerName("%sController")
// Mapper xml 生成基础 查询列 可以不设置
.setBaseColumnList(true)
//Mapper xml 生成基础返回map 可以不设置
.setBaseResultMap(true)
// 实体属性 Swagger2 注解 默认false
.setSwagger2(true);
// 3、数据源配置
DataSourceConfig dataSourceConfig = new DataSourceConfig();
// 设置数据库类型和数据源
dataSourceConfig.setDbType(DbType.MYSQL)
.setDriverName(dbDriverName)
.setUrl(dbUrl)
.setUsername(dbUsername)
.setPassword(dbPassword);
// 4、策略配置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig
// 数据库表映射实体 下划线转大写,驼峰命名方式
.setNaming(NamingStrategy.underline_to_camel)
// 数据库字段映射实体属性 下划线转大写,驼峰命名方式
.setColumnNaming(NamingStrategy.underline_to_camel)
// 生成 @RestController 控制器
.setRestControllerStyle(true)
// 设置controller继承的父类
.setSuperControllerClass(BaseController.class)
// entity继承的父类
.setSuperEntityClass(BaseEntity.class)
// entity继承类的字段
.setSuperEntityColumns("id", "create_by", "create_time", "update_by", "update_time")
// 是否生成lombok模式
.setEntityLombokModel(true)
//要生成的表名
.setInclude(gen.getTableName());
// 设置表前缀,生成的实体名称不包含前缀
if (StrUtil.isNotEmpty(gen.getTablePrefix())) {
strategyConfig.setTablePrefix(gen.getTablePrefix());
}
// 5、生成代码包信息配置
PackageConfig packageConfig = new PackageConfig();
packageConfig
// 设置生成的包名的父类名称
.setParent("com.ify.sampleAdmin.web")
.setController("controller" + "." + gen.getModule())
.setEntity("entity" + "." + gen.getModule())
.setMapper("dao" + "." + gen.getModule())
.setService("service" + "." + gen.getModule())
.setServiceImpl("service.impl" + "." + gen.getModule());
//xml 自定义输出到java 文件夹下,所以下面自定义输出路径
// .setXml(mapper");
// 自定义要注入到模板的属性,在模板里用cfg.xxx引用
InjectionConfig injectionConfig = new InjectionConfig() {
// 必须实现的方法, 内容可以放空
@Override
public void initMap() {
Map<String, Object> map = new HashMap<>(4);
map.put("moduleName", gen.getModule());
map.put("description", gen.getDescription());
this.setMap(map);
}
};
List<FileOutConfig> fileOutConfigList = new ArrayList<>();
FileOutConfig fileOutConfig = new FileOutConfig("/templates/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return projectPath + "/src/main/resources/mapper/" + gen.getModule() + "/" + tableInfo.getEntityName() + "Dao" + StringPool.DOT_XML;
}
};
fileOutConfigList.add(fileOutConfig);
injectionConfig.setFileOutConfigList(fileOutConfigList);
// 7 自定义模板
TemplateConfig templateConfig = new TemplateConfig();
// xml自定义输出路径,所以设置为null
templateConfig.setXml(null);
// 8、整合配置
generator.setGlobalConfig(globalConfig)
.setDataSource(dataSourceConfig)
.setStrategy(strategyConfig)
.setPackageInfo(packageConfig)
.setTemplate(templateConfig)
.setCfg(injectionConfig);
//9、执行
generator.execute();
}
}
把基础的表重新生成一遍。
看一下生成的基本代码是什么样子
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_user")
@ApiModel(value="User对象", description="")
public class User extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "性别 0 女| 1 男")
private String sex;
@ApiModelProperty(value = "是否锁住 0 否 | 1 是")
private String locked;
}
public interface UserService extends IService<User> {
ResResult saveUser(User user);
ResResult updateUser(User user);
ResResult deleteById(String id);
ResResult deleteBatch(String ids);
ResResult getUserById(String id);
ResResult findPage(User user);
}
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserDao, User>implements UserService {
@Override
public ResResult saveUser(User user){
return null;
}
@Override
public ResResult updateUser(User user){
return null;
}
@Override
public ResResult deleteById(String id){
return null;
}
@Override
public ResResult deleteBatch(String ids){
return null;
}
@Override
public ResResult getUserById(String id){
return null;
}
@Override
public ResResult findPage(User user){
return null;
}
}
@RestController
@RequestMapping("sys")
@Api(tags = "UserApi(用户表)", value = "")
public class UserController extends BaseController {
@Autowired
private UserService userService;
@PostMapping(value = "/users")
@ApiOperation(value = "新增", notes = "接口描述")
@DynamicParameters(name = "saveUser", properties = {
@DynamicParameter(name = "username", value = "用户名", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "password", value = "密码", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "sex", value = "性别 0 女| 1 男", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "locked", value = "是否锁住 0 否 | 1 是", example = "", required = false, dataTypeClass = String.class),
})
public ResResult saveUser(@RequestBody JSONObject param){
return this.userService.saveUser(param.toJavaObject(User.class));
}
@PutMapping(value = "/users")
@ApiOperation(value = "更新", notes = "接口描述")
@DynamicParameters(name = "updateUser", properties = {
@DynamicParameter(name = "username", value = "用户名", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "password", value = "密码", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "sex", value = "性别 0 女| 1 男", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "locked", value = "是否锁住 0 否 | 1 是", example = "", required = false, dataTypeClass = String.class),
})
public ResResult updateUser(@RequestBody JSONObject param){
return this.userService.updateUser(param.toJavaObject(User.class));
}
@DeleteMapping(value = "/users/{id}")
@ApiOperation(value = "删除(单条)", notes = "接口描述")
public ResResult deleteUserById(@PathVariable("id") String id){
return this.userService.deleteById(id);
}
@PostMapping(value = "/users/batch")
@ApiOperation(value = "删除(批量)", notes = "接口描述")
@DynamicParameters(name = "deleteUserByIds", properties = {
@DynamicParameter(name = "ids", value = "id字符串", example = "id1,id2...", required = false, dataTypeClass = String.class),
})
public ResResult deleteUserByIds(@RequestBody JSONObject param){
return this.userService.deleteBatch(param.getString("ids"));
}
@GetMapping(value = "/users/{id}")
@ApiOperation(value = "查询(单条)", notes = "接口描述")
public ResResult getUser(@PathVariable("id") String id){
return this.userService.getUserById(id);
}
@PostMapping(value = "/users/page")
@ApiOperation(value = "分页查询", notes = "接口描述")
@DynamicParameters(name = "findUserPage", properties = {
@DynamicParameter(name = "username", value = "用户名", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "password", value = "密码", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "sex", value = "性别 0 女| 1 男", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "locked", value = "是否锁住 0 否 | 1 是", example = "", required = false, dataTypeClass = String.class),
@DynamicParameter(name = "page", value = "分页对象", example = "{}", required = true, dataTypeClass = Page.class),
})
public ResResult findUserPage(@RequestBody JSONObject param){
return this.userService.findPage(param.toJavaObject(User.class));
}
}
swagger文档的效果
轻松加愉快!
补充
BaseEntity
封装了分页对象
@Data
public class BaseEntity {
/**
* id 生成策略为UUID
*/
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/**
* 创建者 填充策略为插入自动填充
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 创建时间 填充策略为插入自动填充
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新者 填充策略为更新自动填充
*/
@TableField(fill = FieldFill.UPDATE)
private String updateBy;
/**
* 更新时间 填充策略为更新自动填充
*/
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
/**
* 分页对象,分页查询传参用
*/
@TableField(exist = false)
private Page page;
}
结尾
偷懒工作就这些了,后面开发生成代码可以节省点基础crud代码的编写