1. ServletConfig
在web.xml配置文件中,<servlet>元素中有一个子元素叫<init-param>,可以使用一个或多个<init-param>元素为该servlet配置一些初始化参数。当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init(ServletConfig config)方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
例如在web.xml文件中配置如下信息:
<servlet>
<description></description>
<display-name>ServletDemo5</display-name>
<servlet-name>ServletDemo5</servlet-name>
<servlet-class>com.oner.Servlet5</servlet-class>
<init-param>
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>database_url</param-name>
<param-value>jdbc:mysql://192.168.80.101:3306/test</param-value>
</init-param>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>password</param-value>
</init-param>
<init-param>
<param-name>config</param-name>
<param-value>/struts-config.xml</param-value>
</init-param>
</servlet>
编写程序获取这些参数:
package com.oner;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Servlet5 extends HttpServlet {
private static final long serialVersionUID = 1L;
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 得到ServletConfig对象
ServletConfig config = this.getServletConfig();
// 得到指定的参数
String value1 = config.getInitParameter("username");
System.out.println(value1);
// 得到所有的参数
Enumeration enu = config.getInitParameterNames();
while (enu.hasMoreElements()) {
String pname = (String) enu.nextElement();
String value2 = config.getInitParameter(pname);
System.out.println(pname + "=" + value2);
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
运行结果:
一般在以下情况下可以考虑使用ServletConfig:servlet采用哪个字符集编码、servlet连接哪个数据库,servlet连接数据库的用户名和密码、servlet读取某个配置文件。
2. ServletContext
WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。也可以直接通过servlet对象的getServletContext方法得到ServletContext对象。
由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。
下面来列出ServletContext的一些应用:
2.1 获取Web应用的初始化参数
在web.xml配置文件中,使用<context-param>元素可以配置这个Web的一些初始化参数。当Web服务器加载这个Web应用时,会自动将这些初始化参数封装到ServletContext对象中。所以可以使用ServletContext来得到Web应用的初始化参数。
例如在web.xml文件中配置如下信息:
<context-param>
<param-name>data</param-name>
<param-value>hello ServletContext!</param-value>
</context-param>
<context-param>
<param-name>data2</param-name>
<param-value>hello ServletContext2!</param-value>
</context-param>
编写程序获取这些参数:
package com.oner;
import java.io.IOException;
import java.util.Enumeration;
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 ServletDemo9 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 得到ServletContext对象
ServletContext context = this.getServletContext();
// 得到指定参数
String value = context.getInitParameter("data");
System.out.println(value);
// 得到所有参数
Enumeration enu = context.getInitParameterNames();
while (enu.hasMoreElements()) {
String pname = (String) enu.nextElement();
String value2 = context.getInitParameter(pname);
System.out.println(pname + "=" + value2);
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
测试结果:
可以将该Web应用下多个Servlet都需要连接的数据库信息配置到<context-param>元素中,这样就可以避免多次在<servlet>元素的子元素<init-param>中配置。
2.2 多个Servlet实现数据共享
下面要实现ServletDemo7和ServletDemo8这两个Servlet数据共享:
ServletDemo7.java
package com.oner;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo7 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String data = "hello ServletContext!";
this.getServletContext().setAttribute("data", data);
String name = this.getServletName();
response.getOutputStream().write((data + "..." + name).getBytes());
System.out.println(data + "..." + name);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
ServletDemo8.java
package com.oner;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 多个servlet通过servletContext实现数据共享
* @author Oner.wv
*
*/
public class ServletDemo8 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String data = (String) this.getServletContext().getAttribute("data");
String name = this.getServletName();
response.getOutputStream().write((data + "..." + name).getBytes());
System.out.println(data+"..."+name);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
验证:
先访问ServletDemo8,浏览器页面和控制台都得到“null...ServletDemo8”这样的结果,这是由于ServletDemo7这个Servlet还没有运行,也就没有设定ServletContext对象的属性,所以得到null:
这时访问ServletDemo7,浏览器界面得到了“hello ServletContext!...ServletDemo7”内容,控制台也输出了相同的内容:
再次访问ServletDemo8,这时候就得到了“hello ServletContext!”的内容:
2.3 实现Servlet的转发
例如要实现一个转发功能:当浏览器访问ServletDemo10这个Servlet时,将转发到ServletDemo8这个Servlet。
ServletDemo10.java
package com.oner;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
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 ServletDemo10 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String data = "Servlet要转发的资源!";
ServletContext context = this.getServletContext();
context.setAttribute("data", data);
RequestDispatcher rd = context.getRequestDispatcher("/ServletDemo8");
rd.forward(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
ServletDemo8.java
package com.oner;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo8 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String data = (String) this.getServletContext().getAttribute("data");
String name = this.getServletName();
response.getOutputStream().write((data + "..." + name).getBytes());
// System.out.println(data+"..."+name);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
将ServletDemo10和ServletDemo8部署到Tomcat服务器,用浏览器访问ServletDemo10:
由运行结果可以看出最后是浏览器访问ServletDemo10,ServletDemo10调用forward()方法,将请求转发给ServletDemo8。
这里需要注意的是Servlet转发和重定向的区别:servlet的转发与重定向
2.4 读取Web应用的资源文件
在Servlet中直接读取配置文件:
package com.oner;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//通过ServletContext读取web资源文件
public class ServletDemo11 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// test1();
// test2();
// test3();
test4();
}
// 获取web资源的绝对路径
private void test4() throws IOException {
// 获取web资源的绝对路径
String path = this.getServletContext().getRealPath(
"/WEB-INF/classes/db.properties");
System.out.println(path);
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);
}
// 当资源文件在WebContent目录下时
private void test3() throws IOException {
// 得到输入流对象
InputStream in = this.getServletContext().getResourceAsStream(
"/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);
}
// 当资源文件在src/com/oner目录下时
private void test2() throws IOException {
// 得到输入流对象
InputStream in = this.getServletContext().getResourceAsStream(
"/WEB-INF/classes/com/oner/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);
}
// 当资源文件在src目录下时
private void test1() throws IOException {
// 得到输入流对象
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);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
使用dao读取配置文件:
ServletDemo12.java
package com.oner;
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.oner.dao.UserDao;
public class ServletDemo12 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
UserDao dao = new UserDao();
dao.update();
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
UserDao.java
package com.oner.dao;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
//如果读取资源文件的程序不是Servlet的话,就只能通过类装载器读取
public class UserDao {
public void update() throws IOException {
// 以下代码虽然可以读取资源文件,但是无法读取到更新后的数据,因为类装载器只会装载一次文件
// InputStream in = this.getClass().getClassLoader()
// .getResourceAsStream("db.properties");
// Properties prop = new Properties();
// prop.load(in);
//
// System.out.println(prop.getProperty("url"));
// 通过类装载的方式得到资源文件的位置,再通过传统方式读取资源文件的数据,就可以读取到更新后的数据了
String path = this.getClass().getClassLoader()
.getResource("db.properties").getPath();
InputStream in = new FileInputStream(path);
Properties prop = new Properties();
prop.load(in);
}
}