Servlet预加载实现手动添加全局参数

时间:2022-12-17 03:09:21

Servlet生命周期第一步,也就是init()函数,在此函数中,完成了各种数据的初始化,当然也包括参数初始化,也就是InitParam

 

当我们取初始化参数的时候,代码如下

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Enumeration
<String> e = this.getServletContext().getInitParameterNames(); while (e.hasMoreElements()) { System.out.println(e.nextElement()); } System.out.println("---------------------------------------"); Enumeration<String> ee = this.getServletConfig().getInitParameterNames(); while (ee.hasMoreElements()) { System.out.println(ee.nextElement()); } }

也就是,初始化参数,实在init()中就被初始化,并实现了枚举接口Enumeration。

当这个枚举类型的对象(其实也就是初始化参数集合)被创建后,就无法再次添加了。

当我们在doget()函数中,想要再度添加全局参数的时候,就会报错。

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //添加全局参数,报错。
        this.getServletContext().setInitParameter("test", "test");

        Enumeration<String> e = this.getServletContext().getInitParameterNames();
        while (e.hasMoreElements()) {
            System.out.println(e.nextElement());
        }

        System.out.println("---------------------------------------");

        Enumeration<String> ee = this.getServletConfig().getInitParameterNames();
        while (ee.hasMoreElements()) {
            System.out.println(ee.nextElement());
        }
    }

错误一句话:Initialization parameters cannot be set after the context has been initialized

翻译过来就是说:已被初始化后的初始化参数集合,不能被设置。

 

好了,这么说,那这个this.getServletContext().setInitParameter()函数,存在的意义是什么呢?

 

从错误可以看出,这句话,必须要在init()函数初始化完毕这个 初始化参数集合(也就是上述说的,Enumeration接口对象)之前,才能设置初始化参数。

 

如何实现呢?

这时,我们的servlet预加载,就要闪亮登场了。

首先webl.xml中中的load-on-startup,设置一个大于等于0的数即可,我设置为1(数越低,优先级越高。值为负,不预加载。)

    <servlet>
        <servlet-name>Test</servlet-name>
        <servlet-class>cn.maiqiu.servlet.Test</servlet-class>
        <init-param>
            <param-name>city</param-name>
            <param-value>xian</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Test</servlet-name>
        <url-pattern>/Test</url-pattern>
    </servlet-mapping>

此时,当服务器启动的时候,就会把这个servlet给加载了。

加载也就是说,创建了servlet对象,并且执行了init()方法。

 

重点:此时,刚启动服务器,就要加载这个servlet并且执行init()函数,那么,我们重写这个init()函数

    @Override
    public void init() throws ServletException {
        System.out.println("这个servlet预加载");
        //预加载之后,才可以操作初始化的值
        this.getServletContext().setInitParameter("test", "test");
    }

此时,服务器启动,为web项目创建servletcontext,并且立刻创建这个预加载的servlet并且执行init()函数,此时往servletContext中添加初始化参数,

就不会报错了。

 

xml中全局参数和预加载servlet方式读取全局参数顺序测试

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>birthday</param-name>
        <param-value>0424</param-value>
    </context-param>

    <servlet>
        <servlet-name>Test</servlet-name>
        <servlet-class>cn.maiqiu.servlet.Test</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Test</servlet-name>
        <url-pattern>/Test</url-pattern>
    </servlet-mapping>
</web-app>

此时我的web.xml中,有一个全局参数,叫做birthday。

另外我的预加载的servlet,也就是Test中重写Servlet接口中的init()函数,如上上图所示,

使用代码添加了一个全局参数,test。

 

此时,我们尝试在doGet()函数中,测试读取到的参数顺序。

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        Enumeration<String> e = this.getServletContext().getInitParameterNames();
        while (e.hasMoreElements()) {
            System.out.println(e.nextElement());
        }
    }

输出结果:

birthday
test

 

结论:servlet预加载,在init()方法中,可以实现代码添加初始化参数。

读取顺序,servletContext先读取xml中的全局参数,再读取init()方法中的代码添加的全局参数。