← 返回首页
Servlet基础教程(十六)
发表时间:2020-04-08 01:17:30
讲解Servlet的三大作用域

java web开发中servlet三大作用域对象为request、session和application(ServletContext)。

1.request

request表示一个请求,只要发出一个请求就会创建一个request。

作用域:仅在当前请求中有效。

2.session

简单说:session是一个时间段,表示客户端与服务器交互的一个时间段。

服务器会为每个会话创建一个session对象,所以session中的数据可供当前会话中所有Servlet共享。

作用域:用户从打开浏览器会话开始,直到关闭本次会话所有浏览器窗口,并且超时,会话才会结束。一次会话期间只会创建一个session对象。

获取方式:

HttpSession session = request.getSession();

session实现的内部原理如下:

当客户端访问服务器的某个资源时(静态资源除外,比如:html,css,js),服务器会创建一个名字叫JSESSIONID的会话编号,并且把它写入到客户端浏览器的cookie中。以后客户端每次访问服务器的资源时,客户端都会携带这个JSESSIONID和服务器的JSESSIONID对比,如果相同说明是同一个会话。

3.application(ServletContext)

所有的用户都可以取得这个信息,此信息在整个服务器中被保留。application属性范围值,只要设置一次,则所有的网页窗口都可以取得数据。

ServletContext在服务器启动时创建,在服务器关闭时销毁,一个javaweb应用只能创建一个ServletContext对象。所有客户端在访问服务器时共享同一个ServletContext对象。

获取方式:

ServletContext application= request.getServletContext();

4.实例

//HelloServlet
package com.servlet;

import javax.servlet.ServletConfig;
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 java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Enumeration;

@WebServlet(value = "/hello")
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //保存在request
        req.setAttribute("city","西安");
        //保存在session
        String sessionId = req.getSession().getId(); //获取当前会话ID。
        req.getSession().setAttribute("sessionId",sessionId);

        //保存在application
        String date = LocalDate.now().format(DateTimeFormatter.ISO_DATE);
        req.getServletContext().setAttribute("date",date);
        //通过请求重定向测试三个作用域。
        resp.sendRedirect(req.getContextPath()+"/test");
    }
}

//TestServlet 
package com.servlet;

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 java.io.IOException;

@WebServlet(name = "TestServlet", value = "/test")
public class TestServlet extends HttpServlet {
    public TestServlet() {
        System.out.println("执行TestServlet的构造方法...");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String city=null;
        String sessionId = null;
        String date = null;
        //获取request内保存的城市。
        if(request.getAttribute("city")!=null) {
            city = (String) request.getAttribute("city");
        }
        //因为使用了请求重定向,不是一次请求了,所有这里输出是null. 
        System.out.println("request内的city=" + city);

        //获取session内保存的会话编号
        if(request.getSession().getAttribute("sessionId")!=null){
            sessionId = (String) request.getSession().getAttribute("sessionId");
        }
        System.out.println("session内的会话编号=" + sessionId);

        //获取application内保存的日期
        if(request.getServletContext().getAttribute("date")!=null){
            date = (String) request.getServletContext().getAttribute("date");
        }

        System.out.println("application内的日期=" + date);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

启动tomcat后,分别使用两款不同的浏览器测试(比如:IE和Chrome),在地址输入测试地址: http://localhost:8080/helloservlet/hello

IE浏览器发出请求后,控制台输出内容如下:

request内的city=null
session内的会话编号=FD5F92FE84FC2EAED2D53E0E81E8678C
application内的日期=2020-04-08

Chrome浏览器发出请求后,控制台输出内容如下:

request内的city=null
session内的会话编号=825756DAC591D71BAE6C4292E3E9B004
application内的日期=2020-04-08

我们发现,不同的会话,有不同的会话ID。当然,这样测试还不足以说明application里保存的日期对象是所有用户所共享的。我们可以换一个思路,让Chrome浏览器,单独请求http://localhost:8080/helloservlet/test 控制台输出内容如下:

request内的city=null
session内的会话编号=null
application内的日期=2020-04-08

这样就很好的说明了application里保存的日期对象是被所有客户端所共享的。

5.request与session的区别

request的一个作用是获取信息--通过用户提交的表单,查询字符串,cookie等获得信息 ,第二个作用是请求资源。比如:http://localhost:8080/myapp/hello, 表示请求hello这个资源。即便是下次请求相同的资源,也是不同的请求(这个道理好比,你去饭馆吃饭,点了两瓶相同的啤酒,也是发了两次不同的请求)。

session是表示客户端与服务器交互的一个时间段(这个道理好比,你去一家饭馆吃饭的时间段,从进入饭馆点菜到最后结账离开,这一段时间。),session是保存在服务器内存里面,是服务端用来保存一些数据(通常是标记状态的,当然也可以保存别的) 。session通常可以用来跟踪用户的动作,比如登录,退出等。

session可以跨越很多页面。而session的生命周期也是针对一个客户端,但是却是在别人设置的会话周期内(一般是20-30分钟),session里边的内容将一直存在,即便关闭了这个客户端浏览器 session也不一定会马上释放掉的。

简单来说:request是请求资源,而session是一个时间段。request的生命周期只在数据提交,提交以后即释放,session则是浏览器关闭并且超时后才释放。