代码规范与工具使用
# 前言
本手册作为实际开发阶段的主要指导性文档,阅读范围为开发人员
# 相关术语
- IOC : 依赖注入或反向控制
- AOP : 面向切面编程
- Domain : 数据持久化VO类(ValueObject)
- Repository : 数据仓库,相当于Dao
- Service : 业务层或逻辑层
- Controller : 不做特别说明时指Spring MVC的Controller(控制器)
# 技术选型
# 环境
- Java SDK 8
- Apache Maven 3.x
# 基础框架
- Spring Boot 2
- Spring Framework 5
- Apache MyBatis 3
- Spring MVC
# 数据库
- MySQL
# 工具使用
# 代码生成器
# 基础配置
- 配置src/main/resources/codeGenerate.properties
javaPath=src/main/java/com/gictgict/ims/modules/
webpath=D:/work/HBuilderProjects/mtsample_front/src/views
sourceJavaPath=src/main/java/com/gictgict/ims/modules/
sourceWebpath=D:/work/HBuilderProjects/mtsample_front/src/views
sysCode=ims
rootPackage=com.gictgict
templatePath=D:/mttemplate
1
2
3
4
5
6
7
2
3
4
5
6
7
javaPath 生成的java文件所在的module目录,相对路径
webpath 生成的前端文件(vue)所在的目录,以/开始或含有:的为绝对路径,否则为相对路径
sourceJavaPath java模板文件所在的module目录,相对路径
sourceWebpath 前端模板文件(vue)所在的目录,以/开始或含有:的为绝对路径,否则为相对路径
sysCode 当前系统的系统代码
rootPackage 当前系统的包
templatePath 模板存放的目录
*
# 写好代码生成的excel
# 生成
- 打开src/main/java/项目/tools/CodeGeneratorByExcel.java
- fileOrPath改成excel模板的绝对路径
- java执行
# 代码规范
# 命名规范
以下以功能代码为demo的功能作为例子
# 功能代码
- 每个功能都有唯一的功能代码
- 功能代码全小写
- 功能代码的命名上避免歧义
- 最好让人一看就知道这功能的意思,而且好拼写好记
- 因功能代码也显示在url上,所以要符合英文词意,不能让用户觉得我们的英语很差劲
- 原则上在能表达意思,不使用缩写(公认的缩写除外)的基础上越短越好,尽量不要超过两个单词
- 在其它功能使用到功能时,命名上要保持功能代码的小写,例如送货时间段的功能代码为deliverytime,那么送货时间段的id属性命名应该为:deliverytimeId,不能是deliveryTimeId
# 方法命名规范
- 取得单个对象的方法:get+功能代码:getDemoById
- 取得对象列表的方法:list+功能代码:listDemo
- 新增对象方法:create+功能代码:createDemo
- 修改对象方法:update+功能代码:updateDemo
- 删除对象方法:delete+功能代码:deleteDemo
# 属性规范
# 常用
- id 主键
- name 名称
- code 代码(或编码,主要用来给内部使用的代码/编码)
- number 编码(给外部使用的,有一定生成规则自动生成的,比如订单号)
- createTime 创建时间
- lastUpdateTime 最后更新时间
- showOrder 排序
- mobile 手机号码
- wechat 微信
- memo 备注
- status 状态
- enableStatus 启用状态
- operatorId 操作人id
- operatorName 操作人name
# 其它
- loginId 登录账号
- username 用户名
- description 描述
- bankUsername 开户名称
- bankName 开户行
- bankAccount 银行账号
# 公共字典库
- common.enableStaus 启用状态
- common.yesOrNot 是否
# Domain
- 类放在domain目录下
- 类名为功能代码:Demo
- 属性不能用原生(int,long)类型,用对象类型(Integer,Long)
- 货币和涉及到计算的用BigDecimal类型,不用Float和Double
- 用1和0表示是和否(或有类似是否含义的属性)
- 子表一般用item表示
# Repository
- 类放在repository目录下
- 没有接口类
- 类名,功能代码+Repository:DemoRepository
- 方法命名规范类似Service
# Service
- 接口和实现类都放在service目录下
- 接口类名,I+功能代码+Service:IDemoServcie
- 实现类名以,功能代码+ServiceImpl:DemoServcieImpl
# Controller
- 类放在web目录下
- 类名,功能代码+Controller:DemoController
- 方法命名规范类似Service,操作当前功能时不用加功能代码,比如:list(),delete(),create(),update(),get()
# 项目目录结构

# 功能存放位置要求
- 每个功能一个完整的目录结构(每个功能独有自己的service,repository,domain,web等功能结构目录)
# Domain编码
- 必须继承基类com.helpfulzoo.common.base.BaseDomain
- 主键必须是String类型的id(全小写)
- 属性类型不能是原生类型,比如不能是int,只能是Integer
- 注解在Jpa的基础上加了@Comment属性名
- 类和属性上必须加上@Comment属性名注解
- 要在属性上注解,不能在方法上注解
- 其它的请参考domain例子
# domain例子
package com.gictgict.fpms.modules.demo.domain;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import com.helpfulzoo.common.orm.Comment;
import java.util.Date;
import com.helpfulzoo.common.base.BaseDomain;
/**
* 演示功能
* @author abc
* @date 2020-01-10
*/
@Entity
@Table(name = "fpms_demo")
@Comment("演示功能")
public class Demo extends BaseDomain {
private static final long serialVersionUID = 1L;
@Id
@Column(length = 32)
@GeneratedValue(generator = "uuid.hex")
private String id;
@Comment("名称")
private String name;
@Comment("代码")
private String code;
//@Clob
@Comment("配置")
private String config;
@Column(length = 32)
@Comment("操作人id")
private String operatorId;
@Comment("操作人name")
private String operatorName;
@Comment("排序")
private Float showOrder;
@Comment("备注")
private String memo;
@Comment("创建时间")
private Date createTime;
@Comment("修改时间")
private Date lastUpdateTime;
@Transient
private String test;//不持久化的属性
...get set 方法省略
}
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
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
# Repository编码
- 必须继承基类com.helpfulzoo.common.base.BaseRepository
- 其它的请参考repository例子
# repository例子
package com.gictgict.fpms.modules.demo.repository;
import org.springframework.stereotype.Repository;
import com.gictgict.fpms.modules.demo.domain.Demo;
import com.helpfulzoo.common.base.BaseRepository;
import com.helpfulzoo.common.orm.Query;
import com.helpfulzoo.common.page.model.Page;
@Repository("demoRepository")
public class DemoRepository extends BaseRepository<Demo> {
public Demo getDemoById(String id) {
return this.getById(id);
}
public Demo createDemo(Demo demo) {
return this.create(demo);
}
public Demo updateDemo(Demo demo) {
return this.update(demo);
}
public Page<Demo> listDemoForPage(Query query) {
return this.listForPage(query);
}
public void deleteDemo(String... ids) {
this.delete(ids);
}
//Page<Demo> list(Map searchMap);
}
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
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
# Service编码
- 必须继承基类com.helpfulzoo.common.base.BaseService
- 接口以I开始,实现以Impl结尾
- 其它的请参考service例子
# service例子
package com.gictgict.fpms.modules.demo.service;
import java.util.Date;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.freeworld.util.ReflectionUtil;
import com.gictgict.fpms.modules.demo.domain.Demo;
import com.gictgict.fpms.modules.demo.repository.DemoRepository;
import com.helpfulzoo.common.base.BaseRepository;
import com.helpfulzoo.common.base.BaseService;
import com.helpfulzoo.common.orm.Query;
import com.helpfulzoo.common.orm.QueryUtil;
import com.helpfulzoo.common.page.model.Page;
@SuppressWarnings("unchecked")
@Service("demoService")
public class DemoServiceImpl extends BaseService<Demo> implements IDemoService {
@Autowired
private DemoRepository demoRepository;
@Override
protected BaseRepository<Demo> getRepository() {
return demoRepository;
}
@Override
public Demo getDemoById(String id) {
return demoRepository.getDemoById(id);
}
@Override
public Demo createDemo(Demo demoFromWeb) {
demoFromWeb.setCreateTime(new Date());
return demoRepository.createDemo(demoFromWeb);
}
@Override
public Page<Demo> listDemoForPage(Map map) {
QueryUtil.getTableInfo(Demo.class);//autotable
return demoRepository.listDemoForPage(new Query("code,name").fromMap(map).order("create_time", Query.ORDER_DESC));
}
@Override
public Demo updateDemo(Demo demoFromWeb) {
Demo demo = demoRepository.getDemoById(demoFromWeb.getId());
ReflectionUtil.copyProperties(demo, demoFromWeb);
demo.setLastUpdateTime(new Date());
return demoRepository.updateDemo(demo);
}
@Override
public void deleteDemo(String[] ids) {
demoRepository.deleteDemo(ids);
}
}
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
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
# Controller编码
- 必须继承基类com.helpfulzoo.common.base.BaseController
- 其它的请参考controller例子
# controller例子
package com.gictgict.fpms.modules.demo.web;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.freeworld.json.Json;
import com.freeworld.util.JsonUtil;
import com.freeworld.util.StringUtil;
import com.gictgict.fpms.modules.demo.domain.Demo;
import com.gictgict.fpms.modules.demo.service.IDemoService;
import com.helpfulzoo.common.base.BaseController;
import com.helpfulzoo.common.page.model.Page;
@RestController
@RequestMapping("/wapi/demo")
public class DemoController extends BaseController {
@Autowired
private IDemoService demoService;
@PostMapping("/get")
@ResponseBody
public String getById(@RequestBody Map map) {
String id = (String)map.get("id");
Demo demo = demoService.getDemoById(id);
if (StringUtil.isBlank(demo.getId())) {
return this.newJson().setErrorMessage("无法找到对应的数据").toJsonString();
} else {
return getJson(demo, "操作成功");
}
}
@PostMapping("/create")
@ResponseBody
public String create(@RequestBody Demo demoFromWeb) {
Demo demo = demoService.createDemo(demoFromWeb);
return getJson(demo, "保存成功");
}
@PostMapping("/update")
@ResponseBody
public String update(@RequestBody Demo demoFromWeb) {
Demo demo = demoService.updateDemo(demoFromWeb);
return getJson(demo, "保存成功");
}
private String getJson(Demo demo, String tip) {
return this.newJson().put("demo", demo, getDemoFilter()).setSuccessMessage(tip).toJsonString();
}
@PostMapping("/delete")
@ResponseBody
public String delete(@RequestBody String[] ids) {
demoService.deleteDemo(ids);
return this.newJson().setSuccessMessage("删除成功").toJsonString();
}
@PostMapping("/list")
@ResponseBody
public String list(@RequestBody Map searchMap) {
Page page = demoService.listDemoForPage(searchMap);
Json json = this.newJson();
this.setPage(json, page);
this.setList(json, page.getList(), demo -> new Json().copy(demo, getDemoFilter()));
return json.toJsonString();
}
private String getDemoFilter() {
return "id, name, code, config, memo, createTime, lastUpdateTime";
}
}
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
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