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; } }