先看兄弟篇:MyBatis-generator简单升级
目的
整合模板引擎,生成mapper、xml、entity三个类之外的其他类。
例如:
-
pojoInsert、pojoUpdate实体(用户更新新增接口接收参数)
使用swagger注解实现API文档自动化显示。
使用@NotBlank
、@Length
、@NotNull
等注解实现参数校验。 -
service接口
接口作用 接口名 参数类型 新增 insert pojoInsert 删除 delete String id 更新 update pojoUpdate 详情 detail String id 查询 select IdPage 其中
delete
、detail
、select
接口在实现类中继承父类,不在接口中重复定义。 -
controller接口
接口上注解:
@PostMapping
、@ApiOperation
、@ApiImplicitParam
、
类上注解:
@RestController
、@RequestMapping
、@Api
实操
-
在MyBatis插件包中添加依赖:
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> <exclusions> <exclusion> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency>
-
定义一个模板使用的类
MyColumn
package org.pet.king.gen; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor public class MyColumn { private String javaProperty; private Integer length; private String typeHandler; private String remarks; private Boolean nullable; public MyColumn(String javaProperty, Integer length, String typeHandler, String remarks, Boolean nullable) { this.javaProperty = javaProperty; this.length = length; this.typeHandler = typeHandler; this.remarks = remarks; this.nullable = nullable; } }
后面说明单独定义的理由。
-
Velocity工具类:
package org.pet.king.gen; import org.apache.velocity.app.Velocity; import java.util.Properties; /** * VelocityEngine工厂 * * @author ruoyi */ public class VelocityInitializer { /** * 初始化vm方法 */ public static void initVelocity() { Properties p = new Properties(); try { // 加载classpath目录下的vm文件 p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); // 定义字符集 p.setProperty(Velocity.INPUT_ENCODING, "UTF-8"); p.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8"); // 初始化Velocity引擎,指定配置Properties Velocity.init(p); } catch (Exception e) { throw new RuntimeException(e); } } }
package org.pet.king.gen; import org.apache.commons.lang3.StringUtils; import org.apache.velocity.VelocityContext; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.java.TopLevelClass; import java.io.File; import java.util.ArrayList; import java.util.List; /** * 模板处理工具类 * * @author ruoyi */ public class VelocityUtils { /** * 项目空间路径 */ private static final String PROJECT_PATH = "main/java"; /** * 设置模板变量信息 * * @return 模板列表 */ public static VelocityContext prepareContext(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { // 获取包名 String packageName = topLevelClass.getType().getPackageName(); String tableAlias = introspectedTable.getTableConfiguration().getProperties().get("tableAlias").toString(); List<MyColumn> columnList = new ArrayList<>(); for (IntrospectedColumn column : introspectedTable.getAllColumns()) { // 创建时间和状态值无法修改,不需要此参数 if (column.getJavaProperty().equalsIgnoreCase("createTime") || column.getJavaProperty().equalsIgnoreCase("status") || column.getJavaProperty().equalsIgnoreCase("statusTime")) { continue; } else { MyColumn myColumn = new MyColumn(column.getJavaProperty(), column.getLength(), "", column.getRemarks(), column.isNullable()); // boolean类型参数需要特殊转义 // 其他类型同理 if (column.getJdbcTypeName().equalsIgnoreCase("TINYINT")) { myColumn.setTypeHandler("Boolean"); } else { myColumn.setTypeHandler(column.getFullyQualifiedJavaType().getShortName()); } columnList.add(myColumn); } } VelocityContext velocityContext = new VelocityContext(); velocityContext.put("ClassName", topLevelClass.getType().getShortName());// 类名 velocityContext.put("basePackage", getPackagePrefix(packageName));// 包名 velocityContext.put("packageName", packageName); velocityContext.put("columns", columnList);// 字段集合 // 首字母小写 char[] chars = topLevelClass.getType().getShortName().toCharArray(); //首字母小写方法,大写会变成小写,如果小写首字母会消失 chars[0] += 32; velocityContext.put("className", String.valueOf(chars));// 小写类名 velocityContext.put("functionName", tableAlias);// 模块名称 return velocityContext; } /** * 获取模板信息 * * @return 模板列表 */ public static List<String> getTemplateList() { List<String> templates = new ArrayList<String>(); templates.add("vm/pojoInsert.java.vm"); templates.add("vm/pojoUpdate.java.vm"); templates.add("vm/service.java.vm"); templates.add("vm/serviceImpl.java.vm"); templates.add("vm/controller.java.vm"); return templates; } /** * 获取包前缀 * * @param packageName 包名称 * @return 包前缀名称 */ public static String getPackagePrefix(String packageName) { int lastIndex = packageName.lastIndexOf("."); String basePackage = StringUtils.substring(packageName, 0, lastIndex); return basePackage; } public static String getFileName(String template, TopLevelClass topLevelClass) { // 文件名称 String fileName = ""; String javaPath = System.getProperty("user.dir") + File.separator + "src" + File.separator + PROJECT_PATH + "/" + StringUtils.replace(getPackagePrefix(topLevelClass.getType().getPackageName()), ".", "/"); if (template.contains("pojoInsert.java.vm")) { fileName = String.format("%s/entity/pojo/%sInsert.java", javaPath, topLevelClass.getType().getShortName()); } else if (template.contains("pojoUpdate.java.vm")) { fileName = String.format("%s/entity/pojo/%sUpdate.java", javaPath, topLevelClass.getType().getShortName()); } else if (template.contains("service.java.vm")) { fileName = String.format("%s/service/%sService.java", javaPath, topLevelClass.getType().getShortName()); } else if (template.contains("serviceImpl.java.vm")) { fileName = String.format("%s/service/impl/%sServiceImpl.java", javaPath, topLevelClass.getType().getShortName()); } else if (template.contains("controller.java.vm")) { fileName = String.format("%s/controller/%sController.java", javaPath, topLevelClass.getType().getShortName()); } return fileName; } }
MyBatis插件获取不到表名(注释),所以定义额外参数获取表名。
IntrospectedColumn类参数不能修改,否则会影响到MyBatis中xml文件的生成,所以自定义新的实体类。 -
使用:在
LombokPlugin
类的modelBaseRecordClassGenerated
方法中最开始加上如下代码,在使用MyBatis插件的时候就会自动执行模板的生成。VelocityInitializer.initVelocity(); VelocityContext context = VelocityUtils.prepareContext(topLevelClass, introspectedTable); // 渲染模板 // 获取模板列表 List<String> templates = VelocityUtils.getTemplateList(); for (String template : templates) { try { // 渲染模板 StringWriter sw = new StringWriter(); Template tpl = Velocity.getTemplate(template, "UTF-8"); tpl.merge(context, sw); FileUtils.writeStringToFile(new File(VelocityUtils.getFileName(template, topLevelClass)), sw.toString(), "UTF-8"); } catch (IOException e) { log.info("模板渲染失败"); e.printStackTrace(); } }
generatorConfig.xml:
<table tableName="ams_inform" domainObjectName="AmsInform" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> <property name="tableAlias" value="个人通知"/> </table>
添加一个property即可(必填)。
-
附件:
pojoInsert.java.vm(添加数据接收类)package ${basePackage}.entity.pojo; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; import java.util.Date; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @Data @ApiModel("${functionName}-添加") @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class ${ClassName}Insert implements Serializable { private static final long serialVersionUID = 1L; #foreach ($column in $columns) #if($column.javaProperty == 'id') @JsonIgnore #end #if($column.javaProperty == 'userId') @JsonIgnore #end #if($column.nullable == false) #if($column.typeHandler == 'String') @NotBlank(message = "请输入/选择${column.remarks}") @Length(max = ${column.length}, message = "${column.remarks}字段超长,请确认") #else @NotNull(message = "请输入/选择${column.remarks}") #end @ApiModelProperty(value = "${column.remarks}", required = true) #else @ApiModelProperty("${column.remarks}") #end #if($column.typeHandler == 'Date') @JsonFormat(locale = "zh", timezone = "Asia/Shanghai", pattern = "yyyy-MM-dd HH:mm:ss") #end private $column.typeHandler $column.javaProperty; #end }
pojoUpdate.java.vm(更新数据接收类)
package ${basePackage}.entity.pojo; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; import java.util.Date; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @Data @ApiModel("${functionName}-更新") @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class ${ClassName}Update implements Serializable { private static final long serialVersionUID = 1L; #foreach ($column in $columns) #if($column.javaProperty == 'id') #if($column.typeHandler == 'String') @NotBlank(message = "请选择数据") @Length(max = ${column.length}, message = "${column.remarks}字段超长,请确认") #else @NotNull(message = "请选择数据") #end #end #if($column.javaProperty == 'userId') @JsonIgnore #end #if($column.nullable == false) #if($column.typeHandler == 'String') @NotBlank(message = "请输入/选择${column.remarks}") @Length(max = ${column.length}, message = "${column.remarks}字段超长,请确认") #else @NotNull(message = "请输入/选择${column.remarks}") #end @ApiModelProperty(value = "${column.remarks}", required = true) #else @ApiModelProperty("${column.remarks}") #end #if($column.typeHandler == 'Date') @JsonFormat(locale = "zh", timezone = "Asia/Shanghai", pattern = "yyyy-MM-dd HH:mm:ss") #end private $column.typeHandler $column.javaProperty; #end }
其他三个项目色彩太严重了就不放了,根据这两个基本上自己就能写出来了,实在需要的私聊吧。