• 苍穹外卖(二)新增员工及项目细节


    我们实现员工管理功能:

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

    员工管理效果:

    员工管理效果: 

    1. 新增员工

    1.1 需求分析和设计 

    接口设计

     

    明确新增员工接口的请求路径、请求方式、请求参数、返回数据

    表设计

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

    1.2 代码开发 

    1.2.1 设计DTO类

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

    前端传递参数列表:

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

     

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

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

     

    1.2.2 Controller层

    EmployeeController中创建新增员工方法

    1. /**
    2. * 新增员工
    3. * @param employeeDTO
    4. * @return
    5. */
    6. @PostMapping
    7. @ApiOperation("新增员工")
    8. public Result save(@RequestBody EmployeeDTO employeeDTO){
    9. log.info("新增员工:{}",employeeDTO);
    10. employeeService.save(employeeDTO);//该方法后续步骤会定义
    11. return Result.success();
    12. }

    1.2.3 Service层接口

    在EmployeeService接口中声明新增员工方法

    1.2.4 Service层实现类

    在EmployeeServiceImpl中实现新增员工方法

    1. /**
    2. * 新增员工
    3. *
    4. * @param employeeDTO
    5. */
    6. public void save(EmployeeDTO employeeDTO) {
    7. Employee employee = new Employee();
    8. //对象属性拷贝
    9. BeanUtils.copyProperties(employeeDTO, employee);
    10. //设置账号的状态,默认正常状态 1表示正常 0表示锁定
    11. employee.setStatus(StatusConstant.ENABLE);
    12. //设置密码,默认密码123456
    13. employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
    14. //设置当前记录的创建时间和修改时间
    15. employee.setCreateTime(LocalDateTime.now());
    16. employee.setUpdateTime(LocalDateTime.now());
    17. //设置当前记录创建人id和修改人id
    18. employee.setCreateUser(10L);//目前写个假数据,后期修改
    19. employee.setUpdateUser(10L);
    20. employeeMapper.insert(employee);//后续步骤定义
    21. }

     

    1.2.5 Mapper层

    在EmployeeMapper中声明insert方法

    1. /**
    2. * 插入员工数据
    3. * @param employee
    4. */
    5. @Insert("insert into employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user,status) " +
    6. "values " +
    7. "(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")
    8. void insert(Employee employee);

     

    细节一 :  @Data

    使用lombok简化操作 

    只需要加入下面依赖 就可以达成操作

     

    细节二:  Mybatis

    (1) 在Sky_take_out数据库中建立employee表

    (2) 在Springboot工程中引入起步依赖 

    application.yml文件中配置数据库连接信息

    (3) Mapper中以注解方式编写SQL语句

    完成引入mybatis操作

    注意 : 若以XML方式配置映射文件须遵守一下要求 

    细节三: @ConfigurationProperties

    当我们把四个参数传给yml属性配置文件进行集中的配置管理

    如果我们想在工具类中使用这四个参数就要在类中变量上加上注解 来注入这四个参数

    但这样无疑很繁琐

    @Component: 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。

     

    改进办法:

            使用@ConfigurationProperties注解来指定前缀

    条件: 

            1. yml 文件和类中变量名必须一致

            2. 加入@Data注解 方便调用类中变量, 设置类中变量

            3. 加入@Component 将这个类交给IOC容器管理

            4. 加入@ConfigurationProperties  补全前缀

     

     改进结果:

            只在对象上需要加上@Autowired  注入上面这个Bean对象,  再调用 Get()方法就可拿到参数值

    两种方法对比:

    @Component
    @ConfigurationProperties(prefix = "sky.jwt")
    @Data
    public class JwtProperties {
    
        /**
         * 管理端员工生成jwt令牌相关配置
         */
        private String adminSecretKey;
        private long adminTtl;
        private String adminTokenName;
    
        /**
         * 用户端微信用户生成jwt令牌相关配置
         */
        private String userSecretKey;
        private long userTtl;
        private String userTokenName;
    
    }

     细节四: ThreadLocal

     描述:新增员工时,创建人id和修改人id设置为固定值

    1. //当前设置的id为固定值10//
    2. employee.setCreateUser(10L);
    3. employee.setUpdateUser(10L);
    4. //

    解决:

    通过某种方式动态获取当前登录员工的id。

     

    员工登录成功后会生成JWT令牌并响应给前端: 

    1. claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
    2. String token = JwtUtil.createJWT(
    3. jwtProperties.getAdminSecretKey(),
    4. jwtProperties.getAdminTtl(),
    5. claims);

     

    后续请求中,前端会携带JWT令牌,通过JWT令牌可以解析出当前登录员工id:

    JwtTokenAdminInterceptor.java

    1. Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
    2. Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());

     **思考:**解析出登录员工id后,如何传递给Service的save方法?

     

    答 : ThreadLocal

    介绍:

    ThreadLocal 并不是一个Thread,而是Thread的局部变量。 ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。

    常用方法:

    • public void set(T value) 设置当前线程的线程局部变量的值
    • public T get() 返回当前线程所对应的线程局部变量的值
    • public void remove() 移除当前线程的线程局部变量

    对ThreadLocal有了一定认识后,接下来继续解决问题

    在拦截器中解析出当前登录员工id,并放入线程局部变量中: 

    1. public class JwtTokenAdminInterceptor implements HandlerInterceptor {
    2. @Autowired
    3. private JwtProperties jwtProperties;
    4. /**
    5. * 校验jwt
    6. */
    7. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    8. //.............................
    9. //2、校验令牌
    10. try {
    11. //.................
    12. Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
    13. Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
    14. log.info("当前员工id:", empId);
    15. /将用户id存储到ThreadLocal
    16. threadLocal.set(empId);
    17. //3、通过,放行
    18. return true;
    19. } catch (Exception ex) {
    20. //......................
    21. }
    22. }
    23. }

     在Service中获取线程局部变量中的值:

    1. /**
    2. * 新增员工
    3. *
    4. * @param employeeDTO
    5. */
    6. public void save(EmployeeDTO employeeDTO) {
    7. //.............................
    8. //设置当前记录创建人id和修改人id
    9. employee.setCreateUser(threadLocal.get());//目前写个假数据,后期修改
    10. employee.setUpdateUser(threadLocal.get());
    11. employeeMapper.insert(employee);
    12. }

     

  • 相关阅读:
    Nacos从0到1(基础篇)
    Opencv中使用Tracker实现物体跟踪
    windows下VS配置NISwGSP
    设置电脑定时关机
    安装CDH配置本地CM、CDH源时,配置Apache Web服务器一直显示403看不到目录
    图像二值化阈值调整——Triangle算法,Maxentropy方法
    TCP/IP(六)TCP的连接管理(三)
    Kotlin高仿微信-第17篇-单聊-转账
    第五届“传智杯”全国大学生计算机大赛(练习赛)[传智杯 #5 练习赛] 时钟
    2023亚太杯数学建模思路 - 案例:最短时间生产计划安排
  • 原文地址:https://blog.csdn.net/weixin_47786582/article/details/133808208