# 案例分析

在开始项目前,我们先来了解下项目框架的整体构思以及依赖关系,在《目录结构》这一章节中我们详细的展示和介绍了框架结构及相关配置信息,框架最新核心的模块是javaweb-common,其他几个模板底层依赖都是他,可以这样理解他是整个框架的地基,没有他其他模块将毫无意义,下面我们会对框架进行一个整体的分析。

# 自定义注解

在SpringBoot项目开发中,我们会发现注解是常用的工具,比如常见的注解@Controller@RequestMapping@Autowired@ResponseBody@PostMapping等等,目前我们所使用的大部分注解都是SpringBoot框架所提供的,实际使用中发现注解确实是一个非常实用的东西,不能帮我我们实现了原先需要些大量代码才能完成的功能,而且让我们少写了很多代码的同时让我们的程序变得简洁、易读,根据项目的实际业务场景我们框架中也自定义了部分注解来帮我们完成相应的功能:

  • @Excel: 导出Excel注解,在很多模块中我们都需要对外导出Excel的功能,那么如何才能方便简洁的导出Excel呢?@Excel帮我们实现了目标,使用也非常简单,只需要在需要导出数据的类字段上添加这个注解即可,举例说明,如:@Excel(name = "添加时间"),@Excel(name = "角色状态", readConverterExp = "1=正常,2=停用")等等,代码非常简洁,添加完注解后,导出Excel时只需调用框架中封装好的ExcelUtil工具类即可,此工具类是动态解析上述注解信息,具体使用可查看项目,直接看使用案例。
  • @Log:日志注解,项目研发中或多或少都需要实现诸如:登录日志操作日志的功能,那么我们是否有简便的方法去实现呢?JAVA其实已经帮我考虑到了,基于AOP的思想去实现日志记录的功能,框架中@Log就是基于这一思想,采取线程异步的方式来实现了系统日志功能,注解使用也非常简单,只需要在需要记录操作日志的方法上加上这一注解即可,如:@Log(title = "职级", businessType = BusinessType.INSERT)@Log(title = "职级", businessType = BusinessType.UPDATE)一行代码轻松搞定,无需堆砌大量代码去实现,详细的使用场景请直接看框架源码,简单易读。

# 框架基类

为了简化模块的开发,我们对项目中每一层级文件都封装了一个基类文件,在新建文件时只需要集成基类即可帮你完成一些基础的功能,避免了抒写大量的重复性代码,我们封装基类的初衷就是简化开发,提高开发效率,把开发人员从复杂重复率高的代码中解放出来,只需要将精心放在业务的处理上,下面我们详细的介绍每个基类的内容及其用途:

  • 控制器基类(BaseController.java):控制器基类目前封装的比较简单,抽离了模块中共性的一些方法,如列表页显示、编辑页显示、删除方法等等,内容如下:
// +----------------------------------------------------------------------
// | JavaWeb_Cloud_Pro微服务旗舰版框架 [ JavaWeb ]
// +----------------------------------------------------------------------
// | 版权所有 2019~2020 南京JavaWeb研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.javaweb.vip/
// +----------------------------------------------------------------------
// | 作者: 鲲鹏 <1175401194@qq.com>
// +----------------------------------------------------------------------

package com.javaweb.common.framework.common;

/**
 * 基类控制器
 */
public class BaseController {

}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  • 实体基类(BaseEntity.java) 实体基类对实体类中共性的字段信息做了抽离,避免每个实体类中都会出现重复性的字段,如:记录ID创建人(createUser)创建时间(createTime)更新人(updateUser)更新时间(updateTime)有效标识(mark)等等,内容如下:
// +----------------------------------------------------------------------
// | JavaWeb_Cloud_Pro微服务旗舰版框架 [ JavaWeb ]
// +----------------------------------------------------------------------
// | 版权所有 2019~2020 南京JavaWeb研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.javaweb.vip/
// +----------------------------------------------------------------------
// | 作者: 鲲鹏 <1175401194@qq.com>
// +----------------------------------------------------------------------

package com.javaweb.common.framework.common;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serializable;
import java.util.Date;

/**
 * 基类实体对象
 *
 * @author 牧羊人
 * @date 2019/11/28
 */
@Data
public class BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键ID
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /**
     * 添加人
     */
    private Integer createUser;

    /**
     * 创建时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
    private Date createTime;

    /**
     * 更新人
     */
    private Integer updateUser;

    /**
     * 更新时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
    private Date updateTime;

    /**
     * 有效标识
     */
    private Integer mark;

}

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

特别说明

子类实体类只需要继承当前BaseEntity即可。

  • 列表查询基类(BaseQuery.java) 在数据列表中,必不可少的会对数据进行分页和条件筛选,其他筛选条件都是动态的,但是对于列表而言分页确实大家共性的东西,因此我们特地封装了查询基类,子类只需集成即可,内容如下:
// +----------------------------------------------------------------------
// | JavaWeb_Cloud_Pro微服务旗舰版框架 [ JavaWeb ]
// +----------------------------------------------------------------------
// | 版权所有 2019~2020 南京JavaWeb研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.javaweb.vip/
// +----------------------------------------------------------------------
// | 作者: 鲲鹏 <1175401194@qq.com>
// +----------------------------------------------------------------------

package com.javaweb.common.framework.common;

import lombok.Data;

/**
 * 查询对象基类
 */
@Data
public class BaseQuery {
    /**
     * 页码(默认1)
     */
    private Integer page = 1;

    /**
     * 每页数(默认:20)
     */
    private Integer limit = 20;
}


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
  • 接口基类(IBaseService.java) 在MybatisPlus中框架已经提供了接口IService,根据框架设计要求,我们需要抽离出一些公共的API接口对外暴露调用,IService接口层提供了封装的API接口,但是对于我们框架来说肯定想做增强,同时又省的我们在每个业务模块中去写重复性的增删改查等一些重复性的方法,现在得在IService模块接口等中间写一个基类做桥接,因此IBaseService接口基类显得必不可少,直接上代码,内容如下:
// +----------------------------------------------------------------------
// | JavaWeb_Cloud_Pro微服务旗舰版框架 [ JavaWeb ]
// +----------------------------------------------------------------------
// | 版权所有 2019~2020 南京JavaWeb研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.javaweb.vip/
// +----------------------------------------------------------------------
// | 作者: 鲲鹏 <1175401194@qq.com>
// +----------------------------------------------------------------------

package com.javaweb.common.framework.common;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.javaweb.common.framework.utils.JsonResult;

import java.io.Serializable;
import java.util.List;


public interface IBaseService<T> extends IService<T> {

    /**
     * 根据查询条件获取数据列表
     *
     * @param page  分页
     * @param query 查询条件
     * @return
     */
    JsonResult getList(Page<T> page, BaseQuery query);

    /**
     * 获取数据列表
     *
     * @param query 查询条件
     * @return
     */
    JsonResult getList(BaseQuery query);

    /**
     * 根据ID获取记录信息
     *
     * @param id 记录ID
     * @return
     */
    JsonResult info(Integer id);

    /**
     * 根据ID获取记录信息
     *
     * @param id 记录ID
     * @return
     */
    Object getInfo(Serializable id);

    /**
     * 根据实体对象添加记录
     *
     * @param entity 实体对象
     * @return
     */
    JsonResult add(T entity);

    /**
     * 根据实体对象更新记录
     *
     * @param entity 实体对象
     * @return
     */
    JsonResult update(T entity);

    /**
     * 根据实体对象添加、编辑记录
     *
     * @param entity 实体对象
     * @return
     */
    JsonResult edit(T entity);

    /**
     * 删除记录
     *
     * @param entity 实体对象
     * @return
     */
    JsonResult delete(T entity);

    /**
     * 根据ID删除记录
     *
     * @param id 记录ID
     * @return
     */
    JsonResult deleteById(Integer id);

    /**
     * 根据ID删除记录
     *
     * @param ids 记录ID
     * @return
     */
    JsonResult deleteByIds(Integer[] ids);

    /**
     * 设置状态
     *
     * @param entity 实体对象
     * @return
     */
    JsonResult setStatus(T entity);

    /**
     * 导出Excel
     *
     * @return
     */
    List<T> exportExcel();

}


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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  • 接口实现基类(BaseServiceImpl.java) 上面我们详细的介绍了,同理我们也需要写一个匹配IBaseService接口的实现基类BaseServiceImpl,在接口实现基类中我们将接口层的方法一一的做了重写和实现,已达到我们所期待的业务和数据处理,内容如下:
// +----------------------------------------------------------------------
// | JavaWeb_Cloud_Pro微服务旗舰版框架 [ JavaWeb ]
// +----------------------------------------------------------------------
// | 版权所有 2019~2020 南京JavaWeb研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.javaweb.vip/
// +----------------------------------------------------------------------
// | 作者: 鲲鹏 <1175401194@qq.com>
// +----------------------------------------------------------------------

package com.javaweb.common.security.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.javaweb.api.system.entity.User;
import com.javaweb.common.framework.common.BaseEntity;
import com.javaweb.common.framework.common.BaseQuery;
import com.javaweb.common.framework.common.IBaseService;
import com.javaweb.common.framework.config.CommonConfig;
import com.javaweb.common.framework.utils.DateUtils;
import com.javaweb.common.framework.utils.JsonResult;
import com.javaweb.common.framework.utils.StringUtils;
import com.javaweb.common.security.utils.SecurityUtils;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> implements IBaseService<T> {

    /**
     * 根据查询条件获取数据列表
     *
     * @param page  分页
     * @param query 查询条件
     * @return
     */
    @Override
    public JsonResult getList(Page<T> page, BaseQuery query) {
        return null;
    }

    /**
     * 获取数据列表
     *
     * @param query 查询条件
     * @return
     */
    @Override
    public JsonResult getList(BaseQuery query) {
        return null;
    }

    /**
     * 根据实体ID获取实体信息
     *
     * @param id 记录ID
     * @return
     */
    @Override
    public JsonResult info(Integer id) {
        if (id == null && id <= 0) {
            return JsonResult.error("记录ID不能为空");
        }
        Object result = this.getInfo(id);
        return JsonResult.success(result, "操作成功");
    }

    /**
     * 根据ID获取记录信息
     *
     * @param id 记录ID
     * @return
     */
    @Override
    public Object getInfo(Serializable id) {
        T entity = this.getById(id);
        return entity;
    }

    /**
     * 传入实体对象添加记录
     *
     * @param entity 实体对象
     * @return
     */
    @Override
    public JsonResult add(T entity) {
        entity.setCreateUser(SecurityUtils.getUserId());
        entity.setCreateTime(DateUtils.now());
        entity.setMark(1);
        boolean result = this.save(entity);
        if (!result) {
            return JsonResult.error();
        }
        return JsonResult.success();
    }

    /**
     * 传入实体对象更新记录
     *
     * @param entity 实体对象
     * @return
     */
    @Override
    public JsonResult update(T entity) {
        entity.setUpdateUser(SecurityUtils.getUserId());
        entity.setUpdateTime(DateUtils.now());
        boolean result = this.updateById(entity);
        if (!result) {
            return JsonResult.error();
        }
        return JsonResult.success();
    }

    /**
     * 根据实体对象添加、编辑记录
     *
     * @param entity 实体对象
     * @return
     */
    @Override
    public JsonResult edit(T entity) {
        if (entity == null) {
            return JsonResult.error("实体对象不存在");
        }
        if (entity.getId() != null && entity.getId() > 0) {
            // 修改记录
            return this.update(entity);
        } else {
            // 新增记录
            return this.add(entity);
        }
    }

    /**
     * 删除记录
     *
     * @param entity 实体对象
     * @return
     */
    @Override
    public JsonResult delete(T entity) {
        entity.setUpdateUser(SecurityUtils.getUserId());
        entity.setUpdateTime(DateUtils.now());
        entity.setMark(0);
        boolean result = this.updateById(entity);
        if (!result) {
            return JsonResult.error();
        }
        return JsonResult.success("删除成功");
    }

    /**
     * 根据ID删除记录
     *
     * @param id 记录ID
     * @return
     */
    @Override
    public JsonResult deleteById(Integer id) {
        if (id == null || id == 0) {
            return JsonResult.error("记录ID不能为空");
        }
        // 设置Mark=0
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.set("mark", 0);
        updateWrapper.eq("id", id);
        boolean result = update(updateWrapper);
        if (!result) {
            return JsonResult.error();
        }
        return JsonResult.success("删除成功");
    }

    /**
     * 根据ID删除记录
     *
     * @param ids 记录ID
     * @return
     */
    @Override
    public JsonResult deleteByIds(Integer[] ids) {
        if (StringUtils.isNull(ids)) {
            return JsonResult.error("记录ID不能为空");
        }
        // 设置Mark=0
        Integer totalNum = 0;
        for (Integer id : ids) {
            UpdateWrapper updateWrapper = new UpdateWrapper();
            updateWrapper.set("mark", 0);
            updateWrapper.eq("id", id);
            boolean result = update(updateWrapper);
            if (result) {
                totalNum++;
            }
        }
        if (totalNum != ids.length) {
            return JsonResult.error();
        }
        return JsonResult.success("删除成功");
    }

    /**
     * 设置状态
     *
     * @param entity 实体对象
     * @return
     */
    @Override
    public JsonResult setStatus(T entity) {
        return this.update(entity);
    }

    /**
     * 导出Excel
     *
     * @return
     */
    @Override
    public List<T> exportExcel() {
        return null;
    }
}


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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231