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>