为何session中存入对象后,修改对象的属性值后并没有再次存入session,session中存放的对象也发生改变?

遇到这样的一个业务场景:前端请求检查会员信息接口,后端用session保存会员信息以便后续业务使用。但输出的信息需要脱敏,在把会员信息对象存入session后,修改对象的属性值为脱敏值输出,但是在后续业务需要用到会员信息时再从session中获取,发现session中的对象的属性也被修改成了脱敏值,这是为什么呢?
大体代码如下:

@Data
public class User {
    private Integer id;
    private String name;
}
/**
 * 得到request对象
 */
public HttpServletRequest getRequest() {
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    return request;
}

/**
 * 保存session
 *
 * @param key
 * @param value
 */
public void setSessionAttr(String key, Object value) {
    HttpSession session = getRequest().getSession();
    session.setAttribute(key, value);
}

/**
 * 获取session值
 *
 * @param key
 * @return
 */
public <T> T getSessionAttr(String key) {
    HttpSession session = getRequest().getSession();
    return (T) session.getAttribute(key);
}
@RequestMapping("/test4")
public Object test4() throws Exception{
    User user = new User();
    user.setId(100);
    user.setName("王二狗");
    setSessionAttr("user",user);

    //脱敏
    user.setName("王*狗");
    return user;
}
@RequestMapping("/test6")
public void test6() throws Exception{
    User user = getSessionAttr("user");
    System.out.println("user: "+user);
}

测试结果如下:
在这里插入图片描述
发现明明没有再保存进入,但从session中获取出来的值却被改变了!
原因分析
session底层其实是用ConcurrentHashMap保存数据的,下面就以Map集合进行分析

@Test
public void test35() throws Exception{
    User user = new User();
    user.setName("王二狗").setAge(18);
    Map<String,User> map = new HashMap<>();
    map.put("user",user);
    System.out.println(map.get("user"));

    user.setName("王三狗").setAge(20);
    System.out.println(map.get("user"));
}

在这里插入图片描述
由此可见,在Map集合中保存的对象并不是对象本身,而是对象的引用地址。当对象放入Map集合后修改对象的属性值,然后再次从Map中取值,实际上是根据的引用地址去找此对象。同理,session中保存的数据也是一样。

参考:

  1. Tomcat Session总结及底层实现

  2. session中存放一个对象,只修改对象的属性,不将修改后的对象存放session,发现session中存放的对象也发生改变!

你可能感兴趣的:(Java,java,map,session)