config里放配置文件,entity包里放实体类,resources里放管理端和用户端的静态页面等文件,common放通用类和全局异常处理器,filter放过滤器。

后台登录功能

需求分析

前端的login.html中的登录功能,要求服务端处理完登录的账号、密码后,给前端响应的数据里应当含有code,data,msg。而且数据的格式应该是jason格式

点击登录按钮,请求地址是http://localhost:8080/employee/login

POST请求方式

成功登录后,本地浏览器缓存中由employee的数据

代码开发

(1)创建实体类Employee,和数据库中的employee表进行映射。

(2)创建出大致结构。

EmployeeMapper接口

EmployeeService接口

EmployeeServiceImpl实现类

EmployeeController

(3)导入返回结果类R

此类是一个通用类,服务端响应的所有结果最终都会包装成这种类型返回给前端页面。

(4)在Controller中创建登录方法

处理逻辑如下:

1、将页面提交的密码password进行md5加密处理

2、根据页面提交的用户名username查询数据库

3、如果没有查询到则返回登录失败结果

4、密码比对,如果不一致则返回登录失败结果

5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果

6、登录成功,将员工id存入Session并返回登录成功结果

后台退出功能

需求分析

员工登录成功后,页面跳转系统首界面(/backend/index.html),此时会显示当前用户的姓名。

如果员工需要退出系统,直接点击右侧的退出按钮可以直接退出系统。退出系统后页面应该跳转到登录界面(/backend//page/login/login.html)

代码开发

用户点击页面中退出按钮,发送请求,请求地址为/employee/logout,请求方式为POST。我们只需要在Controller中创建对应的处理方法即可,具体的处理逻辑:

1、清理Session中的用户id

2、返回结果

功能测试

退出登录后,页面跳转到登陆界面,并且浏览器缓存中的userinfo被清理

完善登录功能

问题分析

前面我们已经完成了后台系统的员工登录功能开发,但是还存在一个问题:用户如果不登录,直接访问系统首页面,照样可以正常访问

这种设计并不合理,我们希望看到的效果应该是,只有登录成功后才可以访问系统中的页面,如果没有登录则跳转到登录页面。那么,具体应该怎么实现呢?

答案就是使用过滤器或者拦截器,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面。

代码实现

实现步骤:

1、创建自定义过滤器LoginCheckFilter

2、在启动类上加入注解@ServletComponentScan

3、完善过滤器的处理逻辑

过滤器具体的处理逻辑如下:

1、获取本次请求的URI

2、判断本次请求是否需要处理

3、如果不需要处理,则直接放行

4、判断登录状态,如果已登录,则直接放行

5、如果未登录则返回未登录结果

新增员工

需求分析

后台系统中可以管理员工信息,通过新增员工来添加后台系统用户。

点击[添加员工]按钮跳转到新增页面,如下:

数据模型

新增员工,其实就是将我们新增页面录入的员工数据插入到employee表。

需要注意,employee表中对username字段加入了唯一约束,因为username是员工的登录账号,必须是唯一的。

employee表中的status字段已经设置了默认值1,表示正常

代码开发

先尝试在前端添加员工,这个请求以POST的方式发送到http://localhost:8080/employee

发送请求的参数是JSON格式的

在开发代码之前,需要梳理一下整个程序的执行过程:

1、页面发送ajax请求,将新增员工页面中输入的数据以json的形式提交到服务端

2、服务端Controller接收页面提交的数据并调用Service将数据进行保存

3、Service调用Mapper操作数据库,保存数据

前面的程序还存在一个问题,就是当我们在新增员工时输入的账号已经存在,由于employee表中对该字段加入了唯—约束,此时程序会抛出异常:

此时需要我们的程序进行异常捕获,通常有两种处理方式:

1、在Controller方法中加入try.catch进行异常捕获。但是这种方法不是很好,如果新增数据很多,那trycatch会写很多遍。下面的代码只是针对当前这一种情况来处理。

2、使用异常处理器进行全局异常捕获

员工信息分页查询

需求分析

系统中的员工很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。

代码开发

在开发代码之前,需要梳理一下整个程序的执行过程:

1、页面发送ajax请求,将分页查询参数(page、pagesize、name)提交到服务端

2、服务端Controller接收页面提交的数据并调用Service查询数据

3、Service调用Mapper操作数据库,查询分页数据

4、Controller将查询到的分页数据响应给页面

5、页面接收到分页数据并通过ElementUI的Table组件展示到页面上

(1)配置MybatisPlus分页插件

(2)分页查询

启用/禁用员工账户

需求分析

在员工管理列表页面,可以对某个员工账号进行启用或者禁用操作。账号禁用的员工不能登录系统,启用后的员工可以正常登录。

需要注意,只有管理员(admin用户)可以对其他普通用户进行启用、禁用操作,所以普通用户登录系统后启用、禁用按钮不显示。

在开发代码之前,需要梳理一下整个程序的执行过程:

1、页面发送ajax请求,将参数(id、 status)提交到服务端

2、服务端Controller接收页面提交的数据并调用Service更新数据

3、Service调用Mapper操作数据库

代码开发

update方法

启用、禁用员工账号,本质上就是一个更新操作,也就是对status状态字段进行操作在Controller中创建update方法,此方法是一个通用的修改员工信息的方法。

由于前端的js精度16位,而ID是19位,需要添加对象转换器。否则点击禁用/编辑按钮返回的id数据精度不够,无法在数据库匹配到,导致更改无效。

对象转换器

具体实现步骤:

1)提供对象转换器JacksonObjectMapper,基于Jackson进行Java对象到json数据的转换

2)在WebMvcConfig配置类中扩展Spring mvc的消息转换器,在此消息转换器中使用提供的对象转换器进行Java对象到json数据的转换

编辑员工信息

需求分析

在员工管理列表页面点击编辑按钮,跳转到编辑页面,在编辑页面回显员工信息并进行修改,最后点击保存按钮完成操作。

代码开发

在开发代码之前需要梳理一下操作过程和对应的程序的执行流程:

1、点击编辑按钮时,页面跳转到add.html,并在url中携带参数[员工id]

2、在add.html页面获取url中的参数[员工id]

3、发送ajax请求,请求服务端,同时提交员工id参数

4、服务端接收请求,根据员工id查询员工信息,将员工信息以json形式响应给页面

5、页面接收服务端响应的json数据,通过VUE的数据绑定进行员工信息回显

6、点击保存按钮,发送ajax请求,将页面中的员工信息以json方式提交给服务端

7、服务端接收员工信息,并进行处理,完成后给页面响应

8、页面接收到服务端响应信息后进行相应处理

注意: add.html页面为公共页面,新增员工和编辑员工都是在此页面操作

因为在编写禁用员工状态时,写了update方法,可以通用,这里编辑功能的实现就可以借用update方法实现。

分类管理

公共字段自动填充

需求分析

前面已经完成了后台系统的员工管理功能开发,在新增员工时需要设置创建时间、创建人、修改时间、修改人等字段,在编辑员工时需要设置修改时间和修改人等字段。这些字段属于公共字段,也就是很多表中都有这些字段,如下:

对于这些公共字段在某个地方统一处理,来简化开发——使用Mybatis Plus提供的公共字段自动填充功能。

代码开发

Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。

实现步骤:

1、在实体类的属性上加入@TableField注解,指定自动填充的策略

2、按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口

下图是已经解决了无法取得id后的代码(MyMetaObjectHandler.java)

功能完善:

createuser和updateuser

把controller中的新增员工类,设置公共字段改为自动填充。

新增分类

需求分析

后台系统中可以管理分类信息,分类包括两种类型,分别是菜品分类和套餐分类。当我们在后台系统中添加菜品时需要选择一个菜品分类,当我们在后台系统中添加一个套餐时需要选择一个套餐分类,在移动端也会按照菜品分类和套餐分类来展示对应的菜品和套餐。

数据模型

新增分类,其实就是将我们新增窗口录入的分类数据插入到category表,表结构如下:

代码开发

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

1、实体类Category

2、Mapper接口CategoryMapper

3、业务层接口CategoryService

4、业务层实现类CategoryServicelmpl控制层CategoryController

在开发代码之前,需要梳理一下整个程序的执行过程:

1、页面(backend/page/category/list.html)发送ajax请求,将新增分类窗口输入的数据以json形式提交到服务端

2、服务端Controller接收页面提交的数据并调用Service将数据进行保存

3、Service调用Mapper操作数据库,保存数据

可以看到新增菜品分类和新增套餐分类请求的服务端地址和提交的json数据结构相同,所以服务端只需要提供一个方法统—外理即可

分类信息分页查询

需求分析

系统中的分类很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。

代码开发

在开发代码之前,需要梳理一下整个程序的执行过程:

1、页面发送ajax请求,将分页查询参数(page.pageSize)提交到服务端

2、服务端Controller接收页面提交的数据并调用Service查询数据

3、Service调用Mapper操作数据库,查询分页数据

4、Controller将查询到的分页数据响应给页面

5、页面接收到分页数据并通过ElementUI的Table组件展示到页面上

删除分类

需求分析

在分类管理列表页面,可以对某个分类进行删除操作。需要注意的是当分类关联了菜品或者套餐时,此分类不允许删除。

代码开发

在开发代码之前,需要梳理一下整个程序的执行过程:

1、页面发送ajax请求,将参数(ids)提交到服务端

2、服务端Controller接收页面提交的数据并调用Service删除数据3、Service调用Mapper操作数据库

功能完善

前面我们已经实现了根据id删除分类的功能,但是并没有检查删除的分类是否关联了菜品或者套餐,所以我们需要进行功能完善。

要完善分类删除功能,需要先准备基础的类和接口:

1、实体类Dish和Setmeal

2、Mapper接口DishMapper和SetmealMapper

3、Service接口Dishservice和SetmealService

4、Service实现类DishServicelmpl和SetmealServicelmpl

判断是否关联:

抛出异常功能:

删除功能完善:

修改分类

需求分析

在分类管理列表页面点击修改按钮,弹出修改窗口回显分类信息并进行修改,最后点击确认按钮完成修改操作。

代码开发