苍穹外卖day2 员工管理(JWT、ThreadLocal)、分类管理


前言

员工管理、分类管理。主要分析员工管理部分,分类管理中的代码逻辑和员工管理差不多,可以自己尝试着仿写。


一、员工管理

1、新增员工

以新增员工为例,给出产品原型和接口的设计。

1.1 产品原型

在这里插入图片描述

1.2 接口设计

在这里插入图片描述
怎么去看接口设计这部分,我们之后编写代码都是基于此,这是前端与后端的约定。
1、Path:请求路径 ,对应的注解@RequestMapping(“/admin/employee”)
2、Method:请求方式,方法上对应的注解@PostMapping(要不要写参数具体看path这里,如果xxcontroller类中请求路径都是admin/employee,那就把它放在类上面,后面还有具体的路径就可以写在这里)
3、请求参数:主要看请求体Body的内容,根据请求体来设计对应的实体类(DTO)。如下图。同时这部分也会作为方法的传入参数,JSON格式要记得在参数前加入@RequestBody注解。
在这里插入图片描述
4、返回的数据:这部分是数据被封装到Result结果集当中,主要是看返回的data数据,data数据是什么类型就按照对应的类型存入Result中。

1.3 代码开发

1、在EmployeeController中创建新增员工方法,接收前端提交的参数

 @PostMapping
    @ApiOperation("新增员工")
    public Result save(@RequestBody EmployeeDTO employeeDTO){
        employeeService.save(employeeDTO);
        return Result.success();
    }

2、在EmployeeServiceImpl中实现新增员工方法

 @Override
    public void save(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        //属性拷贝
        BeanUtils.copyProperties(employeeDTO,employee);
        //设置账号状态
        employee.setStatus(StatusConstant.ENABLE);
        //加密技术
             employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
       //这部分后面采用aop框架,所以就注释掉了
       //创建时间和更新时间
        //employee.setCreateTime(LocalDateTime.now());
       // employee.setUpdateTime(LocalDateTime.now());
        //当前创建人,修改人
        //employee.setCreateUser(BaseContext.getCurrentId());
       // employee.setUpdateUser(BaseContext.getCurrentId());*/
        employeeMapper.insert(employee);
    }

3、在EmployeeMapper中声明insert方法

  @Insert("insert into employee" +
            "(name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user)"+
            "VALUES" +
            "(#{name}, #{username}, #{password}, #{phone}, #{sex}, #{idNumber}, #{status}, #{createTime},#{updateTime},#{createUser}, #{updateUser})")
    @AutoFill(value = OperationType.INSERT)  //自定义注解
    void insert(Employee employee);

4、新增用户信息,要检查用户是否已经存在,可以通过全局异常处理器来处理。

  /**
     * 捕获sql异常,用户已存在
     */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
        log.error("异常信息:{}", ex.getMessage());
        String message = ex.getMessage();
        if(message.contains("Duplicate entry")){
            String[] split = message.split(" ");
            String name = split[2];
            return Result.error(name + MessageConstant.ALREADY_EXISTS);   }
        return Result.error(MessageConstant.UNKNOWN_ERROR);}
}

1.4 功能测试

两种方式:
通过接口文档(Swagger)
通过前后端联调(前端界面)

2、JWT、ThreadLocal

通过某种方式动态获取当前登录员工的id。
在这里插入图片描述
员工登录成功后会生成JWT令牌并响应给前端:

        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

通过JWT令牌可以解析出当前登录员工id,那如何传递给Service的save方法呢?
ThreadLocal
为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
常用方法:

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

注意:客户端发送的每次请求,后端的Tomcat服务器都会分配一个单独的线程来处理请求
方法:
(1)通过BaseContext封装ThreadLocal操作的工具类
(2)在JWT拦截器中解析当前登录员工的id,并放入线程局部变量中(BaseContext.setCurrentId(empId);)
(3)在Service中获取线程局部变量中的值。(employee.setCreateUser(BaseContext.getCurrentId());)

二、员工分页查询

1、 产品原型

在这里插入图片描述

2、 接口设计

在这里插入图片描述
根据请求参数设计实体类(DTO)
分页查询,统一封装成PageResult对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
    private long total; //总记录数
    private List records; //当前页数据集合
}

后端返回的对象类型:Result

3、 代码开发

1、controller层创建分页查询方法

 @GetMapping("/page")
    @ApiOperation("员工分页查询")
    public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
        PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
        return Result.success(pageResult);
    }

2、EmployeeService接口定义方法,EmployeeServiceImpl 中实现 pageQuery 方法

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

使用 mybatis 的分页插件 PageHelper 来简化分页代码的开发。底层基于 mybatis 的拦截器实现。
3、在 EmployeeMapper 中声明 pageQuery 方法
4、在 EmployeeMapper.xml 中编写SQL

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

4、 日期格式问题

在这里插入图片描述
解决方式
(1)在属性上加入注解,对日期进行格式化。效率低
在这里插入图片描述
(2)在 WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理

protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将java对象序列化为JSON数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转化器加到容器中
        converters.add(0,converter);
    }

三、启用禁用员工账号

1、业务规则

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

2、接口设计

在这里插入图片描述

3、代码开发

1、根据接口设计中的请求参数形式对应的在 EmployeeController 中创建启用禁用员工账号的方法

 @PostMapping("/status/{status}")
    @ApiOperation("启用禁用员工账号")
    public Result startOrStop(@PathVariable Integer status,Long id){
        log.info("启用禁用员工账号:{},{}",status,id);
        employeeService.startOrStop(status,id);
        return Result.success();
    }

2、在 EmployeeService 接口中声明方法,在EmployeeServiceImpl 中实现

@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)
                /*.updateTime(LocalDateTime.now())     //运用aop减少代码冗余
                .updateUser(BaseContext.getCurrentId())*/  
                .build();
        employeeMapper.update(employee);
    }

3、在 EmployeeMapper 接口中声明 update 方法
4、在 EmployeeMapper.xml 中编写SQ

 <update id="update">
        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>

四、修改员工信息

1、接口设计

在这里插入图片描述

2、代码开发

1、在 EmployeeController 中创建 update ()方法
2、在 EmployeeService 接口中声明方法,在 EmployeeServiceImpl 中实现方法
3、调用EmployeeMapper中的update()方法

总结

实现基本的增删改查操作,都是一个套路,代码编辑路线:controller->service->serviceImpl->mapper(简单的sql语句直接用注解,不需要去xml文件中编写)—>mapper.xml(编写sql语句)

  • 27
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值