目录
一. 编辑员工信息
1.1 需求分析
1.2 代码编写
执行流程
后端代码
二. 项目公共字段填充
2.1 问题分析
2.2 代码实现
2.3 功能完善
一. 编辑员工信息
1.1 需求分析
在员工管理列表点击编辑按钮,跳转至编辑页面后,回显员工数据进行修改。
请求URL:
http://localhost:8080/backend/page/member/add.hml?id=1519713809428660226
编辑页面使用的是添加页面,不一样的是编辑页面需要携带传递的参数ID去修改员工对象。
1.2 代码编写
执行流程
在开发代码之前需要梳理一下操作过程和对应的程序的执行流程:
- 点击编辑按钮时,页面跳转到add.html,并在url中携带参数员工ID
- 在add.html页面获取url中的参数员工ID
- 发送ajax请求,请求服务端,同时提交员工id参数
- 服务端接收请求,根据员工id查询员工信息,将员工信息以ison形式响应给页面
- 页面接收服务端响应的ison数据,通过VUE的数据绑定进行员工信息回显
- 点击保存按钮,发送aiax请求,将页面中的员工信息以ison方式提交给服务端
- 服务端接收员工信息,并进行处理,完成后给页面响应
- 页面接收到服务端响应信息后进行相应处理
后端代码
EmployeeController
/**
* 根据ID查询员工信息
* @param id
* @return
*/
@GetMapping("/{id}")
public R<Employee> getById(@PathVariable Long id){
log.info("根据ID查询员工信息");
Employee employee = employeeService.getById(id);
return R.success(employee);
}
二. 项目公共字段填充
2.1 问题分析
新增员工时需要设置时间,创建人,修改时间,修改人等字段,在编辑员工的时候也要设置这些字段,这些属于公共的字段可以使用MybatisPlus提供的公共字段填充功能,避免代码重复:
2.2 代码实现
实现步骤:
- 实体类的属性上加入@TableField注解,指定自动填充的策略
- 按照框架编写元数据对象处理器,同一字段赋值,实现MetaObjectHandler接口
MyMetaObjecthandler.java
package com.itheima.reggie.common;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 自定义元数据对象处理器
*/
@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {
/**
* 插入操作,自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充[insert]...");
log.info(metaObject.toString());
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime",LocalDateTime.now());
metaObject.setValue("createUser", BaseContext.getCurrentId());
metaObject.setValue("updateUser", BaseContext.getCurrentId());
}
/**
* 更新操作,自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充[update]...");
log.info(metaObject.toString());
long id = Thread.currentThread().getId();
log.info("线程id为:{}",id);
metaObject.setValue("updateTime",LocalDateTime.now());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
}
2.3 功能完善
上面的代码还是有所欠缺,无法获得创建的用户和更新的用户导致程序报错,使用ThreadLocal可以解决无法获取session中的员工ID的问题。
当客户端发送的每次的Http请求,对应的服务器都会分配一个新的线程来处理,处理过程中下面的类所属方法都属于一个线程:
- LoginCheckFilter的doFilter的方法
- EmployeeController的update方法
- MyMetaObjectHandler的updateFill方法
可以在上面的三个方法中分别加入下面代码(获取当前线程ID):
long id = Thread.currentThread().getId();
log.info("线程id为:{}",id);
什么是ThreadLocal?
ThreadLocal并不是一个Thread,而是Thread的局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
ThreadLocal常用方法
public void set(Tvalue):设置当前线程的线程局部变量的值
public T get(): 返回当前线程所对应的线程局部变量的值
我们可以在LoainCheckFilter的doFilter方法中获取当前登录用户id,并调用ThreadLocal的set方法来设置当前线程的线程局部变量的值用户ID,然后使用MyMetaObjectHandler的updateFill方法姥获取用户ID
具体实现步骤:
- 编写BaseContext工具类,基于ThreadLocal封装的工具类
- 在LoginCheckFilter的doFilter方法中调用BaseContext来设置当前登录用户的id
- 在MyMetaObjectHandler的方法中调用BaseContext获取登录用户的id
BaseContext.java
package com.itheima.reggie.common;
/**
* 基于ThreadLocal封装工具类,用户保存和获取当前登录用户id
*/
public class BaseContext {
private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
/**
* 设置值
* @param id
*/
public static void setCurrentId(Long id){
threadLocal.set(id);
}
/**
* 获取值
* @return
*/
public static Long getCurrentId(){
return threadLocal.get();
}
}
LoginCheckFilter.java的doFilter方法中加入:
Long empId = (Long) request.getSession().getAttribute("employee");
BaseContext.setCurrentId(empId);
改完之后,测试后功能与之前一样,说明无问题。