一、ServletContext是什么?
WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。
域对象: 在一个可以被看见的范围内共享数据用到对象
作用范围: 整个web应用范围内共享数据
生命周期: 当服务器启动web应用加载后创建出ServletContext对象后,域产生。当web应用被移除出容器或服务器关闭,随着web应用的销毁域销毁。
二、 ServletContext的应用:
1.做为域对象可以在整个web应用范围内共享数据。就是说可以写多个servlet,之间可以共享变量。
public class ServletTest01 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext context = this.getServletContext();
context.setAttribute("name", "smyhvae");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
另一个servlet可以拿到这个数据
public class ServletTest02 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext context = this.getServletContext();
String myName = (String) context.getAttribute("name");
System.out.println(myName);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2、获取WEB应用的初始化参数
这个有点熟悉,因为通过ServletConfig的getInitParameter()方法,通过 <init-param>
标签为某一个单独的servlet加配置信息,这种配置信息在其他的Servlet中是无法访问到的。可如果我们使用<context-param>
标签(与Servlet标签并列)为整个Web应用配置属性的话,那所有的Servlet就都能访问里面的参数了。例如:可以把数据库的配置信息放在这里。
public class ServletTest03 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext context = this.getServletContext(); // 得到上下文对象
// 获取单个的Context里面的初始化参数
String value1 = context.getInitParameter("username");
String value2 = context.getInitParameter("password");
System.out.println(value1 + ";" + value2);
System.out.println();
// 一次性获取Context里所有的初始化参数
Enumeration enumeration = context.getInitParameterNames();
while (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String value = context.getInitParameter(name);
System.out.println(name + ";" + value);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3、实现Servlet的转发
/**
* ServletContext实现请求转发
*/
public class ServletTest04 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher = this.getServletContext()
.getRequestDispatcher("/servlet/ServletTest05");// 参数中写虚拟路径
dispatcher.forward(request, response); // 执行完这一行代码后,将会跳到ServletTest05中去执行。
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
4.加载资源文件
4.1在Servlet中读取资源文件时
在Servlet中指定相对路径,指的是 【当前程序启动的目录下】 里面的路径。所以,在web环境下,就是tomcat启动的目录即tomcat/bin。
指定绝对路径是可以找到,但是只要一换发布环境,这个硬盘路径很可能是错误的,同样不行。
为了解决这样的问题,ServletContext提供了getRealPath方法,在这个方法中传入一个路径,这个方法的底层会在传入的路径的前面拼接当前web应用的硬盘路径,从而得到当前资源的硬盘路径,这种方式即使换了发布环境,方法的底层也能得到正确的web应用的路径从而永远都是正确的资源的路径。代码如下:
this.getServletContext().getRealPath("config.properties")
public class ServletTest06 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Properties prop = new Properties(); // 注意导的包是import java.util.Properties;
prop.load(new FileReader(this.getServletContext().getRealPath("config.properties")));
System.out.println(prop.getProperty("username"));
System.out.println(prop.getProperty("password"));
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
这样,就可以获取到WebRoot的根目录下的资源文件config.properties
4.2 在很多情况下,Servlet中并不会处理大量的逻辑,而是直接调用其他的java代码,service等等,如果在service中去加载资源文件,前面的那个方法就不行了,那就涉及到了下面的这个问题:
如果在非Servlet环境下要读取资源文件时可以采用类加载器加载文件的方式读取资源:MyService.class.getClassLoader().getResource("…/…/…/config.properties").getPath()
那现在getResource()里面的路径该怎么写呢?只要记住一句话:类加载器从哪里加载类,就从哪里加载资源。
比如说,有一个servlet调用了一个service(这里没写,没有其他操作,就仅仅是调用service)
public class MyService {
public void method() throws FileNotFoundException, IOException{
//在没有ServletContext的环境下,如果想要读取资源,可以使用类加载器以加载类的方式加载资源,
//这里要注意,类加载器从哪个目录加载类,就从哪个目录加载资源,
//所以此处的路径一定要给一个相对于类加载目录的路径
Properties prop = new Properties();
prop.load(new FileReader(MyService.class.getClassLoader().getResource("config.properties").getPath()));
System.out.println(prop.getProperty("username"));
System.out.println(prop.getProperty("password"));
}
}
这个MyService.class.getClassLoader().getResource("config.properties").getPath()
类加载的目录就是发布项目里的WEB-INF目录下的classes目录。
这下就好理解了,比如:
如果config.properties文件放在src目录下,那路径为:getResource(“config.properties”)
如果config.properties文件放在com.four.test包下,那路径为:getResource(“com/four/test/config.properties”)
如果此时config.properties文件和classes文件并列:
那路径为:getResource("…/config.properties") 注:"…/"表示上一级目录。