web容器在启动时,为每个web应用都创建了一个对应的ServletContext对象,所以ServletContext对象就代表着当前的web应用,在停掉服务器或删除某个web应用时,ServletContext对象就会销毁
获取ServletContext对象的方法
1、调用getServletConfig()方法的getServletContext()方法
ServletContext context = this.getServletConfig().getServletContext();
2、直接调用getServletContext()方法
ServletContext context = this.getServletContext();
ServletContext方法的应用
1、通过ServletContext实现数据共享:
一个web应用中所有的Servlet共用同一个ServletContext对象,所以多个Servlet通过一个ServletContext对象实现数据共享,ServletContext对象又被成为context域对象。
ServletContext域:这是一个容器,说明了容器的作用范围,即web应用程序的范围。
在一个Servlet文件ServletDemo1中写如下代码
String data = "aaa";
this.getServletContext().setAttribute("data", data);
要实现数据共享,另一个Servlet文件ServletDemo2必须getAttribute(String name),才能获得所需要的数据
String value = (String) this.getServletContext().getAttribute("data");
System.out.println("data:"+value);
实际开发中,用于聊天室的开发
2、获取web应用的初始化参数
web.xml文件中添加<context-param>
元素,即为整个web应用配置初始化参数,服务器在加载web应用时,就自动配置了初始化参数,在ServletContext对象创建出来时,就自动被封装到ServletContext对象中,这时候只需要直接取这些初始化参数就行。
web.xml文件配置:
<context-param>
<param-name>data</param-name>
<param-value>xxxx</param-value>
</context-param>
ServletDemo中获得初始化参数(与ServletConfig类似):
this.getServletContext().getInitParameter("data");
实际开发中,用于连接数据库,url,username,password
3、实现Servlet的转发
首先搞清楚转发和重定向的区别:
- 转发:一次请求,一次响应。地址栏的url不会改变。在服务器端执行,所以必须在同一台服务器上。转发速度快。
- 重定向:两次请求。地址栏的url会随之改变为定向后的那个url。在客户端执行,所以可以在不同的服务器上。重定向速度慢。
通俗的来讲,这就类似于借钱,转发类似于,A找B借钱,B没有,B帮忙找到C借钱;重定向类似于,A找B借钱,B没有,B让A自己去找C借钱,其中一个是由服务器执行,只有一次url,客户机只有一次请求,另一个是由客户端执行,url由原来的url变成了一个新的url,客户机请求了两次,所以转发速度快,重定向速度慢,转发实际应用比重定向多。
4、利用ServletContext对象读取资源文件
软件开发中写配置文件,类型:.xml或.properties,若数据有关系,用.xml文件,数据没有关系,用.properties文件
如:数据库连接,用.properties文件,在src上点击新建file,新建db.properties文件,输入url,username,password
url=jdbc:mysql://localhost:3306/test
username=root
password=root
要读取该资源文件,通过getServletContext()方法,获取该web应用,然后通过getResourceAsStream()方法,获得该web应用下资源文件的路径,不提倡直接使用FileInputStream()方法读取,这样用相对路径获取的是相对web服务器启动程序的路径,麻烦。
新建Servlet文件,ServletDemo3,要根据db.properties文件放在不同的位置设置不同的路径,因为我的db.properties文件在tomcat的/webapps/TestServlet2/WEB-INF/CLASSES目录下,所以代码如下
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(in);
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
System.out.println(url);
System.out.println(username);
System.out.println(password);
如果必须要使用FileInputStream读取资源文件,就要先通过:
getServletContext()获得该web应用,然后调用getRealPath()方法获得db.properties资源文件在硬盘上的绝对路径,然后再读取,代码如下
String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties"); //获得资源文件的绝对路径
FileInputStream in = new FileInputStream(path);
Properties prop = new Properties();
prop.load(in);
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
System.out.println(url);
System.out.println(username);
System.out.println(password);
该方法可用于下载文件,可以得到资源名称
String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");
String filename = path.substring(path.lastIndexOf("\\")+1);
System.out.println("资源名字是:"+filename);
普通java程序读取资源文件
我们一般需要操作数据库时,不直接在Servlet文件中操作数据库,而是调用UserDao的update()方法来操作数据库,所以要先新建UserDao类,放在com.servlet.dao包中。
package com.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.servlet.dao.UserDao;
public class ServletDemo7 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
UserDao dao = new UserDao();
dao.update();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
如果读取资源文件的程序不是Servlet,只能通过类装载器来读取资源文件
如下,新建UserDao.java文件
package com.servlet.dao;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class UserDao {
private static Properties dbconfig = new Properties();
static {
try {
InputStream in = UserDao.class.getClassLoader().getResourceAsStream("db.properties");
dbconfig.load(in);
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
public void update() {
String url = dbconfig.getProperty("url");
}
}
注:通过类装载器读取资源文件时,会把文件load到内存中,所以文件不能太大,以防内存溢出。这种方法虽然可以读取到资源文件中的数据,但是在数据更新后,它不可以读取到更新后的数据,因为类装载器只加载了一次,之后不会再重新加载。
如果要读取到更新后的资源文件的数据,不能通过类装载器读取,要通过FileInputStream流读取,这就需要先通过类装载器读取到文件位置,再读取文件中的数据,代码如下:
package com.servlet.dao;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class UserDao {
public void update() {
String path = UserDao.class.getClassLoader().getResource("db.properties").getPath();
FileInputStream in = null;
try {
in = new FileInputStream(path);
Properties dbconfig = new Properties();
dbconfig.load(in);
String url = dbconfig.getProperty("url");
System.out.println(url);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}