JavaWeb中web.xml初始化加载顺序详解
需求说明
做项目时,为了省事,起初把初始化的配置都放在每个类中 static加载,初始化配置一多,就想把它给整理一下,这里使用servlet中的init方法初始化。
web.xml说明
首先了解下web.xml中元素的加载顺序:
- 启动web项目后,web容器首先回去找web.xml文件,读取这个文件
- 容器会创建一个 servletcontext ( servlet 上下文),整个 web 项目的所有部分都将共享这个上下文
- 容器将 转换为键值对,并交给 servletcontext
- 容器创建 中的类实例,创建监听器
- 容器加载filter,创建过滤器, 要注意对应的filter-mapping一定要放在filter的后面
- 容器加载servlet,加载顺序按照 load-on-startup 来执行
完整加载顺序:servletcontext -> context-param -> listener-> filter -> servlet
配置实现
initservlet.java:
/** * 初始化系统参数 * 创建者 科帮网 * 创建时间 2017年5月10日 * */ public class initservlet extends httpservlet { private static final long serialversionuid = 1l; @override public void init(){ try { if(constants.pay_url.size()==0){ list<commonentity> listpayurl = propertieslistutil.listpayurl(); for(commonentity entity:listpayurl){ constants.pay_url.put(entity.getentitycode(), entity.getentityname()); } } logutil.info("佛祖保佑 永不宕机 永无bug :初始化系统数据数量:"+constants.pay_url.size()); configs.init("zfbinfo.properties"); logutil.info("初始化支付宝配置信息"); sdkconfig.getconfig().loadpropertiesfromsrc(); logutil.info("初始化银联支付配置信息"); } catch (exception e) { e.printstacktrace(); } } /** * 重新加载配置文件 * @author 科帮网 * @param request * @param response * @throws servletexception * @throws ioexception * @date 2017年5月10日 * 更新日志 * 2017年5月10日 张志朋 首次创建 * */ @override public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { constants.pay_url = new concurrenthashmap<string, string>(); list<commonentity> listpayurl = propertieslistutil.listpayurl(); for(commonentity entity:listpayurl){ constants.pay_url.put(entity.getentitycode(), entity.getentityname()); } logutil.info("初始化系统数据数量:"+constants.pay_url.size()); } @override public void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { doget(request, response); } }
web.xml:(部分配置)
<!-- 初始基础化数据--> <servlet> <servlet-name>initservlet</servlet-name> <servlet-class>com.acts.web.common.servlet.initservlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>initservlet</servlet-name> <url-pattern>/initservlet</url-pattern> </servlet-mapping>
servlet介绍
什么是servlet
servlet是sun公司为开发动态web而提供的一门技术,用户若想用发一个动态web资源(即开发一个java程序向浏览器输出数据),需要完成以下2个步骤:
- 编写一个java类,实现servlet接口。
- 把开发好的java类部署到web服务器中。
按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为servlet。
servlet的运行过程
- 浏览器发出请求,被web容器获取到
- web服务器首先检查是否已经装载并创建了该servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
- 装载并创建该servlet的一个实例对象,调用servlet实例对象的init()方法。
- 创建一个用于封装http请求消息的httpservletrequest对象和一个代表http响应消息的httpservletresponse对象,然后调用servlet的service()方法并将请求和响应对象作为参数传递进去。
- web应用程序被停止或重新启动之前,servlet引擎将卸载servlet,并在卸载之前调用servlet的destroy()方法
servlet初始化
- load-on-startup >=0 时,表示在web应用启动后立即加载,其中load-on-startup的值越小,表示加载的优先级越高,如果两个servlet的load-on-startup值相同,则其加载优先级有容器决定;
- load-on-startup 未配置时,则该servlet的加载由容器决定;
配置load-on-startup后,servlet在startup后立即加载,但只是调用servlet的init()方法,用以初始化该servlet相关的资源。初始化成功后,该servlet可响应web请求;如未配置load-on-startup,容器一般在第一次响应web请求时,会先检测该servlet是否初始化,如未初始化,则调用servlet的init()先初始化,初始化成功后,再响应请求。
ps:一般我们在开发web应用时,都会配置这个参数,有两个好处:
- 如果初始化过程失败,则容器会提示启动失败,此时我们能够提前知道相关错误;
- 配置该参数相当于将初始化servlet的工作转移到容器启动过程,使得容器只要启动成功后,就可立即响应web请求。
关于load-on-startup一些官网说明:
if the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses. if the value is a positive integer or 0, the container must load and initialize the servlet as the application is deployed.
注意
使用servlet时,一般都是继承httpservlet,然后分别实现doget或者dopost方法,但是在这里面要注意的是,这servlet并不是线程安全的,多线程单实例执行的,当并发访问同一个资源的话(成员变量等等),就有可能引发线程安全问题。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读