前言
车队管理类似的SaaS平台,从0到1,继续..
上一篇咱撸到租户入驻,已经是实际业务场景了,然后在设计下入驻的租户主要信息,已经租户的状态历史表。本篇本来是编写下关于SaaS计费规则的,但这块还是得按需求来设计,就先不要了。 那就从代码生成器,做个分享吧。
(我是后半夜Java,在掘金这分享下经验,那些靠copy的搬运作者,未经允许,不要copy文章了)
代码生成
程序猿子都知道,平白无期的copy代码是浪费时间的,一直CtrlC CtrlV 浪费头发,主要的精力应该用在业务逻辑上,架构完善上面,那么有一套代码生成的工具,就灰常的适合,或者已经就是程序猿的必备工具了。
场景
比如新增个业务表,那么表已经有了,如果咱用的是Mybatis 那么那些基础的SQL、表对应的Bean对象,CRUD的基础方法这些基本都是一样的,所以这类代码就是需要咱自动生成代码的工具来完成了。
做法
估计网上可以搜索出一片的代码生成工具,但从原理上或者思路上,去理解下,对每个程序猿都会有些成长值。
思路
表->获取字段,生成基本TableNameMapping.xml ,及对应的Bean对象,然后生成service、control那些
准备
先了解下Velocity,也就是*.vm 后缀的文件,Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(templatelanguage)来引用由java代码定义的对象。
TableNameMapping.xml.vm
mapping文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${package}.${moduleName}.dao.${className}Dao">
<resultMap type="${package}.${moduleName}.entity.${className}Entity" id="${classname}Map">
#foreach($column in $columns)
<result property="${column.attrname}" column="${column.columnName}"/>
#end
</resultMap>
</mapper>
TableNameDao.java.vm
Dao内容
package ${package}.${moduleName}.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import ${package}.${moduleName}.entity.${className}Entity;
/**
* ${comments}
* @author ${author}
* @date ${datetime}
*/
@Mapper
public interface ${className}Dao extends BaseMapper<${className}Entity> {
}
TableNameEntity.java.vm
Entity表对象,也有叫model的,反正一个意思,就是表对应的bean对象
package ${package}.${moduleName}.entity;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
#if(${hasBigDecimal})
import java.math.BigDecimal;
#end
import java.io.Serializable;
import java.util.Date;
/**
* 对象说明:${comments}
* @author ${author}
* @date ${datetime}
*/
@TableName("${tableName}")
@Data
public class ${className}Entity implements Serializable {
private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
/**
* $column.comments
*/
#if($column.columnName == $pk.columnName)
@TableId
#end
private $column.attrType $column.attrname;
#end
}
TableNameService.java.vm
表对应的接口类
package ${package}.${moduleName}.service;
import com.baomidou.mybatisplus.extension.service.IService;
import ${mainPath}.common.utils.PageUtils;
import ${package}.${moduleName}.entity.${className}Entity;
import java.util.Map;
/**
* 接口描述:${comments}
* @author ${author}
* @date ${datetime}
*/
public interface ${className}Service extends IService<${className}Entity> {
/**
* 分页查询
* @param params
* @return
*/
PageUtils queryPage(Map<String, Object> params);
}
TableNameServiceImpl.java.vm
接口实现类
package ${package}.${moduleName}.service.impl;
import org.springframework.stereotype.Service;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ${mainPath}.common.utils.PageUtils;
import ${mainPath}.common.utils.Query;
import ${package}.${moduleName}.dao.${className}Dao;
import ${package}.${moduleName}.entity.${className}Entity;
import ${package}.${moduleName}.service.${className}Service;
/**
* 描述:${comments}
* @author ${author}
* @date ${datetime}
*/
public class ${className}ServiceImpl extends ServiceImpl<${className}Dao, ${className}Entity> implements ${className}Service {
/**
* 分页查询
* @param params
* @return
*/
@Override
public PageUtils queryPage(Map<String, Object> params) {
IPage<${className}Entity> page = this.page(
new Query<${className}Entity>().getPage(params),
new QueryWrapper<${className}Entity>()
);
return new PageUtils(page);
}
}
TableNameController.java.vm
最后就是control层,一般的增删改查的入口:
package ${package}.${moduleName}.controller;
import java.util.Arrays;
import java.util.Map;
import io.renren.common.validator.ValidatorUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ${package}.${moduleName}.entity.${className}Entity;
import ${package}.${moduleName}.service.${className}Service;
import ${mainPath}.common.utils.PageUtils;
import ${mainPath}.common.utils.R;
/**
* 描述:${comments}
* @author ${author}
* @date ${datetime}
*/
@RestController
@RequestMapping("${moduleName}/${pathName}")
public class ${className}Controller {
@Autowired
private ${className}Service ${classname}Service;
/**
* 分页查询列表
*/
@RequestMapping("/list")
@RequiresPermissions("${moduleName}:${pathName}:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = ${classname}Service.queryPage(params);
return R.ok().put("page", page);
}
/**
* 获取单个对象信息
*/
@RequestMapping("/info/{${pk.attrname}}")
@RequiresPermissions("${moduleName}:${pathName}:info")
public R info(@PathVariable("${pk.attrname}") ${pk.attrType} ${pk.attrname}){
${className}Entity ${classname} = ${classname}Service.getById(${pk.attrname});
return R.ok().put("${classname}", ${classname});
}
/**
* 新增
*/
@RequestMapping("/save")
@RequiresPermissions("${moduleName}:${pathName}:save")
public R save(@RequestBody ${className}Entity ${classname}){
${classname}Service.save(${classname});
return R.ok();
}
/**
* 编辑修改
*/
@RequestMapping("/update")
@RequiresPermissions("${moduleName}:${pathName}:update")
public R update(@RequestBody ${className}Entity ${classname}){
ValidatorUtils.validateEntity(${classname});
${classname}Service.updateById(${classname});
return R.ok();
}
/**
* 删除(物理删除)
*/
@RequestMapping("/delete")
@RequiresPermissions("${moduleName}:${pathName}:delete")
public R delete(@RequestBody ${pk.attrType}[] ${pk.attrname}s){
${classname}Service.removeByIds(Arrays.asList(${pk.attrname}s));
return R.ok();
}
}
总结
代码生成,有很多案例,这种可以自己修改模板的开源也有一些,这种模板的做法,是相对比较好的实现方式。模板分享,下篇我们继续生成代码逻辑。
SaaS系统从0到1搭建,下篇继续....