一、会话
用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话就结束。在一次会话中可以包含多次请求和响应
HTTP 协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,因此我们需要会话跟踪技术来实现一次会话内数据共享
Cookie是存储在浏览器端,而Session是存储在服务器端
当用户首次访问一个Web应用时,服务器会为该用户创建一个会话,并分配一个唯一的会话标识符(session ID)。这个会话标识符通常以cookie的形式存储在用户的浏览器中
在用户访问过程中,浏览器会将会话标识符发送给服务器,服务器根据标识符来识别用户的会话,并在需要时更新会话状态。会话状态可以包括用户的登录状态、购物车内容、用户偏好设置等信息。
关于会话的生命周期,可以通过设置Session存储时间实现
二、登入为例,保存用户id
登录成功,将员工id存入Session并返回登录成功结果
request.getSession().setAttribute("employee",emp.getId());
//json格式的数据,Employee对象接收,要加@RequestBody
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request,@RequestBody Employee employee){
//1、将页面提交的密码password进行md5加密处理
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
//2、根据页面提交的用户名username查询数据库
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getUsername,employee.getUsername());
Employee emp = employeeService.getOne(queryWrapper);
//3、如果没有查询到则返回登录失败结果
if(emp == null){
return R.error("登录失败");
}
//4、密码比对,如果不一致则返回登录失败结果
if(!emp.getPassword().equals(password)){
return R.error("登录失败");
}
//5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果
if(emp.getStatus() == 0){
return R.error("账号已禁用");
}
//6、登录成功,将员工id存入Session并返回登录成功结果
request.getSession().setAttribute("employee",emp.getId());
return R.success(emp);
}
使用session,为线程设置值
//判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("employee") != null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
Long empId = (Long) request.getSession().getAttribute("employee");
BaseContext.setCurrentId(empId);
filterChain.doFilter(request,response);
return;
}
基于ThreadLocal封装工具类,用户保存和获取当前登录用户id,便于公共字段自动填充
/**
* 基于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();
}
}
公共字段自动填充,我们对数据的CRUD操作,数据是谁操作的?,session与ThreadLocal结合使用,保存用户的id
@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());
}
}