itheima苍穹外卖项目学习笔记--Day2:员工管理和分类管理

苍穹外卖

  • Day2:
    • a. 员工管理
      • (1). 新增员工
        • 一. 代码完善
        • 二. 代码完善
      • (2). 员工分页查询
        • 一. 代码完善
      • (3). 启用禁用员工账号
      • (4). 编辑员工
        • 一. 根据id查询员工信息 (GET)
        • 二. 编辑员工信息 (POST)
    • b. 分类模块功能代码

Day2:

a. 员工管理

(1). 新增员工

  • 在EmployeeServiceImpl中,及其父类接口
/**
     * 新增员工
     * @param employeeDTO
     */
    @Override
    public void save(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();

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

        // 设置账号状态,默认正常
        employee.setStatus(StatusConstant.ENABLE);

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

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

        // 设置当前记录创建人id和修改人id
        // TODO 后期需要改为当前登录用户的Id
        employee.setCreateUser(10L);
        employee.setUpdateUser(10L);

        employeeMapper.insert(employee);
}
  • EmployeeMapper,写入相关SQL代码
/**
* 插入员工数据
* @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);
  • EmployeeController中,将DTO传入service类中进行处理
/**
* 新增员工
* @param employeeDTO
* @return
*/
@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO){
    log.info("新增员工: {}", employeeDTO);
    employeeService.save(employeeDTO);
    return Result.success();
}

注意:由于开发阶段前端和后端是并行开发的,后端完成某个功能后,此时前端对应的功能可能还没有开发完成,导致无法进行前后端联调测试。所以在开发阶段,后端测试主要以接口文档测试为主。

一. 代码完善

程序存在的问题:

  • 录入的用户名已存在,抛出异常后没有处理

解决方法:

  • GlobalExceptionHandler中,自定义一个处理SQL异常的方法
/**
* 处理SQL异常
* @param exception
* @return
*/
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException exception){
    // Duplicate entry 'zhangsan' for key 'idx_username'
    String message = exception.getMessage();
    if (message.contains("Duplicate entry")){
        String[] split = message.split(" ");
        String username = split[2];
        String msg = username.substring(1, username.length() - 1) + MessageConstant.ALREADY_EXISTS;
        return Result.error(msg);
    }else {
        return Result.error(MessageConstant.UNKNOWN_ERROR);
    }
}

二. 代码完善

程序存在的问题:

  • 新增员工时,创建人id和修改人id设置为了固定值

解决方法:

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

ThreadLocal常用方法:

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

在JwtTokenAdminInterceptor中,加入BaseContext.setCurrentId(empId);,设置id

    //2、校验令牌
    try {
        log.info("jwt校验:{}", token);
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
            log.info("当前员工id:", empId);
            BaseContext.setCurrentId(empId);
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }

在EmployeeServiceImpl中,BaseContext.getCurrentId() 获取id,并存入数据库

		// 设置当前记录创建人id和修改人id
        // TODO 后期需要改为当前登录用户的Id
        employee.setCreateUser(BaseContext.getCurrentId());
        employee.setUpdateUser(BaseContext.getCurrentId());

(2). 员工分页查询

业务规则:

  • 根据页码展示员工信息

  • 每页展示10条数据

  • 分页查询时可以根据需要,输入员工姓名进行查询

EmployeeController,根据接口定义创建分页查询方法:

/**
* 员工分页查询
* @param employeePageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("员工分页查询")
public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
    log.info("员工分页查询,参数为:{}",employeePageQueryDTO);
    PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
    return Result.success(pageResult);
}

在EmployeeServiceImpl声明pageQuery方法,及其父类接口:

public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) { 
    //select * from employee limit 10,20 
    //基于PageHelper插件实现动态分
    PageHelper.startPage(employeePageQueryDTO.getPage(),
    employeePageQueryDTO.getPageSize());   
Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}

注意:此处使用 mybatis 的分页插件 PageHelper 来简化分页代码的开发。底层基于 mybatis 的拦截器实现

在 EmployeeMapper 中声明 pageQuery 方法:

/**
* 分页查询
* @param employeePageQueryDTO
* @return
*/
Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

在 EmployeeMapper.xml 中编写SQL:


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.EmployeeMapper">
    <select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from employee
        <where>
            <if test="name != null and name != ''">
                and name like concat('%', #{name},'%')
            if>
        where>
        order by create_time desc
    select>
mapper>

一. 代码完善

程序存在的问题:

  • 日期显示并不是正常按年月日输出
    itheima苍穹外卖项目学习笔记--Day2:员工管理和分类管理_第1张图片

解决办法:

  • 方式一:在属性上加入注解,对日期进行格式化

在实体类中,添加注解

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
  • 方式二:在 WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理
/**
* 扩展Spring MVC框架的消息转换器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
	log.info("扩展消息转换器");
    // 创建一个小希转换器对象
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    // 需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
    converter.setObjectMapper(new JacksonObjectMapper());
    // 将自己的消息转换器加入到容器中
    converters.add(0, converter);
}

itheima苍穹外卖项目学习笔记--Day2:员工管理和分类管理_第2张图片

(3). 启用禁用员工账号

业务规则:

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

根据接口设计中的请求参数形式对应的在 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();
}

在 EmployeeServiceImpl 中声明启用禁用员工账号的业务方法,及其父类接口:

/**
* 启用禁用员工账号
* @param status
* @param id
*/
@Override
public void startOrStop(Integer status, Long id) {

    Employee employee = Employee.builder()
            .status(status)
            .id(id)
            .build();

    employeeMapper.update(employee);
}

在 EmployeeMapper 接口中声明 update 方法:

/**
* 根据id修改员工信息
* @param employee
*/
void update(Employee employee);

在 EmployeeMapper.xml 中编写SQL:

<update id="update" parameterType="Employee">
    update employee
    <set>
        <if test="name != null">name = #{name},if>
        <if test="username != null">username = #{username},if>
        <if test="password != null">password = #{password},if>
        <if test="phone != null">phone = #{phone},if>
        <if test="sex != null">sex = #{sex},if>
        <if test="idNumber != null">id_number = #{idNumber},if>
        <if test="updateTime != null">update_time = #{updateTime},if>
        <if test="updateUser != null">update_user = #{updateUser},if>
        <if test="status != null">status = #{status},if>
    set>
    where id = #{id}
update>

(4). 编辑员工

编辑员工功能涉及到两个接口:

  • 根据id查询员工信息 (GET)
  • 编辑员工信息 (POST)

一. 根据id查询员工信息 (GET)

在 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);
}

在 EmployeeServiceImpl 中实现 getById 方法,及其父类接口:

/**
* 根据Id查询员工
* @param id
* @return
*/
@Override
public Employee getById(Long id) {
    Employee employee = employeeMapper.getById(id);
    employee.setPassword("****");
    return employee;
}

在 EmployeeMapper 接口中声明 getById 方法:

/**
* 根据Id查询员工
* @param id
* @return
*/
@Select("select * from employee where id = #{id}")
Employee getById(Long id);

二. 编辑员工信息 (POST)

在 EmployeeController 中创建 update 方法:

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

在 EmployeeServiceImpl 中实现 update 方法,及其父类接口:

/**
 * 编辑员工信息
 * @param employeeDTO
 */
@Override
public void update(EmployeeDTO employeeDTO) {
    Employee employee = new Employee();
    BeanUtils.copyProperties(employeeDTO, employee);

    employee.setUpdateTime(LocalDateTime.now());
    employee.setUpdateUser(BaseContext.getCurrentId());

    employeeMapper.update(employee);
}

在启用禁用员工账号开发时,已在EmployeMapper.xml中编写了动态的update方法,所以在此方法中需要更新员工信息,也可以调用此方法

b. 分类模块功能代码

业务规则:

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

接口设计:

  • 新增分类
  • 分类分页查询
  • 根据id删除分类
  • 修改分类
  • 启用禁用分类
  • 根据类型查询分类

你可能感兴趣的:(苍穹外卖开发笔记,java,开发语言,spring,mybatis)