苍穹外卖Day02

1.新增员工

1.1项目约定

  • 管理端发出的请求,统一使用/admin作为前缀
  • 用户端发出的请求,统一使用/user作为前缀

1.2代码开发

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

在这里插入图片描述
**注意:**当前端提交的数据和实体类中对应的属性差别比较大时,建议使用DTO来封装数据

EmployeeController中创建新增员工方法

/**
     * 新增员工
     * @param employeeDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增人员")
    public Result save(@RequestBody EmployeeDTO employeeDTO) {
        //{}占位符,运行时动态的将employeeDTO放在{}
        log.info("新增员工:{}", employeeDTO);
        //调用service
        employeeService.save(employeeDTO);
        return Result.success();
    }

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

/**
     * 新增员工
     * @param employeeDTO
     */
    void save(EmployeeDTO employeeDTO);
}

在EmployeeServiceImpl中实现新增员工方法

/**
     * 新增员工
     * @param employeeDTO
     */
    public void save(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        //对象属性拷贝
        //从 DTO 到实体类的数据传递。
        BeanUtils.copyProperties(employeeDTO, employee);
        //设置账号的状态,默认正常状态   1表示正常,0表示锁定
        //使用常量而不是硬编码的字符串值可以减少错误,并使代码更易于更新。
        //如果将来状态的表示方式发生变化,只需要在一个地方(即 StatusConstant 中)进行修改即可
        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中声明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);

1.3功能测试

通过Apipost测试:
点击调试,填写请求参数,点击发送后,程序好像没什么反应,而是直接返回响应码 401。HTTP状态码 401 表示未经授权,表示请求需要进行身份验证,但请求没有提供所需的凭据:
在这里插入图片描述
这是因为项目中写了一个拦截器,在收到请求后,都会被其拦截,拦截器会先从请求头中获取 jwt 令牌并校验令牌,通过校验才可以进行后续操作;否则直接返回。

因为刚才并没有传令牌给服务端,所以请求失败了。

但是每一次我们发送请求测试都要传递令牌,其实是很麻烦的,所以我们的想法是在接口文档中统一添加一个令牌,这样在后续调试都会自动将令牌提交给服务端。(在项目的配置文件中,我们设置了 jwt 令牌的有效时间为 2 小时,每次过时都得重新获取复制)

首先,我们需要先获取一个令牌,很简单,我们通过员工登录这个接口即可获取,将其token复制:
在这里插入图片描述
将token设置为全局变量后,点击发送则成功录入数据库
在这里插入图片描述
在这里插入图片描述
前后端联调
从前端添加员工
在这里插入图片描述
在这里插入图片描述

1.4 代码完善

程序尚存问题

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

解决问题一
在GlobalExceptionHandler中添加方法

/**
     *处理sql异常
     * @param ex
     * @return
     */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException  ex) {
        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);
        }
    }

在MessageConstant中添加

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

在这里插入图片描述
解决问题二
针对此问题,则需通过某种方式动态获取当前登录员工的id:在这里插入图片描述

解析出登录员工 id 后,如何将其传递给 Service 的 save 方法?

  • ThreadLocal 并不是一个 Thread,而是 Thread 的局部变量。
  • ThreadLocal 为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问
  • 其是通道技术,是不同线程之间通讯用
    ThreadLocal 常用方法:
  • public void set(T value) 设置当前线程的线程局部变量的值
  • public T get() 返回当前线程所对应的线程局部变量的值
  • public void remove() 移除当前线程的线程局部变量

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

BaseContext.setCurrentId(empId);

EmployeeServiceImpl中获取线程局部变量值:

employee.setCreateUser(BaseContext.getCurrentId());
        employee.setUpdateUser(BaseContext.getCurrentId());

2.员工分页查询

2.1需求分析与设计

产品原型

在这里插入图片描述

接口路径
在这里插入图片描述

业务规则

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

2.2 代码开发

  1. 根据分页查询接口设计对应的DTO:

在这里插入图片描述
在EmployeeController层创建分页查询方法

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

在EmployeeService接口中声明pageQuery 方法

/**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

在 EmployeeServiceImpl 中实现 pageQuery 方法

 /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO){
        //select * from employee limit 0, 10
        //开始分页查询

        //mybatis的动态拼接
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());

        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);

        long total = page.getTotal();
        List<Employee> records = page.getResult();
        return new PageResult(total,records);
    }

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

在EmployeeMapper层中声明PageQuery方法

/**
     * 分页查询的方法
     * @param employeePageQueryDTO
     * @return
     *///需要动态sql
    Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

在 EmployeeMapper.xml 中编写SQL

 <select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from employee
        <where>
            <if test="name != null and != ''">
                and name like concat('%',#{name}, '%')
            </if>
        </where>
        order by create_time desc
    </select>

2.3 功能测试

通过Apipost测试
在这里插入图片描述
发现updatetime格式不对,需要代码完善

2.4 代码完善

时间格式有误

  • 解决方法一:在属性上加入注解,对日期进行格式化(一个个加,当数据多了非常繁琐)
    在这里插入图片描述

  • 方式二:在 WebMvcConfiguration 中扩展 SpringMVC 的消息转换器,统一对日期类型进行格式化处理

/**
     * 扩展SpringMVC框架的消息转化器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转化器...");
        //创建一个消息转化器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转化器加入容器中

        //添加索引 index:0  使得自己的消息转化器为第一位使用

        converters.add(0,converter);

    }

在这里插入图片描述

3.启用禁用员工账号

3.1产品原型与设计

在这里插入图片描述
业务规则

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

接口设计
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2代码设计

在EmployeeController层创建方法

/**
     * 启用禁用员工账号
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("启用禁用员工账号")
    //Result<T> 泛型不是强制的,查询类要返回date数据的就加泛型<T>,而我们返回的是code

    //通过@PathVariable获取{status}路径参数
    public Result startOrStop(@PathVariable Integer status, Long id) {//传过来一个路径参数,一个id
        log.info("启用禁用员工账号:{},{}", status, id);
        employeeService.startorstop(status,id);
    return Result.success();
    }

在EmployeeService接口

/**
     * 启用禁用员工账号
     * @param status
     * @param id
     */
    void startorstop(Integer status, Long id);

在EmployeeService层实现方法

/**
     * 启用禁用员工账号
     * @param status
     * @param id
     */
    @Override
    public void startorstop(Integer status, Long id) {
        //update employee set status = ? where id = ?

         
//       Employee employee = new Employee();
//       employee.setId(id);
//       employee.setStatus(status);

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

        employeeMapper.update(employee);
    }

在EmployeeMapper接口中声明update方法

 /**
     * 根据主键动态修改属性
     * @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>

3.3 功能测试

在这里插入图片描述
在这里插入图片描述

3.4 前后端联调

在这里插入图片描述
在这里插入图片描述

4. 编辑员工

4.1 产品原型与设计

在这里插入图片描述

在这里插入图片描述
业务规则

  • 根据id查询员工信息
  • 编辑员工信息

接口设计
在这里插入图片描述

4.2 代码开发

根据id查询员工信息、编辑员工

EmployeeController层

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


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

EmployeeService接口

 /**
     * 根据id查询员工
     * @param id
     * @return
     */
    Employee getById(Long id);

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
    void update(EmployeeDTO employeeDTO);

EmployeeService层

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

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

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

        employeeMapper.update(employee);
    }

EmployeeMapper层
注:在启用禁用员工账号时已经完成编辑员工的代码(相同的)

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

4.3 功能测试

根据id查询员工信息
在这里插入图片描述

编辑信息
在这里插入图片描述
前后端联调
在这里插入图片描述
在这里插入图片描述

5.分类管理

5.1 产品原型与设计

产品原型
在这里插入图片描述
业务规则

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

接口设计

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

5.2 代码导入

与员工管理类似,导入代码并调试就行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值