前言
此项目为仓库管理系统,是我大二下的实训课作业,虽然是从学期初开始写的,但是实际写项目的日子也就十多天(前面都没怎么动,果然只有临近ddl效率才高)。
到我写这篇博文的时候,实际上项目还有小部分功能未完成,当然如果你不是逐个试过去你是发现不了的(笑哭)。
说实话,我实在不想在未完成前写类似实验报告的文档,而且我也不喜欢写文档。我一直认为写项目根本不需要那么多死板的文档(反正也只是作业)。
有人可能又会奇怪我不喜欢写文档为啥写那么多博文?这个嘛,我写博文的目的也只是想把我彼时彼刻的情感和经验分享出来,我更倾向于那种随性的分享,不想循规蹈矩的写那些死板的文档。
挺不喜欢那些老师每次要做项目都得要我们交各种图,各种功能业务表。那些图对于那些简单的项目还可以,毕竟不复杂,但是对于一个稍微大点的项目,光代码就一大堆,画那些业务图要画到猴年马月去?
有时候,围绕着一个增删改查的小项目大谈架构,这并不是一个明智的选择。
…
好了,碎碎念了这么多,实在抱歉,下面是正文:
一、项目概述
1.项目需求
实现材料仓库的管理:提供材料出入库管理等实用功能。 材料入库管理:材料检验入库、入库查询、入库类别按月统计;
材料出库管理:材料库存查询、材料出库、出库查询、出库类别按月统计; 辅助管理:仓库系统的人员管理、基础表的管理。
当然啦,以上只是简单的需求,多的我也不展示了。
2.总述
此项目为Javaweb项目,前后端不分离,典型的单体架构,主要功能是对仓库转入转出等业务进行管理,并对数据进行可视化展示,同时有部分权限管理的功能(为什么这么说呢,因为我这部分做的并不严谨,如果后面有时间我会尽可能完善)。
3.技术栈选择
前端:layui、jquery、echarts、thymeleaf模板引擎
后端:mysql、maven、tomcat、mybatis、springMVC、spring、SpringBoot、logback
注意:这里的前端页面我拿了gitee上的开源模板layui-mini,地址。
4.环境介绍
数据库:mysql8.0
项目结构:maven
数据库连接池:Druid
前端框架:layui、jquery、echarts、thymeleaf模板引擎
后端框架:SpringBoot、SSM
语言:Java
jdk版本:8
编写的IDE:IDEA
5.效果图展示
为了更直观的展示项目,这里先放几张效果图
二、设计思路
在说明自己的设计思路之前,我们先来看看一般意义上的SSM项目的架构图
1.SSM项目(单体架构)示意图
由上图可以看到SSM项目中大致的组成。
一般的SSM应用都会分三层——数据库层,业务层,控制层,而我们这个仓库信息管理系统也是如此。
2.前后端交互示意图
有人可能不太明白SSMweb应用是如何进行前后端交互的,因此我又补充了交互的部分,如下图:
前后端的交互都以HTTP请求展开的。有些请求是请求页面的;有些请求是请求静态资源的,如css文件,图片等;有些请求是请求数据的,比如出入库记录。
下面是三层调用的细节示意图
上图中我们可以直观的看到SSM项目的基本运行流程。
当请求到来时,先会经过拦截器链,拦截器利用反射机制实现了对请求处理和返回的处理,可以利用它来实现鉴权服务和权限控制。
之后请求分发,对应的请求会有对应处理程序来处理,而这就是Controller控制层的工作,而控制层也会调用相应的业务层方法来进行操作或者返回对应的静态资源、页面等。
Service业务层专门处理业务层面的操作,比如入库,出库,出库成功会创建相应的申请记录同时改变库存数据,至于如何改变,如何增加这是数据库层的事情,在这层只需调用对应的Dao层方法即可。而有些操作需要保证失败回滚的机制,所以可以在Service层开启事务功能。
Dao层通常与数据库中的表一一对应,一般都是去实现增删改查,而mybatis框架将sql语句和程序分离,极大简化了我们的开发。
3.仓库管理系统架构图
在看完了SSM单体项目一般是如何架构之后,再来看看我们的系统架构图(由于业务比较少,所以这里可以直接把各个类写到上面)
和上面的大差不差,只不过这里利用拦截器实现了token机制来进行三级权限控制,同时多用了点spring的aop来处理日志信息,以及利用增强Controller来处理全局异常信息,返回对应的错误响应。
4.响应格式
对于前后端分离的项目,响应格式必定是前后端交流非常重要的一环。虽说这里并不是前后端分离开发,但为了规范,还是规定了请求响应的格式。
status:状态码
statusInfo:{ message:字段作为接口处理失败时, 给予用户的友好的提示信息, 即所有给用户的提示信息都统一由后端来处理 detail:字段用来放置接口处理失败时的详细错误信息. 只是为了方便排查错误, 前端无需使用. } data:返回的数据 count:分页请求数据时使用的参数,意为有多少数据
5.异常处理机制
利用增强Controller的机制来处理全局的异常,然后返回给前端对应的错误响应,如:
6.日志记录机制
利用spring的aop机制,我们可以轻松的在controller接口处理请求之前打印请求的相关信息到日志文件中。
7.鉴权服务设计与实现
关于此系统的鉴权服务,也就是我们常说的注册登录,我用的是自己实现的一套简单的token机制,示意图如下:
简而言之,用户登录后会进行校验密码(为了安全期间,数据库中的密码是经过加密存储的,所以比对时我们也会对密码加密再进行比对),校验通过会给前端一个token令牌的凭证(实际上是根据登录用户名,如邮箱,以当前时间作为盐进行MD5加密后返回的一串字符串)。
该令牌会存储在系统的认证令牌池中,而用户得到的用户凭证会被存储在浏览器的cookie中。
用户每次访问系统资源时,请求头里都会携带token凭证,而每次请求(登录请求,发送验证码等特殊请求除外)都会被userIntercepter拦截器拦截,该拦截器会取出请求中的token凭证,然后去和认证令牌池中校验。如果有且未过期,则放行,同时将该认证令牌放入到请求的Atribute中以便后面的程序处理;否则重定向回登录页面让用户进行登录操作。
关于这个鉴权服务,我写过另一篇博文——手把手教你用Java实现一套简单的鉴权服务(SpringBoot,SSM)(万字长文),有兴趣可以去看看。
8.业务功能简述
该系统主要的就是模拟仓库出入库的流程,所以我把用户的角色氛围普通用户、审核员、仓管员和系统管理员。
普通用户可以填写出入库申请进行制单,然后相应的审核人进行审核,审核员可以指定该仓库的仓管员进行验收,或者审核不通过;当审核成功,货物成功到达仓库时,仓库员进行验收操作,如果验收通过,则成功入库或者出库,相应的库存信息也发生变化。
系统管理员可以管理网站用户,同时发布网站公告。(这个角色权限管理的部分我还没完成,目前所有用户都可以操作所有功能)
除此之外,我还对与一些出入库申请、库存、仓库等信息进行查询和可视化的操作,让仓库管理员可以更直观的看到仓库信息的变化。
三、数据库设计
1.数据库模型设计概览
2.数据库表设计
①depository
描述: 该表存储仓库的信息,比如仓库名称,仓库地址和仓库介绍
表结构:
序号 | 字段名 | 数据类型 | 主键 | 非空 | 默认值 | 描述 |
1 | id | INT(10) | 是 | 是 | 仓库id |
2 | dname | VARCHAR(255) | 否 | 是 | 仓库名称 | |
3 | address | VARCHAR(255) | 否 | 是 | 仓库地址 | |
4 | introduce | VARCHAR(255) | 否 | 是 | 仓库介绍 |
②仓库调度记录(depository_record)
描述: 该表记录仓库调度的记录,同时该表也是数据也可以看做一条条申请信息。
表结构:
序号 | 字段名 | 数据类型 | 主键 | 非空 | 默认值 | 描述 |
1 | id | INT(10) | 是 | 是 | 记录id | |
2 | application_id | INT(10) | 否 | 否 | 申请编号(暂时无用) | |
3 | mname | VARCHAR(255) | 否 | 是 | 产品名称 |
4 | depository_id | INT(10) | 否 | 是 | 调度的仓库id | |
5 | type | INT(10) | 否 | 是 | 0 | 调度记录类型(0出库,1入库) |
6 | quantity | DOUBLE(22) | 否 | 否 | 数量 |
7 | price | DOUBLE(22) | 否 | 否 | 价格 | |
8 | state | VARCHAR(255) | 否 | 否 | 状态(待审核/审核未通过,未入库/出库/检验不通过,待验收/已入库/已出库) | |
9 | applicant_id | INT(10) | 否 | 否 | 申请人id |
10 | apply_remark | VARCHAR(255) | 否 | 否 | 申请备注 | |
11 | apply_time | DATETIME | 否 | 否 | 申请时间 | |
12 | reviewer_id | INT(10) | 否 | 否 | 审核人id | |
13 | review_remark | VARCHAR(255) | 否 | 否 | 审核结果备注 |
14 | review_time | DATETIME | 否 | 否 | 审核时间 | |
15 | review_pass | INT(10) | 否 | 否 | 审核是否通过,0表示未通过,1表示通过 | |
16 | checker_id | INT(10) | 否 | 否 | 验货人id |
17 | check_remark | VARCHAR(255) | 否 | 否 | 验收备注 | |
18 | check_time | DATETIME | 否 | 否 | 出入库时间(验货时间) | |
19 | check_pass | INT(10) | 否 | 否 | 验收是否通过 |
3、产品信息记录(库存)(material)
描述: 产品信息记录(库存信息)
表结构:
序号 | 字段名 | 数据类型 | 主键 | 非空 | 默认值 | 描述 |
1 | id | INT(10) | 是 | 是 | 存储id |
2 | depository_id | INT(10) | 否 | 否 | 仓库名称 | |
3 | mname | VARCHAR(255) | 否 | 否 | 材料名称 |
4 | quantity | DOUBLE(22) | 否 | 否 | 数量 | |
5 | price | DOUBLE(22) | 否 | 否 | 总金额 | |
6 | type_id | INT(10) | 否 | 否 | 材料种类id |
4、material_type
描述: 材料种类,我对材料进行了分类,这样统计起来也方便很多,另外建一个表是为了防止以后可能会对材料类型做的补充,同时节省存储空间。
表结构:
序号 | 字段名 | 数据类型 | 主键 | 非空 | 默认值 | 描述 |
1 | id | INT(10) | 是 | 是 | 类型id |
2 | tname | VARCHAR(255) | 否 | 是 | 类型名称 | |
3 | introduce | VARCHAR(255) | 否 | 否 | 类型介绍 |
5.notice
描述: 公告表,用于存储公告信息
表结构:
序号 | 字段名 | 数据类型 | 主键 | 非空 | 默认值 | 描述 |
1 | id | INT(10) | 是 | 是 | 公告主键 |
2 | title | VARCHAR(255) | 否 | 是 | 公告标题 | |
3 | content | VARCHAR(255) | 否 | 否 | 公告内容 |
4 | time | DATETIME | 否 | 是 | 发布时间 |