Servlet开发案例以及Servlet的细节

详细介绍了Java Servlet的概念以及开发方式和细节。

Servlet学习的基础:网络基础Java Web

在此前的文章中,我们为Servlet的出现进行了大量的铺垫,对于一些基本概念不再赘述,现在我们正式学习Servlet, Servlet是运行在实现了Java Servlet规范的服务器端一个小程序,是JavaWeb的三大组件之一(JavaWeb的三大组件:Servlet、Listener-监听器、Filter-过滤器),它属于动态资源,能够动态的根据请求的信息返回不同的响应。

另外,Servlet的学习还是我们深入学习Spring MVC框架的基础!

文章目录

1 Servlet接口的概述

javax.serlvet.Servlet接口是Servlet规范中最顶级的接口。此接口定义了初始化 servlet、为请求提供服务以及从服务器中删除 servlet 的方法。这些方法称为Servlet的生命周期方法,它们按照一定顺序调用。

除了生命周期方法外,此接口还提供了 getServletConfig 方法(Servlet可以使用该方法可以获取自身配置信息) 和 getservetinfo方法 (允许serverlet返回有关自身的基本信息,如作者,版本和版权)。

实现servlet接口必须实现下面的5个API方法:

public interface Servlet { 

    /** * servlet 容器在实例化servlet后调用init 方法一次进行初始化。只有完成该方法(不抛出异常),然后servlet才能接收任何请求。 * * @param config 包含 servlet 的配置和初始化参数的 ServletConfig 对象。 */
    public void init(ServletConfig config) throws ServletException;


    /** * 返回一个ServletConfig对象,该对象包含此servlet的初始化和启动参数,返回的ServletConfig对象是传递给init方法的参数对象。 * 此接口的实现负责存储ServletConfig对象,以便此方法可以返回它,实现此接口的 GenericServlet 类已经执行了此操作。 * * @return 辅助初始化servlet的ServletConfig对象。 */
    public ServletConfig getServletConfig();


    /** * 由 servlet容器(Web 服务器)调用,以允许servlet处理和响应请求。只有在servlet的 init()方法成功完成后,才能调用此方法。 * * @param req 包含客户端请求的 ServletRequest 对象 * @param res 包含 servlet 响应的 ServletResponse 对象 */
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;


    /** * 返回有关 servlet 的信息,如作者、版本和版权。 * 此方法返回的字符串为纯文本,而不是任何类型的标记(如 HTML、XML等)语言。 * * @return 返回有关 servlet 的信息字符串 */

    public String getServletInfo();


    /** * 由 servlet(Web 服务器)容器调用,以指示 servlet 正在停用。 * 当服务器正常关闭时会调用此方法,使servlet有机会清理正在保留的任何资源(例如, 内存、文件句柄、线程) * 在 servlet 容器调用此方法后,它将不会再在此 servlet 上调用service方法。 */
    public void destroy();
}

上面的方法实际上还是很好理解的,这些Servlet实例和方法都是由Servlet容器(Web服务器)调用的,因此我们的项目不需要任何main方法,也不需要创建任何Servlet实例。

在Servlet接口中出现了三个相关类:

  1. ServletConfig,作为Servlet的配置对象;
  2. ServletRequest ,代表请求封装的对象;
  3. ServletResponse,代表响应封装的对象;

这三个对象也都不需要我们创建,由是Servlet容器(比如tomcat服务器)创建,并且由Web服务器在运行时传递进来,我们可以直接在方法中使用,后面会一一介绍!

2 Servlet的生命周期和请求处理逻辑

  1. Web服务器接收到HTTP请求,将请求转发给servlet容器,servlet容器中根据请求路径查找对应的Servlet;
  2. 如果servlet实例还未创建,那么创建一个servlet实例,随后servlet容器调用servlet的init()方法对servlet进行初始化(该方法只会在servlet第一次被载入时调用)。被创建的servlet实例会被保留在容器的中,当后续有同样的请求到来时可以直接处理,不再需要重新创建和初始化。
  3. servlet容器将会解析到来的HTTP请求,创建一个Request对象,并且创建一个Response响应对象,调用该servlet实例的service方法将这两个对象作为参数传递进来,以期待service方法中的业务逻辑处理HTTP请求,因此service方法就是我们要重点开发的方法。
  4. 我们业务逻辑会将要返回的结果封装到Servlet容器提供的Response对象中,service方法执行完毕之后,Web服务器会将Response对象中保存的动态生成的结果返回给客户端浏览器。
  5. 如果Servlet实例被销毁,那么将会由Servlet容器执行destory方法,通常都是在服务器关闭时Servlet才会销毁,destory方法可以进行资源的释放!

3 Servlet的开发

我们开发Servlet时,需要对Servlet进行实现。一般来说,实现方式有三种:

  1. 直接实现javax.servlet.Servlet接口。
  2. 继承 javax.servlet.GenericServlet抽象类。
  3. 继承javax.servlet.http.HttpServlet抽象类。

3.1 简单的Servlet实现

我们通过Servlet接口来简单的实现一下Servlet。

我们新建一个java Web项目:

《Servlet开发案例以及Servlet的细节》

maven依赖如下,采用tomcat插件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>servlet-01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>servlet-01</name>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <junit.version>5.7.0</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>Servlet</finalName>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <!-- tomcat插件控制 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <configuration>
                    <!--端口控制-->
                    <port>8080</port>
                    <!--项目路径控制意味着http://localhost:8080/servlet-01-->
                    <path>/servlet-01</path>
                    <!--编码-->
                    <uriEncoding>UTF-8</uriEncoding>
                </configuration>
            </plugin>
            <!-- maven插件控制 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>

        </plugins>
    </build>
</project>

开发第一个自己的Servlet:

@WebServlet("/first-servlet")
public class FirstServlet implements Servlet { 
    @Override
    public void init(ServletConfig servletConfig) { 
        System.out.println("---------------");
        System.out.println("servletConfig: " + servletConfig);
        System.out.println("init");
    }

    @Override
    public ServletConfig getServletConfig() { 
        System.out.println("---------------");
        System.out.println("getServletConfig");
        return null;
    }

    /** * 我们主要开发的方法 * * @param servletRequest 请求对象 * @param servletResponse 响应对象 */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException { 
        //获取请求的数据
        String message = servletRequest.getParameter("xx");
        //封装响应数据
        servletResponse.setContentType("text/html");

        // Hello
        PrintWriter out = servletResponse.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + message + "</h1>");
        out.println("</body></html>");
    }

    @Override
    public String getServletInfo() { 
        System.out.println("getServletInfo");
        return null;
    }

    @Override
    public void destroy() { 
        System.out.println("destroy");
    }
}

想要成功运行servlet还要进行servlet的路径配置。这里,我们使用servlet 3.0开始提供的@WebServlet(“/first-servlet”)注解来配置servlet的路径。当然也可以使用web.xml来配置,但是这比较麻烦!这里的路径必须使用“/”开头,并且相对的是当前应用根目录。

如果是配置web.xml,那么可以这样配置:

<!-- 注册 -->
<servlet>
    <!--3、 servlet的内部名称-->
    <servlet-name>firstServlt</servlet-name>
    <!--4、 servlet的类全路径名-->
    <servlet-class>com.example.servlet_01.FirstServlet</servlet-class>
</servlet>
<!-- 映射 -->
<servlet-mapping>
    <!--2、 servlet的映射内部名称,通过他可以找到servlet的内部名称,不区分大小写-->
    <servlet-name>firstServlt</servlet-name>
    <!--1、 请求servlet的映射路径-->
    <url-pattern>/first-servlet</url-pattern>
</servlet-mapping>

将项目部署在tomcat服务器后,在浏览器中输入http://localhost:8080/servlet-01/first-servlet,这时候服务器就会先找到servlet-01工程下的web.xml,然后寻找这一次请求的映射路径/first-servlet,根据映射/first-servlet找到注释1,然后找到同级servlet的映射内部名称注释2,在根据映射的内部名称找到servlet的内部名称注释3,最后找到同级的servlet的具体类名注释4,然后服务器再根据反射执行定义了Servlt的类的方法,开始servlet的生命周期……

启动tomcat插件,访问http://localhost:8080/servlet-01/first-servlet?xx=11,可以发现servlet被初始化的信息:

《Servlet开发案例以及Servlet的细节》

在页面中能够看到传递的参数:

《Servlet开发案例以及Servlet的细节》

跟换请求参数,响应的参数也在改变:

《Servlet开发案例以及Servlet的细节》

这就是基于servlet的动态Web应用。 同时我们发现控制台并没有输出servlet被初始化的信息,这说明servlet只会被初始化一次。

需要注意的是,基于tomcat插件的Web应用在直接关闭时不会输出destory的信息,使用本地tomcat测试即可看到销毁的信息:

《Servlet开发案例以及Servlet的细节》

3.2 继承GenericServlet

java.servlet.GenericServlet类类使编写servlet变得更容易。它提供实现了Servlet接口和来自ServletConfig接口的方法(除了service方法)。GenericServlet类也实现了log()方法,这是一个在ServletContext接口中定义的方法,同时具有自己的init()和log()方法。

由于GenericServlet是一个抽象类,所以要扩展这个类,你必须实现这个类的所有抽象方法。但是相比于实现Servlet接口需要实现所有方法,继承该类只需要实现一个service即可,并且,Servlet接口的其他方法(比如初始化或者销毁方法)在实际开发中基本上是用不到的,因此继承GenericServlet更加方便。

Generic意为“通用的”,自己编写的servlet直接扩展GenericServlet类比实现Servlet接口更加方便。

如下是一个继承了GenericServlet的Servlet实现:

@WebServlet("/generic-servlet")
public class MyGenericServlet extends GenericServlet { 

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { 
        //获取请求的数据
        String message = req.getParameter("xx");
        //封装响应数据
        res.setContentType("text/html");

        // Hello
        PrintWriter out = res.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + message + "</h1>");
        out.println("</body></html>");
    }
}

启动tomcat插件,访问http://localhost:8080/servlet-01/generic-servlet?xx=generic,结果如下,完全没问题:

《Servlet开发案例以及Servlet的细节》

3.3 继承HttpServlet

实际上GenericServlet作为一个通用的Servlet实现,只提供了基本的功能,在某些情况下仍然不方便,比如我们的Web应用基本上都是基于HTTP协议的请求,因此非常有必要创造一个专门针对HTTP协议的Servlet,比如处理各种请求,获取请求头信息等等。

Java已经为我们提供了这样的一个Servlet实现,那就是javax.servlet.http.HttpServlet。HTTP的请求方式包括DELETE、GET、OPTIONS、POST、PUT和TRACE,在HttpServlet类中分别提供了相应的服务方法,它们是doDelete()、doGet()、doOptions()、doPost()、doPut()和doTrace()。

HttpServlet继承了GenericServlet,而GenericServlet实现Servlet接口。所以可以继承HttpServlet来创建一个专门针对http请求的Servlet。

当通过继承HttpServlet来创建一个Servlet时,我们只需要根据要处理的请求的类型,来重写不同的方法就可以了,处理get请求,则重写doGet(),处理post请求,则重写doPost(),无需实现其他方法,开发Servlet时更加简单!

@WebServlet("/http-servlet")
public class MyHttpServlet extends HttpServlet { 

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        //获取请求的数据
        String message = req.getParameter("xx");
        //封装响应数据
        resp.setContentType("text/html");
        // Hello
        PrintWriter out = resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + message + "</h1>");
        out.println("</body></html>");
    }
}

启动tomcat插件,访问http://localhost:8080/servlet-01/http-servlet?xx= http-servlet,结果如下,完全没问题:

《Servlet开发案例以及Servlet的细节》

3.3.1 HttpServlet的设计

HttpServlet类中提供了service(HttpServletRequest,HttpServletResponse)方法,这个方法是HttpServlet自己的方法,不是从Servlet继承来的。

在HttpServlet重写自父类的service(ServletRequest,ServletResponse)方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后调用service(HttpServletRequest,HttpServletResponse)方法,这说明子类可以去覆盖service(HttpServletRequest,HttpServletResponse)方法即可,这就不用自己去强转请求和响应对象了。

public abstract class HttpServlet extends GenericServlet { 
//重写的service方法
    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException { 
        HttpServletRequest  request;
        HttpServletResponse response;
        try { 
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) { 
            throw new ServletException("non-HTTP request or response");
        }
       //以上部分是对两个对象的装强制转型
       //下面是调用自身的service方法
        service(request, response);
}
    //自身的service方法,在该方法中会判断http请求的的方式,并且会选择调用对应的方法如get请求调用doGet方法,post请求调用doPost方法。
protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException { 
        ……
}
}

其实子类也不用去覆盖service(HttpServletRequest,HttpServletResponse)方法,因为HttpServlet还要做另一步简化操作。在HttpServlet的service(HttpServletRequest,HttpServletResponse)方法中会去判断当前请求是GET还是POST,如果是GET请求,那么会去调用本类的doGet()方法,如果是POST请求会去调用doPost()方法,这说明我们在子类中只需要去覆盖doGet()或doPost()方法即可。

实际上这里采用了模版方法模式,service方法定义了请求处理的算法骨架,具体的处理方法则由子类实现。

《Servlet开发案例以及Servlet的细节》

通过这些细可以发现,HttpServlet的目的是让我们在进行基于HTTP请求的Web开发时更加简单,让开开发者把更多的精力放在业务逻辑上去,而不是放在网络请求的解析上。

一系列的doXxx方法使用了模版方法设计模式

4 Servlet的细节

4.1 Servlet与单例

Servlet是单例的,在web容器当中,在服务器关闭之前,自始至终就是同一个Servlet。即同时并发的请求也是由同一个servlet处理的!这样的好处是能够减少对象的创建,提升性能,但是我们在开发Servlet的时候需要注意线程安全问题,尽量不要定义有状态的全局变量。

4.2 多个映射路径

一个Servlet,可以绑定一个多个映射路径,通过这些映射路径发送的请求都会到达该Servlet。

对于web.xml可以如下配置,配置多个servlet-mapping,它们的servlet-name一致,但是url-pattern不一致。

<!-- 注册 -->
<servlet>
    <!--3、 servlet的内部名称-->
    <servlet-name>firstServlt</servlet-name>
    <!--4、 servlet的类全路径名-->
    <servlet-class>com.example.servlet_01.FirstServlet</servlet-class>
</servlet>
<!-- 映射 -->
<servlet-mapping>
    <!--2、 servlet的映射内部名称,通过他可以找到servlet的内部名称,不区分大小写-->
    <servlet-name>firstServlt</servlet-name>
    <!--1、 请求servlet的映射路径-->
    <url-pattern>/first-servlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <!--2、 servlet的映射内部名称,通过他可以找到servlet的内部名称,不区分大小写-->
    <servlet-name>firstServlt</servlet-name>
    <!--1、 请求servlet的映射路径-->
    <url-pattern>/first-servlet2</url-pattern>
</servlet-mapping>

或者在一个servlet-mapping中配置多个url-pattern:

<servlet-mapping>
    <!--2、 servlet的映射内部名称,通过他可以找到servlet的内部名称,不区分大小写-->
    <servlet-name>firstServlt</servlet-name>
    <!--1、 请求servlet的映射路径-->
    <url-pattern>/first-servlet3</url-pattern>
    <url-pattern>/first-servlet4</url-pattern>
    <url-pattern>/first-servlet5</url-pattern>
</servlet-mapping>

对于采用@WebServlet注解的方式,那就更简单了,该注解的value是一个i嗯String数组,因此我们直接传递多个路径地址的数组就行了:

@WebServlet({ "/generic-servlet","/generic-servlet2","/generic-servlet3"})

4.3 映射路径通配符

Servlet映射路径可以使⽤通配符“*”,通配符可以匹配任何的字符串:

  1. 如果路径是/*结尾,则表示匹配具有指定前缀路径的所有的路径(优先级最高)!如果路径为/*,那么它会拦截所有的请求,包括访问直接静态资源、jsp文件的请求。
  2. 如果路径是*. 扩展名,则表示匹配已该后缀结尾的任意路径。
  3. 这两种格式不能混用。

Servlet映射路径优先级:

  1. 对于某个具体的访问路径,如果存在该路径的Servlet映射,那么该Servlet优先级最高。
  2. 如果不存在,那么具有“/*”结尾的通配符路径的Servlet优先级最高。
  3. 如果不存在,那么具有“*.后缀名”结尾的通配符路径的Servlet优先级最高。
  4. 如果不存在,那么最后是具有“/”默认路径通配符的Servlet,它也被称为默认Servlet。

如果使用了“/*”通配符Servlet,那么当该Servlet中存在请求include、forward、redirect到其他没有显示指定路径的资源时(比如转发到某个jsp、静态资源等),那么这个请求将会一直在这个“/*”通配符Servlet中循环直到抛出异常,因为转发的路径并没有在第一步匹配到具体的Servlet的映射,进而又匹配到了这个通配符Servlet本身,而这个通配符Servlet中又再一次进行了转发。

4.3.1 JspServlet

对于以“*.jsp”结尾的访问路径,默认是被一个在tomcat容器的conf/web.xml配置文件中配置的JspServlet处理的,名为jsp。它的定义如下:

《Servlet开发案例以及Servlet的细节》

它的映射如下:

《Servlet开发案例以及Servlet的细节》

如下案例,该Servlet的路径为“*.jsp”:

@WebServlet("*.jsp")
public class AntServlet extends HttpServlet { 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        //封装响应数据
        resp.setContentType("text/html");
        // AntServlet
        PrintWriter out = resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + "AntServlet" + "</h1>");
        out.println("</body></html>");
    }
}

那么我们访问以.jsp结尾的资源,比如http://localhost:8080/servlet-01/11/222.jsp,此时就会转发到该Servlet中:

《Servlet开发案例以及Servlet的细节》

4.4 默认Servlet

Java Web应用的一切请求都是在请求对应的Servlet,动态的资源就不必说了,有自己的路径,对于静态资源,比如html、css、js、图片等,虽然在请求URL中看起来是访问的静态资源的地址,但是实际上仍然是通过一个默认Servlet查找资源的,没找到就返回404。

和JspServlet一样,默认servlet也是在tomcat容器在conf/web.xml配置文件中帮我们配置的,名为default。它的定义如下:

《Servlet开发案例以及Servlet的细节》

它的映射如下:

《Servlet开发案例以及Servlet的细节》

所以说,静态资源的请求,会被这个由tomcat为我们配置的DefaultServlet拦截并处理,在该Servlet中,会尝试查找请求URL路径对应的静态资源,找到了就返回该资源,找不到就返回404!

如果在项目中自定义了映射路径为“/”的Servlet,那么会覆盖容器为我们配置的DefaultServlet,转而走我们自己配置的Servlet的逻辑!

我们在webapp下创建一个default.html:

《Servlet开发案例以及Servlet的细节》

可以通过URL直接访问http://localhost:8080/servlet-01/default.html:

《Servlet开发案例以及Servlet的细节》

如果我们配置了默认的Servlet:

@WebServlet("/")
public class DefaultServlet extends HttpServlet { 

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 
        //封装响应数据
        resp.setContentType("text/html");
        // Hello
        PrintWriter out = resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + "默认Servlet" + "</h1>");
        out.println("</body></html>");
    }
}

再次访问该静态资源,http://localhost:8080/servlet-01/default.html,发现它会自动访问我们配置的默认Servlet:

《Servlet开发案例以及Servlet的细节》

4.5 Servlet初始化时机

Servlet在默认情况下,只有当对应的请求第一次到来时才会初始化,我们也可以配置在启动服务器时立即初始化某些Servlet。这样的好处是,在第一次请求的时候不会再创建Servlet对象了,提升处理速度,缺点就是启动服务器时会更多的对象,可能会延长服务器启动时间。

对于web.xml可以如下配置,在servlet标签中添加一个load-on-startup子标签,该标签用于指示容器是否应该在web应用程序启动的时候就加载这个Servlet(实例化并调用其init方法)。

<!-- 注册 -->
<servlet>
    <servlet-name>firstServlt</servlet-name>
    <servlet-class>com.example.servlet_01.FirstServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

标签中填写的是启动的优先级:

  1. 它的值必须是一个整数,当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet。值越小,该servlet的优先级越高,应用启动时就越先加载。
  2. 如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载。
  3. 当值相同时,容器就会自己选择顺序来加载。

对于@WebServlet注解,可以在loadOnStartup属性中配置该特性。

5 ServletConfig

javax.servlet.ServletConfig封装了配置某个Servlet的初始化信息,这个功能将配置信息从Java文件提到了xml文件或者注解中,能够统一管理配置,更加灵活,这可以看作比较原始的将配置和代码分离的方式。

当servlet配置了初始化参数之后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到一个ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给Servlet,进而,程序员通过Servlet对象可以得到当前servlet的初始化参数信息,并且自定义初始化逻辑。

相关API方法如下:

方法名描述
String getServletName()获得当前servlet对象的名称(就是web.Xml中配置的名称)
Enumeration<java.lang.String> getInitParameterNames()获得所有传递的键值对的键名枚举.没有就返回空枚举
String getInitParameter(String name)通过指定键,获得键的值。
ServletContext getServletContext()返回当然项目的ServletContext对象,一个(运行的)工程只有一个上下文环境对象。

5.1 初始化参数

在WEB-INF的web.xml文件中的servlet标签下可以添加初始化参数键值对,即servlet级别的初始化参数。

如下一个Servlet:

public class InitParamServlet extends HttpServlet { 

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        ServletConfig servletConfig = getServletConfig();
        Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) { 
            String s = initParameterNames.nextElement();
            System.out.println("paramName: " + s);
            System.out.println("paramValue: " + servletConfig.getInitParameter(s));
        }
    }
}

在web.xml的Servlet的标签中,可以用一个或多个< init-param/>标签为某个servlet配置一些初始化参数。

<servlet>
    <servlet-name>InitParamServlet</servlet-name>
    <servlet-class>com.example.servlet_01.InitParamServlet</servlet-class>
    <!-- 给当前servlet传递初始化参数-键值对 -->
    <init-param>
        <param-name>username</param-name>
        <param-value>lisi</param-value>
    </init-param>
    <init-param>
        <param-name>age</param-name>
        <param-value>22</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>InitParamServlet</servlet-name>
    <url-pattern>/initParam-servlet</url-pattern>
</servlet-mapping>

运行tomcat插件,访问http://localhost:8080/servlet-01/initParam-servlet,在控制台可以看到输出的参数信息:

《Servlet开发案例以及Servlet的细节》

也可以在@WebServlet中通过initParams属性配置当前Servlet初始化信息:

@WebServlet(value = "/initParam-servlet",
        initParams = { @WebInitParam(name = "username", value = "zhangsan"),
                @WebInitParam(name = "age", value = "11")})

6 总结

本次我们简单介绍了早期的Servlet的开发方式,比较常用的就是继承HttpServlet的方式了,但是在使用框架之后,甚至连Servlet都“见不到了”,因此本文讲的开发方式基本上都用不到的,但是如果你想了解框架的原理,比如Spring MVC,那么仍然需要对原始的Servlet API有所了解。

后面我们会继续深入原始的Serlet API以及相关知识,比如Session、Cookie技术、HttpServletResponse、HttpServletRequest的介绍,以及异步请求处理,敬请关注!

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

    原文作者:刘Java
    原文地址: https://blog.csdn.net/weixin_43767015/article/details/112800923
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞