第一:Servlet
Servlet是个接口,全限定名是javax.servlet.Servlet,在javax.servlet包中,在servlet-api.jar(在tomcat自带的lib文件夹中)或是在javax.servlet-api-xxx.jar(在maven中引入javax.servlet-api依赖)。
如果我们用IDE工具,右键new,选择Servlet的方式创建一个Servlet,则会自动继承javax.servlet.http.HttpServlet(HttpServlet类实现了Servlet接口),我们只需定义好Servlet名称、在URL mapping框中填好url pattern的值,如果有需要,还可以在Intialization parameters框中填入初始化参数的值。
此外,url pattern的值必须以斜杠"/"或者“*.”开头,如果填入的值不满足这个要求,IDE工具就会提示URL patterns should start with "/" or "*."。如果我们在创建好Servlet之后再手动把url pattern的值修改为不满足条件的值,则此项目就不能启动了,启动项目时会弹出Problem Occured错误提示框,提示 ‘Starting Tomcat v7.0 Server at localhost’ has encountered a problem,控制台也会报异常org.apache.catalina.LifecycleException:Caused
by: org.apache.catalina.LifecycleException: A child container failed during start。
Servlet的生命周期:
1.Servlet实例化
Servlet实例化有2个时机,第一种是客户端第一次请求时,系统创建对应的Servlet实例,默认是这种;第二种是系统启动后就创建Servlet实例,这种要配置load-on-startup的值,0-5的整数,0表示优先级最高,最快实例化。其实负整数也不会报错,只是不起作用,系统还是在客户端第一次请求时创建对应的Servlet实例。
2.Servlet初始化
init(ServletConfig config)方法,如果在创建Servlet类时填写了Intialization parameters,则这些值将被封装在ServletConfig实例中,并传入到init方法中。
3.Servlet处理客户端请求,service()方法。
4.Servlet销毁
系统在关闭前会调用destroy()方法销毁Servlet实例。
如何获取该servlet的配置参数?
HttpServlet的父类GenericServlet中有getServletConfig()方法,我们自己建的servlet调用父类此方法就可以得到ServletConfig实例了,然后在调用ServletConfig的实例方法getInitParameter(String name)就可以获得指定的配置参数的值了。
第二:Filter
Filter也是个接口,全限定名是javax.servlet.Filter,跟Servlet接口在同一目录下。如果配置了Filter,且请求地址满足Filter的url pattern,则请求在到达对应的Servlet之前会先到达Filter。可以有多个Filter,请求到达这些Filter的顺序是由这些Filter在web.xml文件中<url-pattern>*.action</url-pattern>配置的先后顺序决定的,从上到下匹配,先匹配到哪个Filter,请求就先到哪个Filter。因为请求会在到达Servlet之前先到达Filter,所以可以用Filter对用户请求进行预处理,之后再将请求交给Servlet处理,处理之后,再用Filter对响应进行后处理。
有2种常见用法:
1.用户鉴权Filter
接收到请求之后,看用户是否登录了或者看用户是否有对应的访问权限,如果没有,则提示登录或者提示没有权限,如果没问题,则将请求交给Servlet处理。
2.处理字符编码的Filter
设置请求与响应的字符编码为指定格式。
需要说明的是,Filter是在应用一启动的时候就实例化的,紧接着就初始化,而不像Servlet那样可以在第一次请求的时候再实例化。而且,多个Filter实例化的顺序并不一定按照在web.xml文件中配置的顺序。另外,经过实际测试发现一个现象,客户端发起一个请求,到达Filter,按道理来说应该是Filter处理完,请求到达Servlet后再实例化对应的Servlet,但实际却是只要客户端发了请求,实例化、初始化Filter之后就会实例化、初始化对应的Servlet,这时候请求还没有到达对应的Servlet。
Filter处理请求主要是用doFilter(ServletRequest request, ServletResponse response, FilterChain chain)方法,多个Filter间传递请求、最后一个Filter向Servlet传递请求都是在上述doFilter()方法中调用FilterChain接口的doFilter ( ServletRequest request, ServletResponse response )方法,如果之后再调用入参ServletResponse实例的API,则就是对响应进行后处理了。
如何获取该filter的配置参数?
不像获取servlet配置参数一样,没有现成的getFilterConfig()可供调用,但是发现Filter接口的init(FilterConfig filterConfig)方法参数竟然是FilterConfig实例,看来是把初始化参数封装到了此实例当中,如此,我们可以在filter类中创建FilterConfig类型的成员变量,在init方法中把filterConfig赋值给此成员变量,这样就可以在doFilter()方法中调用此FilterConfig类型的成员变量的getInitParameter(xxx)方法获取指定的初始化参数的值了。
第三:Listener
Listener接口分为3类:
1.监听web应用,主要用的是ServletContextListener(javax.servlet.ServletContextListener)接口,web应用的启动与关闭各触发接口的一个方法:
web应用启动触发contextInitialized(ServletContextEvent sce)方法,web应用关闭触发contextDestroyed(ServletContextEvent sce)方法。
2.监听session,主要用的是HttpSessionListener(javax.servlet.http.HttpSessionListener)接口,用户session的开始和结束各触发接口的一个方法:
session开始触发sessionCreated(HttpSessionEvent se)方法,session结束触发sessionDestroyed(HttpSessionEvent se)方法。
3.监听reqeust,主要用的是ServletRequestListener(javax.servlet.ServletRequestListener)接口,用户发起请求、请求结束时各触发接口的一个方法:
用户发起请求时触发requestInitialized(ServletRequestEvent sre)方法,请求结束时触发requestDestroyed(ServletRequestEvent sre)方法。
创建监听类,只需实现对应的xxxListener接口即可。
综上,系统启动后会先触发ServletContextListener实现类的contextInitialized()方法,再实例化、初始化所有的Filter实现类,再实例化、初始化所有配置了load-on-startup的Servlet,用户发起请求后,先实例化、初始化对应的Servlet,然后符合请求条件的Filter链预处理请求之后传给Servlet处理请求,Filter链再后处理响应,之后将响应结果展示给用户。
项目中如果用了Spring框架,为了让web应用在启动时就创建IOC容器,需要在web.xml文件中配置一个监听器,监听器类是spring-web-xxx.jar包中的ContextLoaderListener(org.springframework.web.context.ContextLoaderListener,实现了ServletContextListener接口),并且还要为此类配置一个web应用配置参数。
<!-- 配置监听器ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<!-- 参数名必须是contextConfigLocation -->
<param-name>contextConfigLocation</param-name>
<!-- 参数值是配置文件的名字 -->
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
第四:Interceptor
Interceptor,拦截器,在spring mvc框架中也有较多的应用。
在spring-webmvc-xxx.jar中有一个HandlerInterceptor接口,有一个常用的实现类HandlerInterceptorAdapter,我们既可以直接实现HandlerInterceptor接口也可以继承HandlerInterceptorAdapter类,不论是实现接口还是继承实现类,都需要重写里面的几个方法(preHandle、postHandle、afterCompletion方法),来实现自己的需求。
除了HandlerInterceptor接口外,在spring-web-xxx.jar包中还有一个WebRequestInterceptor接口,该接口及其实现类WebRequestHandlerInterceptorAdapter也是可以用的。