1. session域对象中存储引用数据类型,存储的数据的引用!证明如下:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
/**
* @author Zuoyueer
* Date: 2019/10/26
* Time: 20:52
* @projectName HomeWork
* @description: 证明session存储引用数据类型是存储的引用, 修改集合中的内容会改变session的数据
*/
@WebServlet(urlPatterns = "/TestSession", name = "TestSession")
public class TestSession extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
HttpSession session = request.getSession();
session.setAttribute("list", list);
//直接修改list集合中的数据
list.add("ccc");
list.remove("aaa");
//session中数据同步改变了,说明存储的是引用
ArrayList<String> list1 = (ArrayList<String>) session.getAttribute("list");
for (String s : list1) {
System.out.println(s); //输出的是: bbb ccc
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
2. 上面的servlet类,如果多次访问,那么输出结果会改变吗?
答案是不会,因为每次请求访问,都会重新创建一个Arraylist集合,每次都执行
session.setAttribute("list", list);
,就会覆盖原来的数据,所以每次请求输出的结构都一样
3. 显然我们不希望看到每次请求,session域中原来的数据都被覆盖了,不仅造成数据的丢失,每次创建新的集合都是对资源的浪费.那么我们如何解决呢?
第一种解决方案很简单,就是把创建ArrayList对象的语句提取到外面,作为类的成员变量,这样多次请求共享同一个集合,只会在第一次访问的时候创建集合,可以解决上面的问题.
这种做法虽然解决了问题, 但是很low . 无关紧要的东西是不建议设置成类的成员变量,而且是servlet的共享资源,更加需要多加思考.
第二种解决方案正是我写这篇博客的最大诱因.希望分享给大家,也使得自己能记住.
//多余的代码我就不写了,直接展示精华
List list = session.getAttribute("list");//第一次访问,list为null,其他时候直接获取原来的数据
if (list == null) {
//只有第一次访问的时候才创建list集合,其他的时候直接session域中获取
list = new ArrayList<Book>();
//因为session存储集合是引用数据类型,所以第一次请求的时候添加list的引用就可以,避免了每次请求都覆盖原来的
session.setAttribute("list", list);
}
list.add("aaa");
list.add("bbb");
完!