Servlet系列学习笔记1 --- Servlet工作原理和生命周期
目录
Servlet是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
一、Servlet API概述
Servlet API中有4个Java
1.javax.servlet包含定义servlet和servlet容器之间契约的类和接口。
2.javax.servlet.http包含定义HTTP Servlet 和Servlet容器之间的关系。
3.javax.servlet.annotation包含标注servlet,Filter,Listener的标注。
4.javax.servlet.descriptor包含提供程序化登录Web应用程序配置信息类型。
二、Servlet工作原理
用户请求致使Servlet容器调用Servlet的Service()方法,传入一个ServletRequest实例对象和一个ServletResponse实例对象。其中,ServletRequest封装了当前的HTTP请求信息,ServletResponse封装了当前用户的HTTP响应信息。有了这两个实例,开发者就不需要对底层的HTTP数据进行操作,可以直接通过这两个对象获取信息。
Servlet容器还为每个应用程序创建一个ServletContext实例(Servlet配置)。这个对象封装context(应用程序)的环境细节。每个Servlet实例还有一个封装Servlet配置信息的ServletConfig(Servlet上下文)。
三、Servlet接口
在Servlet接口中定义了以下5个方法
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
void destroy();
java.lang.String getServletInfo();
ServletConfig getServletConfig();
}
init、service和destroy方法方法属于Servlet生命周期方法。Servlet容器将根据以下原则调用这3个方法:
* init : 第一次请求Servlet时,Servlet容器就会调用这个方法。在后续的请求中,将不会在调用该方法。在调用该方法时,Servlet容器会传递一个ServletConfig对象。
* Service : 每次请求Servlet时,Servlet容器调用这个方法。必须在这里编写Servlet要执行的代码。在第一次请求Servlet时,Servlet容器都会调用init方法和service方法。至于后续的请求,只会调用service方法。
* destroy : 当卸载应用程序或关闭Servlet容器的时候,Servlet容器就会调用这个方法销毁Servlet,释放所占用的资源。
Servlet中另外两个方法getServletInfo和getServletConfig是非生命周期方法。
* getServletInfo : 返回Servlet的描述。
* getServletConfig :返回Servlet容器传递给init方法的ServletConfig。
必须要注意下线程的安全性。一个应用程序中的所有用户将共用一个Servlet实例,因此不建议使用类级变量。
四、Servlet的生命周期
Servlet生命周期可被定义为从创建直到毁灭的整个过程。其中,init( ),service( ),destroy( )是Servlet生命周期的方法。Servlet通过调用init ()方法进行初始化、调用service()方法来处理客户端的请求、调用destroy()方法来释放Servlet所占用的资源、最后由JVM的垃圾回收机制进行垃圾回收。
接下来,我们来编写一个简单的Servlet来验证一下它的生命周期
1、创建Servlet类调用javax.servlet接口中的Servlet
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
@WebServlet("/myServlet")
public class myServlet implements Servlet {
private transient ServletConfig servletConfig;
//初始化方法
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init方法初始化");
this.servletConfig = servletConfig;
}
//执行方法
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
System.out.println("service访问");
//从Servlet配置对象中获取当前Servlet的类名
String servletName = servletConfig.getServletName();
//设置响应报文的类型为html文本,其编码方式为utf-8(放在输出前)
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter(); //创建输出流
writer.print("Hello From"+servletName);
}
//销毁方法
public void destroy() {
System.out.println("执行销毁Servlet");
}
public ServletConfig getServletConfig() {
return servletConfig;
}
public String getServletInfo() {
return "My Servlet";
}
}
2、在Web.xml中配置Servlet
3、从浏览器访问myServlet,地址为:http://localhost:8080/app01/my
从动态图中,我们可以发现,在第一次访问时执行了init方法和service方法,之后再次发送请求时只执行了service方法,而关闭服务器时执行了destroy方法。
五、ServletRequest
每一个HTTP请求,Sevlet容器都会创建一个ServletRequest实例,传给Servlet的service方法。ServletRequest里面封装着用户的请求信息。
下面介绍ServletRequest中最常用的方法:getParameter()方法。该方法通常用来返回一个HTML表单域的值或者用来查询字符串的值。接下来,我们通过URL调用一个Servlet来获取这个URL所传递的参数。
//URL
http://localhost:8080/app01/my?name=LaoYe
//Servlet
request.getParameter("name");
最终结果如下图所示
六、ServletResponse
ServletResonse封装了响应内容,隐藏了将响应发给浏览器的复杂性。在调用Servlet的service方法之前,Servlet容器会先创建一个ServletResponse实际对象,将其作为第二个参数传递给servlet方法。
ServletResponse中定义的其中一个方法是getWriter方法。它返回可以将文本传递给客户端的java.io.PrintWriter对象。默认情况下,PrintWriter对象拆用ISO-8859-1编码,所以再传输之前,我们可以通过设置传输编码的格式,使客户端在编译的时候支持中文字符,例如:
//设置响应报文的类型为html文本,其编码方式为utf-8(放在输出前)
response.setContentType("text/html;charset=utf-8");
//创建输出流
PrintWriter writer = response.getWriter();
writer.print("传递过来的参数是:"+name);
在响应内容之前(例如HTML内容),应该先通过调用setContentType方法来设置响应的内容类型,比如,将text/html作为参数传递。如果没有设置响应内容类型,大多数浏览器会默认为HTML的形式显示响应内容,但是有一些浏览则会将HTML标签显示为普通文本。