学习目标:
1、了解服务器端作用域
2、在实际项目中灵活的使用作用域
学习过程:
我们前面讲过http是一次连接,但是服务器有的时候需要记录某个操作是那一个用户的,比如用户下订单前需要登录,服务器需要知道这个订单是谁下的,又或者发布文章,一般也需要先登录,然后再发布,既然http是一次连接,服务器又是如何知道是那一个用户的呢。事实上不论是服务器还是客户端,都是可以保存数据的,客户端一般就是使用cookie保存,服务器根据保存的作用域的大小包括三种方式:request、session和application,这节课我们先学习的是服务器端保存数据的三种作用域的区别和使用方式。
一、基本概念
作用域用来做什么?用于在不同的servlet中交互数据,这些数据都是保存在服务器端,一般有三个request,session和application。他们的区别如下:
1、request作用域。一次请求会产生一个这样的对象,请求结束则销毁。怎样可以被称为同一个请求中?就是一次http的连接。重定向就是两次请求了。所以我们要把servlet的数据交给jsp显示都是使用转发。request的使用非常简单,就是两个操作:设置和取值:
设值:request.setAttribute("usr",Object);
取值:request.setAttribute("usr",Object);
2、session作用域。客户端第一次请求产生,作用于同一个客户端,直到session过期或网页关闭而销毁。怎样可以被称为同一个回话?同一个浏览器窗口中访问服务器,第一次访问服务器就会记录,当然如果你关闭浏览器在访问,这时候服务器就会重新启动一个新的会话,如果你长时间不访问,服务器也会销毁这个会话。session的使用也很简单:
设值:request.getSession().setAttribute("usr", Object);
取值:TBean tnb =(TBean)request.getSession().getAttribute("usr");
3.application作用域。WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
设值: request.getSession().getServletContext().setAttribute("servletCount",Object);
取值: Integer counter =(Integer ) request.getSession().getServletContext().getAttribute("servletCount");
二、测试
下面我们新建一个servlet,我们测试一下request、session和application不同的作用域,servlet对应的web.xml的配置这里就不列出了,应该很熟悉了吧。
代码逻辑是每次都从作用域中取值,然后加一,再把该值重新放回作用域中。看一下作用域是否能保存该值。
这里仅列出servlet代码如下:
public class ScopeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//
Object requestId=request.getAttribute("requestId");
int rid=0;
if(requestId!=null){
rid=Integer.parseInt(requestId.toString());
}
rid++;
request.setAttribute("requestId", rid);
HttpSession session=request.getSession();
Object sessionId=session.getAttribute("sessionId");
int sid=0;
if(sessionId!=null){
sid=Integer.parseInt(sessionId.toString());
}
sid++;
session.setAttribute("sessionId", sid);
//
Object appId=session.getServletContext().getAttribute("appId");
int aid=0;
if(appId!=null){
aid=Integer.parseInt(appId.toString());
}
aid++;
session.getServletContext().setAttribute("appId", aid);
request.setAttribute("name", "Αυ±£");
session.setAttribute("name", "Αυ±Έ");
session.getServletContext().setAttribute("name", "Αυ°ξ");
session.removeAttribute("name");
session.invalidate();//
request.getRequestDispatcher("scope.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
页面代码如下:
<body>
rid:${requestId }
<Br/>
si:${sessionId }
<Br/>
aid:${appId }
<Br/>
${applicationScope.name }
</body>
试验一、打开一个浏览器不断的刷新
访问这个页面,不断刷新这个页面,就等于不断访问服务器。你会发现request一直都是1,因为request并不保存数据,所以每一次访问都是空值。而session每一次访问都会加1。application每一次访问也都会加1。
试验二、打开两个浏览器不断的刷新
但是重启浏览器或者启动另外一个浏览器都会重头开始,这时候又是一个新的会话了,可以看到session的值递增只跟当前的浏览器有关(专业说法就是当前的一次会话)。最有趣的是application,不同的浏览器访问都会互相有影响的,哪怕你重启浏览器也能继续保存之前的值,只有你重启tomcat后才会重新从1开始。
经过上面的试验,应该可以理解三个作用域的不同了吧。
三、EL 表达式的优先顺序
下面我们在做一个实验,为三个作用域设置三个同名的属性
request.setAttribute("name", "request作用域");
session.setAttribute("name", "session作用域");
session.getServletContext().setAttribute("name", "application作用域");
然后在页面使用EL表达式访问,这个时候会显示的是哪一个呢?
${name }
最后看到显示的是request,从中我们可以看到EL表达式访问作用域的顺序是从小到大的。也就是
pageScope:requestScope:sessionScope:applicationScope
这些信息都是保存在服务器的,那么客户端也是可以保持数据的,一般使用cookie,保存在客户端的信息一般都是比较小,而且安全性要求也不高。