Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
-
Servlet 初始化后调用 init () 方法。
-
Servlet 调用 service() 方法来处理客户端的请求。
-
Servlet 销毁前调用 destroy() 方法。
-
最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
执行原理
步骤:
-
Web Client 向Servlet容器(Tomcat)发出Http请求
-
Servlet容器接收Web Client的请求
-
Servlet容器创建一个HttpRequest对象,将Web Client请求的信息封装到这个对象中。
-
Servlet容器创建一个HttpResponse对象
-
Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给HttpServlet 对象。
-
HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息。
-
HttpServlet调用HttpResponse对象的有关方法,生成响应数据。
-
Servlet容器把HttpServlet的响应结果传给Web Client。
原理:
-
首先简单解释一下Servlet接收和响应客户请求的过程,首先客户发送一个请求,Servlet是调用service()方法对请求进行响应的,通过源代码可见,service()方法中对请求的方式进行了匹配,选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。在Servlet接口和GenericServlet中是没有doGet()、doPost()等等这些方法的,HttpServlet中定义了这些方法,但是都是返回error信息,所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。
-
每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,分别是init(),service(),destroy()方法。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。
-
Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest、ServletResponse 强转为HttpRequest 和 HttpResponse。
init() 方法
-
init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。
Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。
当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
init 方法的定义如下:
public void init() throws ServletException { // 初始化代码... }
service() 方法
service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
利用service()方法代替doGet()方法和doPost()方法,反射。
@Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); String method=req.getParameter("method"); try { this.getClass().getDeclaredMethod(method,HttpServletRequest.class,HttpServletResponse.class).invoke(this,req,resp); }catch (Exception e){ e.printStackTrace(); } }
service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。
doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征
doGet() 方法
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { }
doPost() 方法
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); }
destroy() 方法
destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收,即销毁方法。
public void destroy() { // 终止化代码... }
过滤器(Filter)的简介
过滤器的作用: 过滤器可以对所有的请求或者响应做拦截操作.
1:以常规的方式调用资源(Servlet/JSP);
2:利用修改过的请求信息调用资源;
3:调用资源之后,但在响应到客户端之前,对响应做出修改;
4:阻止当前资源调用,代之转到其他资源.
Filter的开发和使用
1:自定义一个类(XxxFilter,Xxx表示功能名),实现于javax.servlet.Filter接口.
2:在wed.xml里面配置拦截器
<filter> <filter-name>XxxFilter</filter-name> <filter-class>XxxFilter类的全限定名</filter-class> </filter> <filter-mapping> <filter-name>XxxFilter</filter-name> <!--表示:当前Filter只对哪些资源做过滤/拦截操作,只对hello.jsp做拦截--> <url-pattern>/hello.jsp</url-pattern> </filter-mapping>
Filter的生命周期方法
void init(FilterConfig config): 初始化方法 (2):void doFilter(ServletRequest request, ServletResponse response, FilterChain chain):执行过滤的方法(每一次请求都会执行过滤) (3):void destroy():销毁方法 执行的流程: 在启动Tomcat服务器的时候,就会执行构造器和init方法. 构造器--->init方法 -----> ( doFilter方法 )N次------->destroy方法
-
具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
-
拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
-
后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
-
拦截所有资源:/* 访问所有资源时,过滤器都会被执行
监听器分类
1.按监听对象分类
(1)用于监听应用程序对象(ServletContext)
(2)用于监听用户会话对象(HttpSession)
(3)用于监听请求消息对象(ServletRequest)
2.按监听事件分类
(1)监听对象的创建和销毁的事件监听器。
(2)监听对象属性变更(添加、修改、删除)的监听器。
监听器接口
Servlet API中定义了监听器接口,用来监听不同的事件类型。
ServletContextListener:上下文监听器; ServletContextAttribute:上下文属性监听器; ServletRequestListener:请求监听器; ServletRequestAttributeListener:请求属性监听器; HttpSessionListener:会话监听器; HttpSessionAttribute:会话属性监听器.
配置监听器类:
创建监听器类,实现监听器接口,在web.xml文件中配置监听器类。
<listener> <listener-class>监听器类全类名</listener-class> </listener>
实例
监听器类(java代码)
<br class="Apple-interchange-newline"><div></div>
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
public class ObjectListener implements ServletContextListener, ServletRequestListener {
/*
监听ServletContext对象的创建
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext创建了");
ServletContext application = sce.getServletContext();//整个应用程序只有一个对象
application.setAttribute("config","123");//设置初始化数据
}
/*
监听ServletContext对象的销毁
*/
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext销毁了");
}
/*
请求对象创建
*/
long s = 0;
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("请求对象创建");
s = System.currentTimeMillis();
}
/*
请求对象销毁
*/
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("请求对象销毁");
//获取客户端ip
HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
System.out.println(request.getRemoteAddr()+"请求耗时:::"+(System.currentTimeMillis()-s));
}