ServletContext对象
作用
不同的用户的数据共享用 ServletContext 对象解决
原理
ServletContext 对象由服务器进行创建,一个项目只有一个对象。不管在项目的任意位置进行获取得到的都是同一个对象,那么不同用户发起的请求获取到的也就是同一个对象了,该对象由用户共同拥有
特点
- 服务器进行创建
- 用户共享
- 一个项目只有一个
生命周期
服务器启动到服务器关闭
作用域
整个项目内
使用
- 获取 ServletContext 对象
第一种方式:
ServletContext sc=this.getServletContext();
第二种方式:
ServletContext sc2=this.getServletConfig().getServletContext();
第三种方式:
ServletContext sc3=req.getSession().getServletContext(); - 使用ServletContext对象完成数据共享(使用作用域进行共享数据流转)
数据存储
sc.setAttribute(String name, Object value);
数据获取
sc.getAttribute(“str”) 返回的是Object类型
注:
不同的用户可以给ServletContext对象进行数据的存取
获取的数据不存在返回null - 获取项目中web.xml文件中的全局配置数据(获取 web.xml 中的全局配置)
sc.getInitParameter(String name); 根据键的名字返回web.xml中配置的全局数据的值,返回String类型,如果数据不存在返回null
sc.getInitParameterNames();返回键名的枚举
在web.xml中进行配置,具体如下:
<!--
一组<context-param>标签只能存储一组键值对数据,
多组可以声明多个 <context-param>进行存储-->
<context-param>
<param-name>name</param-name>
<param-value>zhangsan</param-value>
</context-param>
作用:
将静态数据和代码进行解耦
解耦:原本关系紧密的静态数据和代码,让关系变为藕断丝连
- 获取项目webroot/webcontent下的资源的绝对路径
String path=sc.getRealPath(String path);
获取的路径为项目根目录,path参数为项目根目录中的路径 - 获取 webroot 下项目资源流对象
InputStream is = sc.getResourceAsStream(String path);
注:
此种方式只能获取项目根目录下的资源流对象,class文件的流对象需要使用类加载器获取。path参数为项目根目录中的路径
生命周期
服务器启动到服务器关闭
具体代码实现
package com.youdian.servlet;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletContextServlet extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//获取ServletContext对象
//第一种方式:
ServletContext sc=this.getServletContext();
//第二种方式:
ServletContext sc2=this.getServletConfig().getServletContext();
//第三种方式:
ServletContext sc3=req.getSession().getServletContext();
System.out.println(sc==sc2);
System.out.println(sc==sc3);
//第一种和第三种比较常用,三种得到的是同一个对象
//使用ServletContext对象完成数据共享
//数据存储
sc.setAttribute("str", "ServletContext对象学习");
//获取项目web.xml的全局配置数据
String str = sc.getInitParameter("name");
System.out.println("全局配置参数:"+str);
//获取项目根目录下的资源的绝对路径
//String path="D:/MY/place2/ServletContext/WebRoot/text/text.txt";
//动态获取路径
String path=sc.getRealPath("/text/text.txt");
System.out.println(path);
//获取项目根目录下资源的流对象
InputStream is = sc.getResourceAsStream("/text/text.txt");
}
}
实例(网站计数器)
总结的相关知识点就是上面的,下面的内容是具体练习的有关代码,有兴趣的朋友可以继续看,有不同意见的可以留言讨论
使用ServletContext对象完成网页计数器,在用户登录校验中创建计数器并自增,然后存储到ServletContext对象中,在主页面里取出计数器数据显示给用户
- LoginServlet中需要在重定向之前,让计数器加1操作
//获取计数器对象
ServletContext sc=this.getServletContext();
if(sc.getAttribute("nums")!=null){
int nums=Integer.parseInt
((String)sc.getAttribute("nums"));
//计数器进行自增
nums+=1;
//再次存储到ServletContext对象中
sc.setAttribute("nums", nums);
}else{
sc.setAttribute("nums", 1);
}
完整代码为:
package com.youdian.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.youdian.pojo.User;
import com.youdian.service.LoginService;
import com.youdian.service.impl.LoginServiceImpl;
public class LoginServlet extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//设置请求编码格式:
req.setCharacterEncoding("utf-8");
//设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
//获取请求信息
String uname=req.getParameter("uname");
//uname=new String(uname.getBytes("iso8859-1"),"utf-8");//使用String进行数据重新编码
String pwd=req.getParameter("pwd");
System.out.println(uname+":"+pwd);
//处理请求信息
//获取业务层对象
LoginService ls=new LoginServiceImpl();
User u=ls.checkLoginService(uname, pwd);//检验 用户名密码是否在数据库存在
System.out.println(u);
//响应处理结果
if(u!=null){
//创建Cookie信息实现三天免登录。
Cookie c=new Cookie("uid", u.getUid()+"");
//设置Cookie的有效期
c.setMaxAge(3*24*3600);
c.setPath("/login/ck");
//添加Cookie信息
resp.addCookie(c);
//将数据存储到session对象中
HttpSession hs=req.getSession();
hs.setAttribute("user",u);
//在重定向之前,让计数器加1操作
//获取计数器对象
ServletContext sc=this.getServletContext();
if(sc.getAttribute("nums")!=null){
int nums=Integer.parseInt((String) sc.getAttribute("nums"));
//计数器进行自增
nums+=1;
//再次存储到ServletContext对象中
sc.setAttribute("nums", nums);
}else{
sc.setAttribute("nums", 1);
}
//重定向
//第一个/相当于localhost:8086
//或者直接写别名也可以。main
resp.sendRedirect("/login/main");
//不要用请求转发,会造成表单重复提交
// req.getRequestDispatcher("main").forward(req, resp);
// return ;
}else{
//使用request对象实现不同servlet数据流转
req.setAttribute("str", "用户名或密码错误");
//请求转发
req.getRequestDispatcher("page").forward(req, resp);
return ;
}
}
}
- 在main主页中显示浏览次数
//获取网页浏览次数
int nums=(int) this.getServletContext().getAttribute("nums");
resp.getWriter().write("当前网页浏览次数是:"+nums);
完整代码为:
package com.youdian.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.youdian.pojo.User;
public class MainServlet extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//设置请求编码格式
req.setCharacterEncoding("utf-8");
//设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
//获取请求信息
//获取session中的数据
User u=(User) req.getSession().getAttribute("user");
//获取网页浏览次数
int nums=(int) this.getServletContext().getAttribute("nums");
//处理请求信息
//响应处理结果
resp.getWriter().write("<html>");
resp.getWriter().write("<head>");
resp.getWriter().write("</head>");
resp.getWriter().write("<body>");
resp.getWriter().write("<h3>欢迎"+u.getUname()+"访问我的系统</h3>");
resp.getWriter().write("当前网页浏览次数是:"+nums);
resp.getWriter().write("<hr>");
resp.getWriter().write("<form action='show' method='get'>");
resp.getWriter().write("<input type='submit' value='查看个人信息'>");
resp.getWriter().write("</form>");
resp.getWriter().write("</body>");
resp.getWriter().write("</html>");
}
}
- 重定向之前需要进行计数器操作
//网页计数器自增
int nums=(int) this.getServletContext().getAttribute("nums");
nums+=1; this.getServletContext().setAttribute("nums",nums );
完整代码如下:
package com.youdian.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.youdian.pojo.User;
import com.youdian.service.LoginService;
import com.youdian.service.impl.LoginServiceImpl;
public class CookieServlet extends HttpServlet {
protected void service(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
// 设置请求编码格式
req.setCharacterEncoding("utf-8");
// 设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
// 获取请求信息
// 获取Cookie信息
Cookie[] cks = req.getCookies();
// 处理请求信息
if (cks != null) {
// 遍历Cookie信息
String uid = "";
for (Cookie c : cks) {
if ("uid".equals(c.getName())) {
uid = c.getValue();
}
}
// 校验UID是否存在
if ("".equals(uid)) {
// 请求转发
req.getRequestDispatcher("page").forward(req, resp);
return;
} else {
// 校验UID用户信息
// 获取业务层对象
LoginService ls = new LoginServiceImpl();
User u = ls.checkUidService(uid);
if (u != null) {
// 将用户数据存储到session对象中
req.getSession().setAttribute("user", u);
// 网页计数器自增
int nums = (int) this.getServletContext().
getAttribute(
"nums");
nums += 1;
this.getServletContext().setAttribute
("nums", nums);
// 重定向
resp.sendRedirect("/login/main");
return;
} else {
// 请求转发
req.getRequestDispatcher("page").
forward(req, resp);
return;
}
}
} else {
// 响应处理结果
// 请求转发
req.getRequestDispatcher("page").forward(req, resp);
return;
}
}
}
- 在webroot/webcontent下建立新的文件夹nums,在文件夹下建立nums.txt文件,并在web.xml中配置
<load-on-startup>2 </load-on-startup>
相关完整代码如下:
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>NumServlet</servlet-name>
<servlet-class>com.youdian.servlet.NumServlet</servlet-class>
<load-on-startup>2
</load-on-startup>
</servlet>
注:服务器关闭时存储到文本文件nums.txt中,服务器启动时读入数据,其中NumServlet的init初始化方法需要在服务器一启动就初始化
5. 建立新的.java文件,其中覆写init()和destroy()方法。服务器启动时,初始化计数器,服务器关闭时,销毁计数器,即读入.txt文件
package com.youdian.servlet;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class NumServlet extends HttpServlet {
//覆写init初始化方法,将数据读取到ServletContext对象中
public void init() throws ServletException {
//获取文件中的计数器数据
//获取文件路径
String path=this.getServletContext().getRealPath("/nums/nums.txt");
//声明流对象
FileReader fr=null;
BufferedReader br=null;
try{
fr=new FileReader(path);
br=new BufferedReader(fr);
String nums=br.readLine();
this.getServletContext().setAttribute("nums", nums);
}catch(Exception e) {
e.printStackTrace();
}finally{
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//覆写销毁方法,存储计数器到文件中
public void destroy() {
//获取网页计数器
int nums =(int) this.getServletContext().getAttribute("nums");
//获取文件路径
String path=this.getServletContext().getRealPath("/nums/nums.txt");
//声明流对象
BufferedWriter bw=null;
FileWriter fw=null;
try{
fw=new FileWriter(path);
bw=new BufferedWriter(fw);
bw.write(nums+"");
bw.flush();
}catch(Exception e) {
e.printStackTrace();
}finally{
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}