苍穹外卖day02——员工管理功能代码开发+分类管理代码导入

目录

新增员工——需求分析与设计

 产品原型

 接口设计:

数据库设计:

新增员工——代码开发

 在Controller层中

 在Service层中

 在Mapper层中

 功能测试

接口文档测试:

 前后端联调测试:

 新增员工——代码完善

​编辑

第一个问题 

第二个问题

员工分页查询

需求分析与设计

产品原型如下

接口设计

​编辑

 代码开发

在Controller层中

在Service层中

在Mapper层中

功能测试

swagger接口文档测试

 前后端联调测试

代码完善

启用,禁用员工账号——需求分析与设计

​编辑 接口设计

启用,禁用员工账号——代码开发和功能测试

在Controller层中

在Service层中

在Mapper层中

功能测试

接口文档测试 

前后端联调测试 

编辑员工——需求分析与设计

产品原型:

 接口设计

 编辑员工——代码开发

在Controller层中

在Service层中

在Mapper层中

功能测试

前后端联调测试 

导入分类管理功能代码

产品原型

 数据库设计表


新增员工——需求分析与设计

 产品原型

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第1张图片

 接口设计:

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第2张图片

数据库设计:

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第3张图片

新增员工——代码开发

DTO是传输数据的实体类,而不是某一个表格的实体类。

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第4张图片

 在Controller层中

 EmployeeController中

    /*
    *
    *
    * 新增员工
    * */
    @PostMapping
    @ApiOperation("新增员工")
    public Result save(@RequestBody EmployeeDTO employeeDTO){
        log.info("新增员工:{}",employeeDTO);
        employeeService.save(employeeDTO);
        return Result.success();
    }

 在Service层中

 定义一个新的接口方法


    /**
     * 新增员工业务方法
     * @param employeeDTO
     */
    void save(EmployeeDTO employeeDTO);

 接口实现类新增方法,此处创建人和修改人id后面再解决。

@Override
    public void save(EmployeeDTO employeeDTO) {
        Employee employee=new Employee();
        //两个实体有很多属性名都一样,不一个一个set的话,可以通过对象的属性拷贝
        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
        // TODO 后期改为当前登录用户的id
        employee.setCreateUser(10L);
        employee.setUpdateUser(10L);

        employeeMapper.insert(employee);
    }

 在Mapper层中

    /**
     * 插入员工数据
     * @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);

 功能测试

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第5张图片

接口文档测试:

在调试界面设置好参数,点击发送 后返回一个401,没有成功返回,这里是被拦截器拦截了。

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第6张图片

 会校验jwt令牌 ,这里因为没有令牌,所以token为空,返回的是401苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第7张图片

 首先要获取一个令牌,在登录接口正常获取即可。

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第8张图片

 获取到token之后在文档管理——>全局参数设置里面配置一个token属性。

这里name=token是因为后端项目配置文件里面配置的一个属性就是token,项目会自动取出这个token 

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第9张图片

再次发送调试成功返回 

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第10张图片

 前后端联调测试:

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第11张图片

 数据库成功多出两条数据

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第12张图片

 新增员工——代码完善

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第13张图片

第一个问题 

将插入重复员工时报的错误异常放进全局异常处理器进行处理 

SQLIntegrityConstraintViolationException

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

再次测试

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第14张图片

第二个问题

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第15张图片
苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第16张图片 苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第17张图片

总的就是获取token中间的字段进行解析之后就可以获取登录用户ID了

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第18张图片

客户端发起的每一次请求都是一次单独的线程。

这里项目已经提前封装好了ThreadLocal的常用方法苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第19张图片 

 在拦截器当中将取出的ID存进暂存区

            BaseContext.setCurrentId(empId);

在服务层代码中取出


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

完成一个小功能的代码记得及时存储推送到云端。

员工分页查询

需求分析与设计

产品原型如下

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第20张图片

接口设计

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第21张图片

 代码开发

设计DTO,传输数据格式。

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第22张图片

分页查询的响应数据因为有两个对象,所以再封装一次。然后返回一个Result对象。 

 苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第23张图片

 此处使用到一个mybatis提供的分页查询的插件,依赖如下。

            
                com.github.pagehelper
                pagehelper-spring-boot-starter
                ${pagehelper}
            

在Controller层中

此处是Query参数,所以不需要@Requestbody注解返回的PageResult对象要封装层Result风格。

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

在Service层中

这里用到了PageHeloer插件,要封装成pageResult对象还要将查询结果里面的数据取出来。

此处startPage方法和pageQuery方法看似没有交集,但是在底层是通过ThreadLocal对象共享了一部分数据。后面开始分页查询之前就已经通过ThreadLocal取出了页码和每页记录数,然后动态的拼接上limit关键字。

    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        //select * from employee limit 0,10
        //开始分页查询,传了个页码和每页的记录数
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
        //此处Page对象是PageHelper提供的。
        Page page=employeeMapper.pageQuery(employeePageQueryDTO);

        long total = page.getTotal();
        List records = page.getResult();

        return new PageResult(total,records);
    }

在Mapper层中

这条查询用的不是注解开发,用的是xml配置文件开发,所以还需要在Resources目录下准备对应的xml文件。


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

在配置文件中已经配置好了这个xml开发

mybatis:
  #mapper配置文件
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.sky.entity
  configuration:
    #开启驼峰命名
    map-underscore-to-camel-case: true

在EmployeeMapper.xml文件里面




    

功能测试

swagger接口文档测试

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第24张图片

 苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第25张图片

 控制台输出

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第26张图片

 前后端联调测试

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第27张图片

 因为返回的日期数据用的是数据格式,所以前端的时间格式看着很别扭.

代码完善

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第28张图片

方式一:

加上注解 

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第29张图片 

再次测试看见数据格式有了变化。

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第30张图片 第二种方式

准备一个对象转换器 ,主要进行序列化和反序列化操作

/**
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
 */
public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    //public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

在配置类中

    /**
     * 扩展springMVC框架的消息转换器,可以
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List> converters) {
        log.info("扩展消息转换器...");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将java对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转换器加入容器中,并设定优先级为0,最高优先级
        converters.add(0,converter);
    }

接口文档测试:
苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第31张图片

 前后端联调测试

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第32张图片

都没有问题了。

最后还要记得推送云端。

启用,禁用员工账号——需求分析与设计

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第33张图片

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第34张图片 接口设计

需要一个路径参数和一个Query参数

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第35张图片 

启用,禁用员工账号——代码开发和功能测试

在Controller层中

针对查询类的操作需要返回data数据,则要加上泛型,非查询类的就不需要了。

 


    /**
     * 路径参数通过PathVariable注解获取,Query参数只要name保持一致即可
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("启用禁用员工账号")
    public Result startOrStop(@PathVariable("status") Integer status,Long id){
        log.info("启用禁用员工账号{},{}",status,id);
        employeeService.startOrStop(status,id);
        return Result.success();
    }

在Service层中

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

//        Employee employee = new Employee();
//        employee.setStatus(status);
//        employee.setId(id);
        //两种编程风格
        Employee employee = Employee.builder().status(status).id(id).build();

        employeeMapper.update(employee);
    }

在Mapper层中

这里用的是动态SQL写法,需要xml文件

    /**
     * 根据主键动态修改属性
     * @param employee
     */
    void update(Employee employee);
    
    
        update employee
        
             name = #{name},
             username = #{username},
             password = #{password},
             phone = #{phone},
             sex = #{sex},
             id_number = #{idNumber},
             status = #{status},
             update_Time = #{updateTime},
             update_User = #{updateUser},
        
        where id =#{id}
    

功能测试

接口文档测试 

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第36张图片

数据库数据修改成功苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第37张图片 

前后端联调测试 

成功修改。

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第38张图片

编辑员工——需求分析与设计

编辑界面需要点击修改然后查询回显员工信息然后根据需要进行修改再保存更新数据库。

产品原型:

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第39张图片

 接口设计

一个接口是查询的接口,一个接口是更新的接口。

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第40张图片

 苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第41张图片

 编辑员工——代码开发

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第42张图片

 可以看见id是通过路径参数传参。

在Controller层中

 /**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询员工信息")
    public Result 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();
    }

在Service层中

    /**
     * 根据id查询员工
     * @param id
     * @return
     */
    @Override
    public Employee getBYId(Long id) {
      Employee employee= employeeMapper.getById(id);
      employee.setPassword("****");//防止密码泄露
      return employee;
    }

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
    @Override
    public void update(EmployeeDTO employeeDTO) {
        Employee employee=new Employee();
        //对象属性拷贝,这样就可以使用上面启用禁用那里的update语句
        BeanUtils.copyProperties(employeeDTO,employee);
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.update(employee);
    }

在Mapper层中

这里因为update方法在启用禁用部分已经写过了,所以这里不再写一次了

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

功能测试

查询回显成功

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第43张图片

前后端联调测试 

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第44张图片

记得推送代码

导入分类管理功能代码

产品原型

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第45张图片

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第46张图片

 数据库设计表

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第47张图片

导入分类管理模块的代码之后成功进行前后端联调测试

苍穹外卖day02——员工管理功能代码开发+分类管理代码导入_第48张图片 记得git push

你可能感兴趣的:(SpringBoot,数据库,后端,java,spring,boot)