ServletContext
一个项目只有ServletContext一个对象!所以在创建这个对象时经常起application这个名字。多个Servlet获取的是唯一的这个对象。它可以给多个Servlet传递数据,将多个Servlet串在一起,所以称之为上下文对象。特性:与天地同寿!与Tomcat同生共死
1. ServletContext概述
服务器会为每个应用创建一个ServletContext对象:
- ServletContext对象的创建是在服务器启动时完成的
- ServletContext对象的销毁是在服务器关闭时完成的
ServletContext对象的作用是在整个Web应用的动态资源之间共享数据。例如,AServlet向ServletContext对象中保存一个值,然后咋BServlet中就可以获取这个值了,这就是数据共享。
2. 获取ServletContext对象
在Servlet中获取ServletContext对象:
- 在init()方法中的servletConfig:
ServletContext context = getServletConfig().getServletContext();
ServletConfig类的getServletContext()方法来获取;
在GenericServlet或HttpServlet中获取ServletContext对象:
- 这两个类中有写好的获取ServletContext对象的方法,可以直接使用
this.getServletContext()
方法;
3. 域对象的功能
ServletContext是JavaWeb四大域对象之一:
- PageContext
- ServletContext
- HttpSession
- ServletRequest
域对象就是在多个Servlet中传递数据的!所有域对象都有保存数据的功能,因为域对象的内部只有一个Map来存储数据,下面是ServletContext对象用来操作数据的方法(内部其实就是一个Map):
void setAttribute(String name,Object value)
:用来存储一个对象,也可以称之为存储一个域属性,例如:servletContext.setAttribute("xxx","XXX")
,在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么就会覆盖上一次的值,这就是Map的特性;Object getAttribute(String name)
用来获取ServletContext中的数据,在获取之前要先存储才行。例如:String value = (String)servletContext.getAttribute("xxx");
;void removeAttribute(String name)
:用来移除ServletContext中的域属性,参数不存在,则什么都不做;Enumeration getAttributeNames()
:返回所有域属性的名称;
考虑一个这样的项目:有两个Servlet,一个向ServletContext中存数据,另外一个取出数据,再分两个请求:先请求第一个,再请求第二个;
FServlet用来存储:
public class FServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
1.获取ServletContext对象
2.调用其setAttribute方法来保存数据
*/ getServletContext().setAttribute("name","张三!");
}
}
GServlet用来取出:
public class GServlet extends HttpServlet {
/*
1.获取ServletContext对象
2.取出其中的数据
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String s = (String) getServletContext().getAttribute("name");
System.out.println("name"+": "+s);
}
}
打开浏览器在地址栏依次输入两个Servlet的URL,然后在GServlet上刷新四次页面就可以看到从ServletContext对象中取出的数据:
4. 获取应用初始化参数
- Servlet也可以获取初始化参数,但它是局部的参数;也就是说一个Servlet只能获取自己的初始化参数,不能获取别人的!
- 可以配置公共的初始化参数,为所有的Servlet而用!这就需要ServletContext来获取
还可以使用ServletContext来获取在web.xml文件中配置的应用初始化参数!注意:应用初始化参数与Servlet初始化参数不同;
在web.xml中添加一项如下:
<context-param>
<param-name>context-name</param-name>
<param-value>context-value</param-value>
</context-param>
在EServlet中写如下代码:
public class EServlet extends HttpServlet {
/*
演示ServletContext获取公共的初始化参数
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
1.获取ServletContext对象
2.获取公共初始化参数
*/
String value = getServletContext().getInitParameter("context-name");
System.out.println(value);
}
}
就可以看到公共初始化参数了(由参数的名字返回参数的值):
5. 获取资源相关方法
(1)
- 获取真实路径(重要):还可以使用ServletContext对象来获取web应用下的资源,例如在跟目录下创建一个a.txt文件,现在想在Servlet中获取这个资源,就可以使用ServletContext对象来获取
- 获取a.txt的真实路径:
String realPath = servletContext.getRealPath("a.txt");
则realPath值为a.txt的绝对路径; - 获取b的真实路径:
String realPath = servletContext.getRealPath("/WEB-INF/b.txt");
- 获取a.txt的真实路径:
方法演示1获取a.txt真实路径:
public class EServlet extends HttpServlet {
/*
获取资源路径
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
1.获取ServletContext对象
2.获取资源路径
*/
String s = getServletContext().getRealPath("a.txt");
System.out.println(s);
}
}
运行结果:
方法演示2获取b.txt真实路径(只有名称改变一下):
String s = getServletContext().getRealPath("/WEB-INF/b.txt");
运行结果:
(2)获取资源流:不仅可以获取资源路径,还可以资源流的形式获取数据
- 获取a.txt的资源流:
InputStream in = servletContext.getResourceAsStream("a.txt");
- 获取b.txt的资源流:
InputStream in = servletContext.getResourceAsStream("/WEB-INF/b.txt");
有两种方式与输入流关联:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
String s = getServletContext().getRealPath("/WEB-INF/b.txt");
System.out.println(s);
/*
两种方式获取这个资源
*/
InputStream in = new FileInputStream("s");
InputStream in1 = getServletContext().getResourceAsStream("/WEB-INF/b.txt");
(3)获取指定目录下所有资源路径
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Set<String> path = this.getServletContext().getResourcePaths("/WEB-INF");
System.out.println(path);
}
}
这就可以直接查看这个文件夹下的所有东西:
练习:访问量统计
一个项目中所有资源被访问都要对访问量进行累加(计数器):
- 创建一个int类型的计数器用来统计访问量,然后保存到ServletContext的域中!这样可以保证所有的Servlet都可以访问到
- 当本站被第一次访问时,创建这个计数器并设置为1,保存在ServletContext的域中
- 在以后的访问中,就从ServletContext的对象中获取并加1存储
public class EServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer count = (Integer)getServletContext().getAttribute("count");
if (count==null)
count = 1;
else
count++;
getServletContext().setAttribute("count",count);
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().print("<h1>本页面一共被访问"+count+"次!</h1>");
}
}
当第一次访问时:
刷新两次以后:
获取类路径下的资源
在src文件夹中有a.txt文件,想要读取其中的数据:由于项目src文件夹中东西会被拷贝到WEB-INF的classes文件夹中,所以路径直接写就可以
public class EServlet extends HttpServlet {
/*
获取资源路径
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ClassLoader ca = getClass().getClassLoader();
//ca.getResourceAsStream("a.txt");返回的是一个InputStream流
BufferedReader bufr = new BufferedReader(new InputStreamReader(ca.getResourceAsStream("a.txt");));
String s = null;
while((s=bufr.readLine())!=null){
System.out.println(s);
}
}
}
结果展示:
本人是菜鸟一枚,当做学习笔记写博客。谢谢各路大咖驻足审阅