Servlet 9—— ServletContext

javax.servlet.ServletContextSUN制定的接口,apacheServletContext接口的实现类完整类名:org.apache.catalina.core.ApplicationContextFacade,但是程序员不需要关心具体的类名,直接面向ServletContext接口调用方法即可。

1、如何获取ServletContext对象呢?

通过ServletConfig对象获取ServletContext对象a

ServletContext application = config.getServletContext();

2、ServletContext代表什么?什么时候被创建?什么时候被销毁?

一个webapp只有一个web.xml文件,ServletContextTomcat服务器启动阶段解析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;
        }
      }
  • ServletServletConfigServletContext三个对象内存关系图:

结论:一个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;
    }
}

 

转载请注明出处:https://www.cnblogs.com/stu-jyj3621
原文地址:https://www.cnblogs.com/stu-jyj3621/p/14359680.html