javax.servlet.ServletContext是SUN制定的接口,apache对ServletContext接口的实现类完整类名:org.apache.catalina.core.ApplicationContextFacade,但是程序员不需要关心具体的类名,直接面向ServletContext接口调用方法即可。
1、如何获取ServletContext对象呢?
通过ServletConfig对象获取ServletContext对象a
ServletContext application = config.getServletContext();
2、ServletContext代表什么?什么时候被创建?什么时候被销毁?
一个webapp只有一个web.xml文件,ServletContext在Tomcat服务器启动阶段解析webapp中的web.xml文件的时候创建ServletContext对象,所以,对于同一个webapp来说,ServletContext对象只有一个。在服务器启动阶段被实例化,在Tomcat服务器关闭的时候ServletContext对象被销毁。
ServletContext对应的是web.xml文件,是web.xml文件的代表。
ServletContext代表“Servlet上下文”。ServletContext上下文指的是“所有Servlet对象共享的一个四周环境”对象。在同一个WEBAPP中,所有的Servlet对象共享一个ServletContext对象。存储在ServletContext对象中的数据所有的Servlet共享。ServletContext对象可以完成多个Servlet之间数据的传递。
3、ServletContext接口中常用的方法
向Servlet上下文中存储数据
application.setAttribute(String name,Object obj);
从Servlet上下文中读取数据
Object obj = application.getAttribute(String name);
删除Servlet上下文中的数据
application.removeAttribute(String name);
获取Servlet上下文参数所有的name
Enumeration<String> names = application.getInitParameterNames();
通过Servlet上下文参数的name获取value
String value = application.getInitParameter(String name);
通过ServletContext获取文件的绝对路径真实路径
String realPath = application.getRealPath(“/index.html”); 注意:必须保证webapp的根下有index.html
4、什么样的数据适合存储到ServletContext对象中?
- 很少的数据量
- 所有用户共享的数据
- 这些共享数据不涉及到修改操作,或者很少涉及到修改操作。
5、多线程环境下,什么情况下需要考虑线程并发带来的安全问题?
- 多线程环境下运行程序
- 有共享的数据
- 共享数据涉及到修改操作
6、解决线程安全问题有两种解决方案?
- 使用局部变量替代成员变量、静态变量,局部变量在栈中存储,栈内存不共享,成员变量在堆内存的java对象内部存储,堆内存是共享的,静态变量在方法区中存储,方法区内存也是多线程共享的。
- 使用线程同步机制:synchronized语法支持线程同步机制。(会使并发量降低,吞吐量降低)
7、Servlet 、ServletConfig、ServletContext之间的关系?
- 一个Servlet对应一个ServletConfig
- 100个Secvlet对应100个ServletConfig
- 所有的Servlet共享一个ServletContext对象
- Servlet、ServletConfig、ServletContext三个对象的代码关系如下所示
-
public class Servlet{ private ServletConfig config; public ServletConfig getServletConfig(){ return config; } } public class ServletConfig{ private ServletContext servletContext; public ServletContext getServletContext(){ return servletContext; } }
-
-
Servlet、ServletConfig、ServletContext三个对象内存关系图:
结论:一个Servlet对应一个ServletConfig对象,所有的Servlet对象共享一个ServletContext对象。
附1、到目前为止,所有编写过有关路径:
1、超链接
<a href="/wcbappname/doSome"></a>
2、web.xml中的url-pattern
<url-pattern>/doSome</url-pattern>
3、form表单的action属性
<form action="/webappname/doSome"></form>
4、ServletContext的getRealPath
application.getRealPath("/WEB-INF/resources/db.properties");
附2、案例
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ServletContext接口</title>
</head>
<body>
<a href="/Servlet-05/a">AServlet</a>
<br><br>
<a href="/Servlet-05/b">BServlet</a>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<!-- web.xml文件中配置上下文参数,这些信息会自动封装到ServletContext对象中 -->
<context-param>
<param-name>username</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123</param-value>
</context-param>
<servlet>
<servlet-name>AServlet</servlet-name>
<servlet-class>myweb.AServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AServlet</servlet-name>
<url-pattern>/a</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>BServlet</servlet-name>
<servlet-class>myweb.BServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BServlet</servlet-name>
<url-pattern>/b</url-pattern>
</servlet-mapping>
</web-app>
User.java
package myweb;
public class User {
private String usercode;
private String username;
public String getUsercode() {
return usercode;
}
public void setUsercode(String usercode) {
this.usercode = usercode;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User [usercode=" + usercode + ", username=" + username + "]";
}
}
AServlet.java
package myweb;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Enumeration;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class AServlet implements Servlet {
private ServletConfig config;
public AServlet() {
System.out.println("A");
}
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
// 获取ServletConfig
ServletConfig config = getServletConfig();
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("<html>");
out.print("<head>");
out.print("<title>AServlet</title>");
out.print("</head>");
out.print("<body>");
// 获取ServletContext
ServletContext application = config.getServletContext();
out.print("AServlet's ServletContext = " + application);
out.print("<br>");
// AServlet's ServletContext =
// org.apache.catalina.core.ApplicationContextFacade@74dbe7fe
// 获取上下文初始化参数的name
Enumeration<String> names = application.getInitParameterNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
// 通过上下文初始化参数的name获取value
String value = application.getInitParameter(name);
out.println(name + " = " + value);
out.print("<br>");
}
// 获取文件绝对路径
String realPath = application.getRealPath("/index.html");
out.print(realPath);
out.print("<br>");
out.print("</body>");
out.print("</html>");
// 创建user对象
User user = new User();
user.setUsercode("123");
user.setUsername("LiDanping");
// 想ServletContext范围中存储数据
application.setAttribute("userObj", user);
application.setAttribute("time", new Date());
}
@Override
public void destroy() {
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public String getServletInfo() {
return null;
}
}
BServlet.java
package myweb;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class BServlet implements Servlet {
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
// 获取ServletConfig
ServletConfig config = getServletConfig();
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("<html>");
out.print("<head>");
out.print("<title>BServlet</title>");
out.print("</head>");
out.print("<body>");
// 获取ServletContext
ServletContext application = config.getServletContext();
out.print("BServlet's ServletContext = " + application);
out.print("<br>");
// BServlet's ServletContext =
// org.apache.catalina.core.ApplicationContextFacade@74dbe7fe
// 从ServletContext范围中读取数据
Object obj = application.getAttribute("userObj");
out.print(obj);
out.print("<br>");
Object time = application.getAttribute("time");
out.print(time);
out.print("</body>");
out.print("</html>");
}
@Override
public void destroy() {
}
// 这个方法共子类使用的,在子类中若想获取ServletConfig,可以调用这个方法。
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
}