天天看点

JSP学习之ServletContext对象

ServletContext对象

  • 问题:

    Request解决了一次请求内的数据共享问题,session解决了用户不同请求的数据共享问题,那么不同的用户的数据共享该怎么办呢?

  • 解决:

    使用ServletContext对象

  • 作用:

    解决了不同用户的数据共享问题(如当前网页被浏览的次数)

  • 原理:

    ServletContext对象由服务器进行创建,一个项目只有一个对象。不管在项目的任意位置进行获取得到的都是同一个对象,那么不同用户发起的请求获取到的也就是同一个对象了,该对象由用户共同拥有。

  • 特点:

    服务器进行创建

    用户共享

    一个项目只有一个

  • 生命周期:

    服务器启动到服务器关闭

  • 作用域:

    项目内

  • 使用:

    (1)获取ServletContext对象:三种方式

方式一:(常用)
ServletContext sc = this.getServletContext();
           
方式二:
ServletContext sc2 = this.getServletConfig().getServletContext();
           
方式三:(常用)
 ServletContext sc3 = req.getSession().getServletContext();
           

(2)使用ServletContext对象完成数据共享: 使用作用域进行共享数据流转

数据存储:sc.setAttribute(name, value)
           
数据获取:sc.getAttribute(name)返回的Object类型
           
注意:
	不同的用户可以给ServletContext对象进行数据的存取。
	获取的数据不存在返回null。
           

(3)获取web.xml中的全局配置

Web.xml:(配置全局数据):
<context-param>(一个该标签只能有一组键值对,多个声明多个该标签)
		<param-name>name</param-name>
		<param-value>zhangsan</param-value>
</context-param>

//获取web.xml全局配置
String names = Sc.getInitParameterNames();//返回键名的枚举类
String name = Sc.getInitParameter(“name”);//获取上面全局配置参数, 数据不存在返回null

作用:将静态数据和代码进行解耦;(相当于异地恋)。
           

(4)获取MyEcplise中webroot(Eclipse中的webContent文件夹)下资源绝对路径

获取项目根目录下的资源的绝对路径:
	IO流写法,固定写好的:
	String path = “D:\\tomcat\webapps\sc\doc\1.txt”; 
	
动态获取:获取的目录是项目根目录,path参数为项目根目录中的路径
      String path = sc.getRealPath(String path);
           

(5)获取webContent或webroot项目根目录下资源的流对象

InputStream is = Sc.getResoureAsStream(String path);

注意:
	此种方式只能获取项目根目录下的资源流对象,可以取到和WEB-INF统计目录下的文件的流对象;
	class文件的流对象需要使用类加载器获取(不进WEB-INF文件夹);
	编译好的class文件不能取到;
           

案例(ServletContext对象网站计数器)

  • 原理:在用户登录校验中创建计数器并自增,然后存储到ServletContext对象中,在主页面里取出计数器数据显示给用户即可。
  • 实现:

    第一步:在登录成功的servlet进行重定向之前,创建计数器或计数器加1。

//创建网页计数器:
	//获取计数数据
	ServletContext sc = this.getServletContext();
	if( sc.getAttribute(“nums”) != null){
		int nums = (int)sc.getAttribute(“nums”);
		//计数器自增
		nums+=1;
		//再次存储到ServletContext对象中
		sc.setAttribute(“nums”, nums);
	}else{
		sc.setAttribute(“nums”, 1);
	}
           

第二步:在登录成功后绘制页面的servlet中获取网页浏览次数并显示

//获取网页浏览次数
int nums = Integer.parseInt(this.getServletContext().getAttribute(“nums”))
response.getWriter().write(“当前网页浏览次数为:”+nums)
           

第三步:在cookie登录校验三天免登陆的重定向之前网页计数器也要自增,因为也是一次登录。

int nums = (int)sc.getAttribute(“nums”);
	//计数器自增
	nums+=1;
	//再次存储到ServletContext对象中
	sc.setAttribute(“nums”, nums);
           
  • 问题:

    重启服务器,计数器就会重置

  • 解决方法:

    在webroot(WebContent)下面新建nums文件夹,新建nums.txt。在网站关闭时,将计数器信息写入nums.txt。

  • 解决实现:

    新建NumServlet,别名:/num

覆写init初始化方法,将数据读取到ServletContext对象中
init(){
	//获取文件中的计数器数据
	//获取文件路径
    	  String path = this.getServletContext().getRealPath(“/num/nums.txt”);
	//声明流对象
	FileReader fr=null;
	BufferedReader br = null;
	try{
   		fr= new FileReader(path);
   		br = new BufferedReader(fr);
   		String nums = br.readLine();//第一次启动时为null,但在之前设置了为null判断,所以不会出错
		System.out.println(nums)
   		this. sc.getServletContext().setAttribute(“nums”,nums);
	} catch(Exception e){
      	e.printStackTrace();
	}finally{
    	  //下面关闭需要try
      	fr.close();
      	br.close();
	}
}
           
覆写销毁方法,存储计数器到文件中
Destroy(){
      //获取网页计数器
      String num = (String) this.getServletContext().getAttribute(“nums”);
      //声明流对象
      BufferedWriter bw = null;
      FileWrier fw = null;
      //获取文件路径
      String path = this.getServletContext().getRealPath(“/num/nums.txt”);
      try{
      	fw = new FileWriter(path);
      	bw = new BufferedWriter(fw);
      	bw.write(nums+“”);//将nums转换为string类型
      	bw.flush();
	}catch(Exception e){
    	  e.printStackTrace();
	}finally{
	      //下面关闭需要try
      		fw.close();
    	  	bw.close();
}
           
打开web.xml文件,找到NumServlet,配置<load-on-startup>1</load-on-startup>