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

我们实现员工管理功能:

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

员工管理效果:

员工管理效果: 苍穹外卖(二)新增员工及项目细节_第1张图片

1. 新增员工

苍穹外卖(二)新增员工及项目细节_第2张图片

1.1 需求分析和设计 

接口设计

 苍穹外卖(二)新增员工及项目细节_第3张图片苍穹外卖(二)新增员工及项目细节_第4张图片

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

表设计

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

1.2 代码开发 

1.2.1 设计DTO类

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

前端传递参数列表:

苍穹外卖(二)新增员工及项目细节_第5张图片

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

苍穹外卖(二)新增员工及项目细节_第6张图片 

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

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

 苍穹外卖(二)新增员工及项目细节_第7张图片

1.2.2 Controller层

EmployeeController中创建新增员工方法

/**
     * 新增员工
     * @param employeeDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增员工")
    public Result save(@RequestBody EmployeeDTO employeeDTO){
        log.info("新增员工:{}",employeeDTO);
        employeeService.save(employeeDTO);//该方法后续步骤会定义
        return Result.success();
    }

1.2.3 Service层接口

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

1.2.4 Service层实现类

在EmployeeServiceImpl中实现新增员工方法

/**
     * 新增员工
     *
     * @param employeeDTO
     */
    public void save(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();

        //对象属性拷贝
        BeanUtils.copyProperties(employeeDTO, employee);

        //设置账号的状态,默认正常状态 1表示正常 0表示锁定
        employee.setStatus(StatusConstant.ENABLE);

        //设置密码,默认密码123456
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));

        //设置当前记录的创建时间和修改时间
        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());

        //设置当前记录创建人id和修改人id
        employee.setCreateUser(10L);//目前写个假数据,后期修改
        employee.setUpdateUser(10L);

        employeeMapper.insert(employee);//后续步骤定义
    }

 

1.2.5 Mapper层

在EmployeeMapper中声明insert方法

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

 

细节一 :  @Data

使用lombok简化操作 

苍穹外卖(二)新增员工及项目细节_第8张图片

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

 苍穹外卖(二)新增员工及项目细节_第9张图片

细节二:  Mybatis

苍穹外卖(二)新增员工及项目细节_第10张图片

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

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

苍穹外卖(二)新增员工及项目细节_第11张图片

application.yml文件中配置数据库连接信息苍穹外卖(二)新增员工及项目细节_第12张图片

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

苍穹外卖(二)新增员工及项目细节_第13张图片

完成引入mybatis操作

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

苍穹外卖(二)新增员工及项目细节_第14张图片

细节三: @ConfigurationProperties

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

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

但这样无疑很繁琐

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

苍穹外卖(二)新增员工及项目细节_第15张图片

 苍穹外卖(二)新增员工及项目细节_第16张图片

改进办法:

        使用@ConfigurationProperties注解来指定前缀

条件: 

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

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

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

        4. 加入@ConfigurationProperties  补全前缀

苍穹外卖(二)新增员工及项目细节_第17张图片 

 改进结果:

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

苍穹外卖(二)新增员工及项目细节_第18张图片

两种方法对比:

苍穹外卖(二)新增员工及项目细节_第19张图片

@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设置为固定值

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

解决:

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

 苍穹外卖(二)新增员工及项目细节_第20张图片

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

        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

 

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

JwtTokenAdminInterceptor.java

            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            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有了一定认识后,接下来继续解决问题

苍穹外卖(二)新增员工及项目细节_第21张图片

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

public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 校验jwt
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        //.............................
        //2、校验令牌
        try {
            //.................
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
            log.info("当前员工id:", empId);
            /将用户id存储到ThreadLocal
            threadLocal.set(empId);
            
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //......................
        }
    }
}

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

 /**
     * 新增员工
     *
     * @param employeeDTO
     */
    public void save(EmployeeDTO employeeDTO) {
        //.............................

        //设置当前记录创建人id和修改人id
        employee.setCreateUser(threadLocal.get());//目前写个假数据,后期修改
        employee.setUpdateUser(threadLocal.get());

        employeeMapper.insert(employee);
    }

苍穹外卖(二)新增员工及项目细节_第22张图片 

你可能感兴趣的:(苍穹外卖总结,spring,mybatis,spring,boot)