苍穹外卖-day02

HM大约 36 分钟苍穹外卖拦截器PageHelper自定义异常MD5JWT

苍穹外卖-day02

课程内容

  • 新增员工
  • 员工分页查询
  • 启用禁用员工账号
  • 编辑员工
  • 导入分类模块功能代码

任务

功能实现 :员工管理、菜品分类管理🎯。

管理端原型open in new window

用户端原型open in new window

员工管理效果:

image-20221112172846316

1. 新增员工 🚩

1.1 需求分析和设计和编码

需求分析和设计

产品原型

一般在做需求分析时,往往都是对照着产品原型进行分析,因为产品原型比较直观,便于我们理解业务。

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

新增员工原型:

image-20221111161120975

当填写完表单信息, 点击"保存"按钮后, 会提交该表单的数据到服务端, 在服务端中需要接受数据, 然后将数据保存至数据库中。

注意事项: 👇

  1. 账号必须是唯一的
  2. 手机号为合法的11位手机号码
  3. 身份证号为合法的18位身份证号码
  4. 密码默认为123456

1.2 代码开发 👇 👇

1.2.1 设计DTO类

根据新增员工接口设计对应的DTO

前端传递参数列表:

image-20221111164002448

思考: 是否可以使用对应的实体类来接收呢?

image-20221111164453341

注意: 当前端提交的数据和实体类中对应的属性差别比较大时,建议使用DTO来封装数据 ⚠️

由于上述传入参数和实体类有较大差别,所以自定义DTO类。

进入sky-pojo模块,在com.sky.dto包下,已定义EmployeeDTO

package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class EmployeeDTO implements Serializable {
    //Serializable 是序列化接口
    private Long id;
    private String username;
    private String name;
    private String phone;
    private String sex;
    private String idNumber;

}

总结

课堂作业

  1. DTO实体类数据怎么传递到Entity实体类🎤
  2. 前端传递的实体类数据,还需要补充什么信息才能存到数据库表中?

1.2 代码完善

完善下列问题

目前,程序存在的问题主要有两个: 👇👇

  • 录入的用户名已存,抛出的异常后没有处理
  • 新增员工时,创建人id和修改人id设置为固定值

1.4.1 用户名已存在问题

描述: 录入的用户名已存,抛出的异常后没有处理

分析:

新增username=zhangsan的用户,若employee表中之前已存在。

image-20221111193700895

后台报错信息:

image-20221111194049620

查看employee表结构:

image-20221111194131787

发现,username已经添加了唯一约束,不能重复。

解决:

通过全局异常处理器来处理。🎯

进入到sky-server模块,com.sky.hander包下,GlobalExceptionHandler.java添加方法

	/**
     * 处理SQL异常
     * @param ex
     * @return
     */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
        //Duplicate entry 'zhangsan' for key 'employee.idx_username'
        String message = ex.getMessage();
        if(message.contains("Duplicate entry")){
            String[] split = message.split(" ");
            String username = split[2];
            String msg = username + MessageConstant.ALREADY_EXISTS;
            return Result.error(msg);
        }else{
            return Result.error(MessageConstant.UNKNOWN_ERROR);
        }
    }








 
 
 
 
 
 




进入到sky-common模块,在MessageConstant.java添加

public static final String ALREADY_EXISTS = "已存在";

再次,接口测试:

image-20221111195521095

总结

课堂作业

  1. 1.独立的绘制新增员工的流程图,并且根据流程图编写代码

流程图绘制可以使用博思白板

2. 员工分页查询 🚩

2.1 需求分析和设计

需求分析和设计

2.1.1 产品原型

  1. 系统中的员工很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看
  2. 员工列表显示还有一个查询条件 员工姓名

➡️使用分页显示列表数据,并且添加查询条件 🎯

查询员工原型:

image-20221111215309289

业务规则

  • 根据页码展示员工信息
  • 每页展示10条数据
  • 分页查询时可以根据需要,输入员工姓名进行查询

2.2 代码开发 👇👇

步骤

  1. 设计DTO类
  2. 封装PageResult
  3. Controller层
  4. Service层接口
  5. Service层实现类
  6. Mapper层

2.2.1 设计DTO类

根据请求参数进行封装,在sky-pojo模块中

package com.sky.dto;
import lombok.Data;
import java.io.Serializable;

@Data
public class EmployeePageQueryDTO implements Serializable {
    //员工姓名
    private String name;
    //页码
    private int page;
    //每页显示记录数
    private int pageSize;

}

总结

课堂作业

  1. 分页查询中前端应该传递什么参数给后端,后端应该返回什么数据给前端?🎤

2.2 代码完善

解决字段不显示的问题

问题描述: 操作时间字段显示有问题。

image-20221112103235539

解决方式:

1). 方式一

在属性上加上注解,对日期进行格式化

image-20221112103501581

但这种方式,需要在每个时间属性上都要加上该注解,使用较麻烦,不能全局处理

总结

课堂作业

  1. 常用的时间格式有哪些?🎤
  2. SpringMVC的消息转换器的作用是什么?🎤

3. 启用禁用员工账号 🚩

3.1 需求分析与设计

需求分析与设计

3.1.1 产品原型

  1. 在员工管理列表页面,可以对某个员工账号进行启用或者禁用操作。
  2. 账号禁用的员工不能登录系统,启用后的员工可以正常登录。业务逻辑
  3. 如果某个员工账号状态为正常,则按钮显示为 "禁用",如果员工账号状态为已禁用,则按钮显示为"启用"。前端显示

启禁用员工原型:

image-20221112112359233

业务规则:

  • 可以对状态为“启用” 的员工账号进行“禁用”操作
  • 可以对状态为“禁用”的员工账号进行“启用”操作
  • 状态为“禁用”的员工账号不能登录系统

3.2 代码开发 👇 👇

3.2.1 Controller层

在sky-server模块中,根据接口设计中的请求参数形式对应的在 EmployeeController 中创建启用禁用员工账号的方法:

	/**
     * 启用禁用员工账号
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("启用禁用员工账号")
    public Result startOrStop(@PathVariable Integer status,Long id){
        log.info("启用禁用员工账号:{},{}",status,id);
        employeeService.startOrStop(status,id);//后绪步骤定义
        return Result.success();
    }










 


总结

课堂作业

  1. 禁用员工是删除员工吗?🎤
  2. 禁用后的员工可以正常登录吗?🎤
  3. 是否是任何人都可以禁用员工?🎤

4. 编辑员工 🚩

4.1 需求分析与设计

需求分析与设计

4.1.1 产品原型

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

员工列表原型:

image-20221112144731759

修改页面原型

注:点击修改时,数据应该正常回显到修改页面。

image-20221112144842825

代码开发 👇 👇

4.2.1 回显员工信息功能

1). Controller层

在 EmployeeController 中创建 getById 方法:

	/**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询员工信息")
    public Result<Employee> getById(@PathVariable Long id){
        Employee employee = employeeService.getById(id);
        return Result.success(employee);
    }

4.2.2 修改员工信息功能 👇👇

1). Controller层

在 EmployeeController 中创建 update 方法:

	/**
     * 编辑员工信息
     * @param employeeDTO
     * @return
     */
    @PutMapping
    @ApiOperation("编辑员工信息")
    public Result update(@RequestBody EmployeeDTO employeeDTO){
        log.info("编辑员工信息:{}", employeeDTO);
        employeeService.update(employeeDTO);
        return Result.success();
    }

总结

课堂作业

  1. 修改员工和增加员工,使用同样的EmployeeDTO对象,区别在哪?🎤

5. 导入分类模块功能代码 🚩

5.1 需求分析与设计

需求分析与设计

5.1.1 产品原型

后台系统中可以管理分类信息,分类包括两种类型,分别是 菜品分类套餐分类

先来分析菜品分类相关功能。

新增菜品分类: 当我们在后台系统中添加菜品时需要选择一个菜品分类,在移动端也会按照菜品分类来展示对应的菜品。

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

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

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

启用禁用菜品分类: 在分类管理列表页面,可以对某个分类进行启用或者禁用操作。

分类类型查询: 当点击分类类型下拉框时,从数据库中查询所有的菜品分类数据进行展示。

分类管理原型:

image-20221112160907419

业务规则:

  • 分类名称必须是唯一的
  • 分类按照类型可以分为菜品分类和套餐分类
  • 新添加的分类状态默认为“禁用”

=

代码导入

导入资料中的分类管理模块功能代码即可

image-20221112164259732

可按照mapper-->service-->controller依次导入,这样代码不会显示相应的报错。

进入到sky-server模块中

Controller层

CategoryController.java

package com.sky.controller.admin;

import com.sky.dto.CategoryDTO;
import com.sky.dto.CategoryPageQueryDTO;
import com.sky.entity.Category;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.CategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

/**
 * 分类管理
 */
@RestController
@RequestMapping("/admin/category")
@Api(tags = "分类相关接口")
@Slf4j
public class CategoryController {

    @Autowired
    private CategoryService categoryService;

    /**
     * 新增分类
     * @param categoryDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增分类")
    public Result<String> save(@RequestBody CategoryDTO categoryDTO){
        log.info("新增分类:{}", categoryDTO);
        categoryService.save(categoryDTO);
        return Result.success();
    }

    /**
     * 分类分页查询
     * @param categoryPageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("分类分页查询")
    public Result<PageResult> page(CategoryPageQueryDTO categoryPageQueryDTO){
        log.info("分页查询:{}", categoryPageQueryDTO);
        PageResult pageResult = categoryService.pageQuery(categoryPageQueryDTO);
        return Result.success(pageResult);
    }

    /**
     * 删除分类
     * @param id
     * @return
     */
    @DeleteMapping
    @ApiOperation("删除分类")
    public Result<String> deleteById(Long id){
        log.info("删除分类:{}", id);
        categoryService.deleteById(id);
        return Result.success();
    }

    /**
     * 修改分类
     * @param categoryDTO
     * @return
     */
    @PutMapping
    @ApiOperation("修改分类")
    public Result<String> update(@RequestBody CategoryDTO categoryDTO){
        categoryService.update(categoryDTO);
        return Result.success();
    }

    /**
     * 启用、禁用分类
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("启用禁用分类")
    public Result<String> startOrStop(@PathVariable("status") Integer status, Long id){
        categoryService.startOrStop(status,id);
        return Result.success();
    }

    /**
     * 根据类型查询分类
     * @param type
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据类型查询分类")
    public Result<List<Category>> list(Integer type){
        List<Category> list = categoryService.list(type);
        return Result.success(list);
    }
}

课后作业

🚩 1. 重点完成上述的课堂作业

  1. 晚自习第一节课的前30分钟,总结完毕之后,每个同学先必须梳理今日知识点 (记得写不知道的,以及感恩三件事);整理好的笔记可以发给组长,组长交给班长,意在培养大家总结的能力)

  2. 晚自习第一节课的后30分钟开始练习(记住:程序员是代码堆起来的):

  3. 剩余的时间:预习第二天的知识,预习的时候一定要注意:

  • 预习不是学习,不要死看第二天的视频(很容易出现看了白看,为了看视频而看视频)
  • 预习看第二天的笔记,把笔记中标注重要的知识,可以找到预习视频,先看一遍,如果不懂的 ,记住做好标注。

结构化面试题

1. 谈谈ThreadLocal的使用

ThreadLocal是Java中的线程本地变量,用于在多线程环境下存储每个线程独有的数据,解决多线程访问共享数据的线程安全问题。

在多线程环境中,如果需要在一个线程中存储数据,以便其他方法或组件能够访问,可以使用ThreadLocal。例如,在Web应用中,可以将当前用户信息存储在ThreadLocal中,确保在同一线程内的任何地方都可以方便地获取到。

  1. 那你了解ThreadLocal底层实现原理吗?
    • 这个了解。每个线程内都有一个ThreadLocalMap集合,用于存储当前线程内共享数据,而这个ThreadLocal就是这个Map的key,value就是要共享的数据。如果要存储数据,就调用ThreadLocal的set()方法,set()方法就是到ThreadLocalMap,以ThreadLocal为key去put值。要获取数据的话,就调用ThreadLocal的get()方法,而get()方法就是以ThreadLocal为key去当前线程的ThreadLocalMap中获取数据。

2. 谈谈SpringMvc消息转换器的应用

Spring MVC消息转换器是用于在HTTP请求和响应之间进行Java对象和数据格式(如JSON、XML)之间的转换,解决前后端数据交互的问题。

在一个前后端分离的应用中,前端通过Ajax请求发送JSON数据到后端,Spring MVC消息转换器可以将JSON数据转换成Java对象,同时也能将Java对象转换成JSON数据返回给前端。

  1. Spring MVC消息转换器的默认支持哪些数据格式?

    • Spring MVC消息转换器默认支持JSON、XML、表单数据等格式。
  2. 如何自定义消息转换器?

    • 可以通过继承AbstractHttpMessageConverter类或实现HttpMessageConverter接口来自定义消息转换器。然后,在Spring配置中注册这个自定义的消息转换器。
  3. 你在项目中的哪些场景使用了消息转换器?

    • 例如,在RESTful API的开发中,使用JSON格式进行前后端数据的传输。通过配置消息转换器,能够自动将Controller的方法返回的Java对象转换成JSON格式响应给客户端。

3. 谈谈员工禁用的实践

员工禁用是一种管理实践,用于在企业中有效管理离职、暂时不可用或其他状态的员工,以确保系统安全和资源合理利用。

在人力资源管理系统中,员工离职或暂时不可用时,可以通过禁用员工账号的方式来限制其对系统资源的访问,以保障公司信息的安全性。

  1. 你在实际项目中如何实现员工禁用?

    • 在数据库中通常会有一个字段标识员工的状态,例如"离职"、"在职"等。通过在系统中进行合适的权限控制,禁用员工账号后,系统将不再允许其登录或执行敏感操作。
  2. 禁用员工有哪些潜在的风险?

    • 一些潜在风险包括未及时更新员工状态可能导致系统安全问题,以及在某些情况下可能会引起业务流程中断。因此,需要合理设计禁用流程,并确保相关的业务逻辑与权限管理得到有效实施。
  3. 如何处理员工禁用后的数据隐私和保密问题?

    • 在员工禁用的流程中,需要考虑合规性问题,例如清理或加密员工的敏感信息,以确保数据隐私和保密性。同时,确保相关操作符合法规和公司政策。
上次编辑于:
贡献者: huhu520,yange