SaaS系统从0到1搭建,06代码生成(模板篇) 前言 代码

前言

车队管理类似的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文件

1
2
3
4
5
6
7
8
9
xml复制代码<?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内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码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对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
java复制代码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

表对应的接口类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
java复制代码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

接口实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
java复制代码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层,一般的增删改查的入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
kotlin复制代码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搭建,下篇继续….

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%