Web基础知识(4)- Java Servlet (四) | Servlet虚拟路径、ServletConfig、ServletContext


1. Servlet虚拟路径

    浏览器通过 URL 地址来访问 Web 服务器中的资源,Servlet 程序若想被外界访问,就必须被映射到一个 URL 地址上。很多时候,该 URL 地址和 Servlet 程序的物理路径(在硬盘上的存储位置)并不一致,因此它被称为虚拟路径。Servlet 与虚拟路径的对应关系就叫做 Servlet 虚拟路径映射。

    1)Servlet虚拟路径单一映射

        Servelt 单一映射是指一个 Servlet 只被映射到一个虚拟路径上。

        (1) 使用 web.xml 实现单一映射

            <servlet-mapping>
                <servlet-name>FourServlet</servlet-name>
                <url-pattern>/four</url-pattern>
            </servlet-mapping>

        (2) 使用 @WebServlet 实现单一映射

                @WebServlet("/four")

            或者:

                @WebServlet(urlPatterns = "/four")

    2)Servlet虚拟路径多重映射

        (1) 配置多个 <servlet-mapping> 元素

            <servlet-mapping>
                <servlet-name>FourServlet</servlet-name>
                <url-pattern>/four</url-pattern>
            </servlet-mapping>
            <servlet-mapping>
                <servlet-name>FourServlet</servlet-name>
                <url-pattern>/four/</url-pattern>
            </servlet-mapping>

        (2) 配置多个 <url-pattern> 子元素

            <servlet-mapping>
                <servlet-name>FourServlet</servlet-name>
                <url-pattern>/four</url-pattern>
                <url-pattern>/four/</url-pattern>
            </servlet-mapping>

        (3) 在 @WebServlet 的 urlPatterns 属性中使用字符串数组

            @WebServlet(urlPatterns = { "/four", "/four/" })

    3)Servlet虚拟路径匹配规则

        (1) 完全路径匹配

            以/开始,不能包含通配符*,必须完全匹配。例如:/four

        (2) 目录匹配

            以/字符开头,并以/*结尾的字符串,用于路径匹配。 例如:/*, /four/*
        
        (3) 扩展名匹配

            以通配符*.开头的字符串,用于扩展名匹配。 例如:*.action,*.jsp
        
        (4) 缺省匹配(默认匹配)

            映射路径为/,表示这个 Servlet 为当前应用的缺省 Servlet 或默认 Servlet,默认处理无法匹配到虚拟路径的请求。

        Servlet 虚拟路径的匹配优先级顺序为:

            全路径匹配(精确匹配)> 目录匹配 > 扩展名匹配 > 缺省匹配(默认匹配)。

        Servlet 容器会从优先级高的虚拟路径开始匹配,匹配成功后就会立刻将请求交给相应的 Servlet 进行处理,不会再关注其他虚拟路径是否匹配成功。

    4) Tomcat 中的缺省 Servlet

        在 Tomcat 安装目录的 \conf\web.xml 文件中,注册了一个名称为 org.apache.catalina.servlets.DefaultServlet 的 Servlet,并将它设置为缺省 Servlet。

        Tomcat 服务器中的 Web 应用没有缺省 Servlet 时,会将 DefaultServlet 作为其缺省 Servlet。当客户端访问 Tomcat 服务器中某个静态 HTML 文件或者图片时,DefaultServlet 会判断该 HTML 或图片是否存在,若存在,则将数据以流的形式返回客户端,否则会报告 404 错误。

2. ServletConfig接口

    Servlet 容器初始化 Servlet 时,会为这个 Servlet 创建一个 ServletConfig 对象,并将 ServletConfig 对象作为参数传递给 Servlet 。通过 ServletConfig 对象即可获得当前 Servlet 的初始化参数信息。

    一个 Web 应用中可以存在多个 ServletConfig 对象,一个 Servlet 只能对应一个 ServletConfig 对象,即 Servlet 的初始化参数仅对当前 Servlet 有效。

    1) 获得 ServletConfig 对象

        (1) 直接从带参的 init() 方法中提取

             public class FourServlet extends HttpServlet {
                private ServletConfig servletConfig;

                @Override
                public void init(ServletConfig config) throws ServletException {
                    this.servletConfig = config;
                }

                ...
            }

        (2) 调用 getServletConfig() 方法获得

            ServletConfig servletConfig = getServletConfig();

     2) ServletConfig 接口方法

          方法                                                 描述
        String getInitParameter(String name)             根据初始化参数名 name,返回对应的初始化参数值。
        Enumeration<String> getInitParameterNames()     返回 Servlet 所有的初始化参数名的枚举集合,如果该 Servlet 没有初始化参数,则返回一个空的集合。
        ServletContext getServletContext()                 返回一个代表当前 Web 应用的 ServletContext 对象。
        String getServletName()                         返回 Servlet 的名字,即 web.xml 中 <servlet-name> 元素的值。

    3) 配置 Servlet 初始化参数

        (1) 使用 web.xml 配置初始化参数

            在 web.xml 中可以使用一个或多个 <init-param> 元素为 Servlet 配置初始化参数,代码如下。

 1                 <!DOCTYPE web-app PUBLIC
 2                  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 3                  "http://java.sun.com/dtd/web-app_2_3.dtd" >
 4 
 5                 <web-app>
 6                   <display-name>Web Basic</display-name>
 7 
 8                   <servlet>
 9                     <servlet-name>FourServlet</servlet-name>
10                     <servlet-class>com.example.FourServlet</servlet-class>
11 
12                     <!-- Servlet 初始化参数 -->
13                     <init-param>
14                         <param-name>name</param-name>
15                         <param-value>WebBasic</param-value>
16                     </init-param>
17                     <init-param>
18                         <param-name>url</param-name>
19                         <param-value>www.webbasic.com</param-value>
20                     </init-param>
21 
22                   </servlet>
23                   <servlet-mapping>
24                     <servlet-name>FourServlet</servlet-name>
25                     <url-pattern>/four</url-pattern>
26                   </servlet-mapping>
27 
28                 </web-app>


            以上配置说明如下:

                <init-param> 元素是 <servlet> 的子元素,需要在 <servlet> 元素内使用,表示只对当前 Servlet 有效 。
                <param-name> 子元素表示参数的名称。
                <param-value> 子元素表示参数的值。

        (2) 使用 @WebServlet 配置初始化参数

            @WebServlet(asyncSupported = true,
                        name = "FourServlet",
                        description = "Four servlet description",
                        loadOnStartup = 5,
                        urlPatterns = { "/four" },
                        initParams = {
                            @WebInitParam(name = "name", value = "WebBasic"),
                            @WebInitParam(name = "url", value = "www.webbasic.com")
                        })
            public class FourServlet extends HttpServlet {

                ...

            }

    4) 读取 Servlet 初始化参数

        通过 ServletConfig 对象读取 Servlet 的初始化参数。

        示例:

 1             package com.example;
 2 
 3             import java.io.IOException;
 4             import java.io.PrintWriter;
 5 
 6             import javax.servlet.ServletConfig;
 7             import javax.servlet.ServletException;
 8             import javax.servlet.http.HttpServlet;
 9             import javax.servlet.http.HttpServletRequest;
10             import javax.servlet.http.HttpServletResponse;
11 
12             public class FourServlet extends HttpServlet {
13 
14                 protected void doGet(HttpServletRequest request, HttpServletResponse response)
15                         throws ServletException, IOException {
16 
17                     ServletConfig config = getServletConfig();
18                     PrintWriter writer = response.getWriter();
19                     response.setContentType("text/html;charset=UTF-8");
20 
21                     writer.write(config.getServletName() + " -> doGet()<br/>");
22                     writer.write("name: " + config.getInitParameter("name") + "<br/>");
23                     writer.write("url: " + config.getInitParameter("url") + "<br/>");
24                     writer.close();
25 
26                 }
27 
28                 protected void doPost(HttpServletRequest request, HttpServletResponse response)
29                         throws ServletException, IOException {
30                 }
31 
32             }


        输出:
            
            name: WebBasic
            url: www.webbasic.com

3. ServletContext接口

    Servlet 容器启动时,会为每个 Web 应用(webapps 下的每个目录都是一个 Web 应用)创建一个唯一的 ServletContext 对象,该对象一般被称为“Servlet 上下文”。

    ServletContext 对象的生命周期从 Servlet 容器启动时开始,到容器关闭或应用被卸载时结束。

    Web 应用中的所有 Servlet 共享同一个 ServletContext 对象,不同 Servlet 之间可以通过 ServletContext 对象实现数据通讯,因此 ServletContext 对象也被称为 Context 域对象。

    域对象是服务器在内存上创建的存储空间,该空间用于不同动态资源(例如 Servlet、JSP)之间传递与共享数据。

    1) 获得 ServletContext 对象

        (1) 通过 GenericServlet 或 HttpServlet 提供的 getServletContext() 方法

            ServletContext servletContext = getServletContext();

        (2) 通过 ServletConfig 提供的 getServletContext() 方法

            ServletContext servletContext2 = getServletConfig().getServletContext();

        (3) 通过 HttpSession 提供的 getServletContext() 方法

            ServletContext servletContext3 = request.getSession().getServletContext();

        (4) 通过 HttpServletRequest 提供的 getServletContext() 方法

            ServletContext servletContext4 = request.getServletContext();

        示例:

 1             package com.example;
 2 
 3             import java.io.PrintWriter;
 4             import java.io.IOException;
 5 
 6             import javax.servlet.ServletContext;
 7             import javax.servlet.ServletException;
 8             import javax.servlet.http.HttpServlet;
 9             import javax.servlet.http.HttpServletRequest;
10             import javax.servlet.http.HttpServletResponse;
11 
12             public class FiveServlet extends HttpServlet {
13 
14                 protected void doGet(HttpServletRequest request, HttpServletResponse response)
15                         throws ServletException, IOException {
16 
17                     ServletContext servletContext = getServletContext();
18                     ServletContext servletContext2 = getServletConfig().getServletContext();
19                     ServletContext servletContext3 = request.getSession().getServletContext();
20                     ServletContext servletContext4 = request.getServletContext();
21 
22                     System.out.println("servletContext: " + servletContext);
23                     System.out.println("servletContext2: " + servletContext2);
24                     System.out.println("servletContext3: " + servletContext3);
25                     System.out.println("servletContext4: " + servletContext4);
26 
27                 }
28 
29             }


        输出:

            servletContext: org.apache.catalina.core.ApplicationContextFacade@720c17df
            servletContext2: org.apache.catalina.core.ApplicationContextFacade@720c17df
            servletContext3: org.apache.catalina.core.ApplicationContextFacade@720c17df
            servletContext4: org.apache.catalina.core.ApplicationContextFacade@720c17df

        以上四种方法都获得了同一个 ServletContext 对象。

    2) 获取上下文初始化参数

        通过 web.xml 中的 <context-param> 元素可以为 Web 应用设置一些全局的初始化参数,这些参数被称为上下文初始化参数。

        与 Servlet 的初始化参数不同,应用中的所有 Servlet 都共享同一个上下文初始化参数。在 Web 应用的整个生命周期中,上下文初始化参数会一直存在,并且可以随时被任意一个 Servlet 访问。

        (1) 设置上下文初始化参数

            在 web.xml 文件中配置上下文初始化参数,代码如下所示。

 1                 <!DOCTYPE web-app PUBLIC
 2                  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 3                  "http://java.sun.com/dtd/web-app_2_3.dtd" >
 4 
 5                 <web-app>
 6                       <display-name>Web Basic</display-name>
 7 
 8                     <!-- 设置全局初始化参数 -->
 9                     <context-param>
10                         <param-name>name</param-name>
11                         <param-value>WebBasic Global</param-value>
12                     </context-param>
13                     <context-param>
14                         <param-name>url</param-name>
15                         <param-value>www.webbasic-global.com</param-value>
16                     </context-param>
17 
18                     ...
19 
20                 </web-app>


            对以上标签说明如下:

                <context-param> 元素用来声明上下文初始化参数,必须在根元素 <web-app> 内使用。
                <param-name> 子元素表示参数名,参数名在整个 Web 应用中必须是唯一的。
                <param-value> 子元素表示参数值。

        (2) 调用接口中方法获取初始化参数

            Servlet 容器启动时,会为容器内每个 Web 应用创建一个 ServletContext 对象,并将 <context-param> 元素中的上下文初始化参数以键值对的形式存入该对象中,因此我们可以通过 ServletContext 的相关方法获取到这些初始化参数。

方法 描述
String getInitParameter(String name) 根据初始化参数名 name,返回对应的初始化参数值。
Enumeration<String> getInitParameterNames() 返回 Web 应用所有上下文初始化参数名的枚举集合,如果该 Web 应用没有上下文初始化参数,则返回一个空的枚举集合。


          示例:

 1                 package com.example;
 2 
 3                 import java.io.PrintWriter;
 4                 import java.io.IOException;
 5 
 6                 import javax.servlet.ServletContext;
 7                 import javax.servlet.ServletException;
 8                 import javax.servlet.http.HttpServlet;
 9                 import javax.servlet.http.HttpServletRequest;
10                 import javax.servlet.http.HttpServletResponse;
11 
12                 public class FiveServlet extends HttpServlet {
13 
14                     protected void doGet(HttpServletRequest request, HttpServletResponse response)
15                             throws ServletException, IOException {
16 
17                         ServletContext servletContext = getServletContext();
18 
19                         response.setContentType("text/html;charset=UTF-8");
20                         PrintWriter writer = response.getWriter();
21 
22                         writer.write("name: " + servletContext.getInitParameter("name") + "<br/>");
23                         writer.write("url: " + servletContext.getInitParameter("url") + "<br/>");
24                         writer.close();
25 
26                     }
27                 }


         输出:

                name: WebBasic Global
                url: www.webbasic-global.com

     3) 实现数据通讯

        在 Servlet 中,调用 ServletContext 接口的 setAttribute() 方法可以创建一些属性,这些属性被存放在 ServletContext 对象中。应用中所有 Servlet 都可以对这些属性进行访问和操作,通过它们可以实现应用内不同 Servlet 之间的数据通讯。

方法  描述
void setAttribute(String name, Object object) 把一个 Java 对象与一个属性名绑定,并将它作为一个属性存放到 ServletContext 中。
void removeAttribute(String name) 从 ServletContext 中移除属性名为 name 的属性。
Object getAttribute(String name) 根据指定的属性名 name,返回 ServletContext 中对应的属性值。


        ServletContext 属性与上下文初始化参数对比:

        虽然 ServletContext 的属性与上下文初始化参数都是存放在 ServletContext 对象中,但它们是不同的。

不同点 ServletContext 的属性 上下文初始化参数
创建方式 通过调用 ServletContext 接口的 setAttribute() 方法创建 通过 web.xml 使用 <context-param> 元素配置
可进行的操作 可以通过 ServletContext 接口的方法进行读取、新增、修改、移除等操作 在容器启动后只能被读取,不能进行新增、修改和移除操作
生命周期 从创建开始,到该属性被移除(remove)或者容器关闭结束 从容器启动开始,到 Web 应用被卸载或容器关闭结束
作用 可以实现 Servlet 之间的数据通讯  无法实现数据通讯


        示例:

 1             public class FourServlet extends HttpServlet {
 2 
 3                 public void init() throws ServletException {
 4 
 5                     ServletContext context = getServletContext();
 6                     context.setAttribute("count", 0);
 7                 }
 8 
 9                 protected void doGet(HttpServletRequest request, HttpServletResponse response)
10                         throws ServletException, IOException {
11 
12                     ServletContext context = getServletContext();
13                     Integer count = (Integer) context.getAttribute("count");
14                     context.setAttribute("count", ++count);
15 
16                     response.setContentType("text/html;charset=UTF-8");
17                     PrintWriter writer = response.getWriter();
18                     writer.write("Welcome to FourServlet, count = " + count + "<br/>");
19                     writer.close();
20 
21                 }
22 
23             }
24 
25             public class FiveServlet extends HttpServlet {
26 
27                 protected void doGet(HttpServletRequest request, HttpServletResponse response)
28                         throws ServletException, IOException {
29 
30                     ServletContext context = getServletContext();
31                     Integer count = (Integer) context.getAttribute("count");
32 
33                     response.setContentType("text/html;charset=UTF-8");
34                     PrintWriter writer = response.getWriter();
35                     writer.write("FourServlet had been visited " + count + " times<br/>");
36                     writer.close();
37 
38                 }            
39             }


     4) 读取 Web 应用下的资源文件

        在实际开发中,有时会需要读取 Web 应用中的一些资源文件,如配置文件和日志文件等。为此,ServletContext 接口定义了一些读取 Web 资源的方法。

方法 描述
Set getResourcePaths(String path) 返回一个 Set 集合,该集合中包含资源目录中的子目录和文件的名称。
String getRealPath(String path) 返回资源文件的真实路径(文件的绝对路径)。
URL getResource(String path) 返回映射到资源文件的 URL 对象。
InputStream getResourceAsStream(String path) 返回映射到资源文件的 InputStream 输入流对象。


        注:上表中参数 path 代表资源文件的虚拟路径,它以正斜线/开始,/表示当前 Web 应用的根目录。

        在 src/main/resources 目录下,创建一个 config.properties 文件,文件中输入如下所示的配置信息。

            name=WebBasic
            url=www.webbasic.com

        示例:

 1             package com.example;
 2 
 3             import java.io.InputStream;
 4             import java.io.IOException;
 5             import java.io.PrintWriter;
 6             import java.util.Properties;
 7 
 8             import javax.servlet.ServletException;
 9             import javax.servlet.http.HttpServlet;
10             import javax.servlet.http.HttpServletRequest;
11             import javax.servlet.http.HttpServletResponse;
12 
13             public class SixServlet extends HttpServlet {
14 
15                 protected void doGet(HttpServletRequest request, HttpServletResponse response)
16                         throws ServletException, IOException {
17 
18                     response.setContentType("text/html;charset=UTF-8");
19                     PrintWriter writer = response.getWriter();
20 
21                     InputStream ins = getServletContext().getResourceAsStream("/WEB-INF/classes/config.properties");
22                     Properties pro = new Properties();
23                     pro.load(ins);
24 
25                     String name = pro.getProperty("name");
26                     String url = pro.getProperty("url");
27                     writer.write("Name: " + name + "<br/>" + "URL: " + url + "<br/>");
28 
29                 }
30 
31                 protected void doPost(HttpServletRequest request, HttpServletResponse response)
32                         throws ServletException, IOException {
33                 }
34 
35             }

     
        输出:

            Name: WebBasic
            URL: www.webbasic.com



posted @ 2022-03-14 23:00  垄山小站  阅读(477)  评论(0)    收藏  举报