[Servlet]研究ServletContext对象

ServletContext概述

ServletContext对象是Servlet三大域对象之一,每个Web应用程序都拥有一个ServletContext对象,该对象是Web应用程序的全局对象或者上下文。Tomcat服务器在启动时,会自动创建一个ServletContext对象,在关闭时,会自动销毁这个ServletContext对象。每个Web应用程序只拥有一个ServletContext对象,ServletContext对象可以在整个Web应用中共享数据资源。

下列是ServletContext提供的方法列表:

Method Summary
Object getAttribute(String name)
Enumeration getAttributeNames()
String getInitParameter(String name)
Enumeration getInitParameterNames()
String getMimeType(String file)
String getRealPath(String path)
String getServletContextName()
Enumeration getServletNames()
void log(String msg)
void removeAttribute(String name)
void setAttribute(String name, Object object)

获取ServletContext对象

在自定义Servlet中有以下几种方式获取到ServletContext对象:

  • 通过ServletConfig对象的getServletContext()方法获取。
  • 通过继承GenericServlet类或HttpServlet类,调用GenericServlet类或HttpServlet类的getServletContext()方法获取。

我们通过一个案例来讨论一下。

  • 首先,创建一个自定义Servlet,用来获取ServletContext对象。
public class AServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        ServletConfig config = getServletConfig();
        ServletContext context1 = config.getServletContext();
        context1.log("这是通过ServletConfig对象获取到的ServletContext对象.");
        ServletContext context2 = getServletContext();
        context2.log("这是通过继承GenericServlet类获取到的ServletContext对象.");
    }
}
  • 在web.xml文件中配置Servlet相关信息。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>AServlet</servlet-name>
    <servlet-class>app.java.context.AServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>AServlet</servlet-name>
    <url-pattern>/servlet/AServlet</url-pattern>
  </servlet-mapping>
</web-app>

这里写图片描述

  • 通过ServletContext对象的log(Stirng msg)方法,可以向控制台打印信息。

配置全局初始化参数

在web.xml文件中,使用定义的初始化参数,只能在当前Servlet中使用,而其他Servlet是无权限访问当前Servlet下配置的初始化参数的。而可以使用ServletContext在web.xml文件中配置全局初始化参数,这样当前Web应用程序中的所有Servlet都可以访问。

  • 在web.xml文件中使用<context-param>来定义全局初始化参数。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <context-param>
    <param-name>weixin</param-name>
    <param-value>longestory</param-value>
  </context-param>
  <servlet>
    <servlet-name>AServlet</servlet-name>
    <servlet-class>app.java.context.AServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>AServlet</servlet-name>
    <url-pattern>/servlet/AServlet</url-pattern>
  </servlet-mapping>
  <servlet>
    <servlet-name>BServlet</servlet-name>
    <servlet-class>app.java.context.BServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>BServlet</servlet-name>
    <url-pattern>/servlet/BServlet</url-pattern>
  </servlet-mapping>
</web-app>
  • 在两个自定义Servlet中,分别利用ServletContext对象获取全局初始化参数。
public class BServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        ServletContext context = getServletContext();

        String weixin = context.getInitParameter("weixin");
        System.out.println(weixin);
    }
}

在自定义Servlet中,可以通过ServletContext对象的getInitParameter(String name)方法获取对应参数名称的全局初始化参数值,也可以通过ServletContext对象的getInitParameterNames()方法获取所有全局初始化参数的名称。

还可以通过ServletContext对象的getMineType(String file)方法根据文件扩展名获取文件MIME类型。

public class BServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        ServletContext context = getServletContext();

        String html = context.getMimeType("1.html");
        String css = context.getMimeType("2.css");
        String javascript = context.getMimeType("3.js");
        System.out.println("HTML的文件类型为"+html+", CSS的文件类型为"+css+", javascript的文件类型为"+javascript);
    }
}

发布Web应用程序,并启动Tomcat服务器,在控制台中打印:

HTML的扩展名为text/html, CSS的扩展名为text/css, javascript的扩展名为application/javascript

ServletContext对象的getMineType(String file)方法会自动读取Tomcat安装目录中conf目录中的web.xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <mime-mapping>
        <extension>html</extension>
        <mime-type>text/html</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>css</extension>
    <mime-type>text/css</mime-type>
</mime-mapping>
    <mime-mapping>
        <extension>js</extension>
        <mime-type>application/javascript</mime-type>
</mime-mapping>
</web-app>

多个Servlet共享数据

在同一个Web应用程序中,多个Servlet之间可以共享ServletContext对象中的数据信息。主要是通过ServletContext对象的setAttribute(String name, Object object)方法和getAttribute(String name)方法完成,下面我们来实现统计网站访问次数的案例。

  • 创建一个VisitServlet用来获取访问次数,并存储在ServletContext对象中。
public class VisitServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        ServletContext context = getServletContext();
        context.setAttribute("times", 0);
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext();

        int times = (Integer)context.getAttribute("times");
        times ++;
        context.setAttribute("times", times);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 创建一个ShowTimeServlet用来显示访问次数。
public class ShowTimeServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext();

        int times = (Integer)context.getAttribute("times");

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println("<h1>VisitServlet共被访问了"+times+"次</h1>");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 配置web.xml文件中有关Servlet信息。
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>VisitServlet</servlet-name>
    <servlet-class>app.java.context.VisitServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>ShowTimeServlet</servlet-name>
    <servlet-class>app.java.context.ShowTimeServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>VisitServlet</servlet-name>
    <url-pattern>/visit</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ShowTimeServlet</servlet-name>
    <url-pattern>/show</url-pattern>
  </servlet-mapping>
</web-app>

这里写图片描述

读取Web工程中资源文件

读取工程中的资源文件,Java中的IO流其实就可以完成,下面使用Java中的IO流完成读取资源文件。

  • 首先在Web工程中,创建四个资源文件。
    • 在Web工程的根目录下创建1.txt。
    • 在Web工程的WebRoot目录下创建2.txt。
    • 在Web工程的WebRoot目录的WEB-INF目录下创建3.txt。
    • 在Web工程的src目录下创建4.txt。
  • 创建一个Java文件用于读取上述的四个资源文件。
public class ReaderFileTest {
    // 编写readfile()方法完成资源文件的读取工作.
    public static void readfile(String fileName) throws Exception{
        BufferedReader reader = new BufferedReader(new FileReader(fileName));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        reader.close();
    }

    public static void main(String[] args) throws Exception {
        // 读取1.txt
        String filename1 = "1.txt";
        readfile(filename1);
        // 读取2.txt
        String filename2 = "WebRoot/2.txt";
        readfile(filename2);
        // 读取3.txt
        String filename3 = "WebRoot/WEB-INF/3.txt";
        readfile(filename3);
        // 读取4.txt
        String filename4 = "src/4.txt";
        readfile(filename4);
    }
}
  • 运行该Java文件会在控制台打印响应信息。

这里写图片描述

如果要想利用Servlet API的内容来读取Web工程中的资源文件,又要如何来做呢?ServletContext对象的getRealPath()方法可以来完成此项工作。

  • 创建一个自定义Servlet,使用ServletContext对象的getRealPath()方法来完成读取资源文件。
public class ReadFileServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        OutputStream out = response.getOutputStream();
        /*
         *  读取1.txt
         *   * 因为1.txt资源文件在Web工程的根目录.
         *   * Web工程的WebRoot目录发布到Tomcat服务器.
         *   * 所以,1.txt资源文件是不会发布到Tomcat服务器的,Servlet无法读取.
         */
        // 读取2.txt
        String filename2 = getServletContext().getRealPath("/2.txt");
        InputStream in2 = new FileInputStream(new File(filename2));
        IOUtils.copy(in2, out);
        // 读取3.txt
        String filename3 = getServletContext().getRealPath("/WEB-INF/3.txt");
        InputStream in3 = new FileInputStream(new File(filename3));
        IOUtils.copy(in3, out);
        // 读取4.txt
        String filename4 = getServletContext().getRealPath("/WEB-INF/classes/4.txt");
        InputStream in4 = new FileInputStream(new File(filename4));
        IOUtils.copy(in4, out);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 发布Web应用程序到Tomcat服务器,并启动Tomcat服务器。
  • 打开浏览器,在地址栏中分别输入http://localhost:8080/08_servlet/read,在控制台打印相关信息。

这里写图片描述

除了可以使用ServletContext对象的getRealPath()方法之外,还可以使用ServletContext对象的getResourceAsStream()方法来完成读取资源文件的工作。

public class ReadFileServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse 
response) throws ServletException, IOException {
        InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/4.txt");
        IOUtils.copy(in, out);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

还有一种通用的方法:利用Class类的getResource()方法也可以完成读取资源文件的工作。

public class ReadFileServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 利用类加载器读取Web工程的资源文件
        String filename = ReadFileServlet.class.getResource("/4.txt").getFile();
        InputStream in = new FileInputStream(new File(filename));
        IOUtils.copy(in, out);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

转载说明:请注明作者及原文链接,谢谢!

原文地址:https://www.cnblogs.com/longestory/p/4566967.html