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()方法中的代码添加的全局参数。