Servlet

来源:互联网 发布:防身器材 淘宝 编辑:程序博客网 时间:2024/06/06 10:56


servlet概述

Servlet (Server Applet),全称Java Servlet。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

服务器上需要一些程序,如根据用户输入访问数据库的程序。在Servlet API产生之前,这些通常是使用公共网关接口(Common Gateway Interface,CGI)应用程序完成的。CGI技术用于创建动态web应用程序。CGI技术有许多缺点,如为每个请求创建单独的进程、依赖于平台代码(C、C++)、内存消耗大和性能低等。

CGI 和 Servlet

>Servlet在处理时间、内存利用率等方面表现更好。因为servlet使用多线程技术,为每个请求创建一个新线程。这自然就比为每个请求创建新进程的CGI技术要快很多,并且节省内存资源。

>Servlet是平台无关的,使用Servlet开发的web应用程序可以运行在任何标准的web容器中,如Tomcat、JBoss、Glassfish服务器。同样可以在任何操作系统中,如Windows、Linux、Unix、Solaris、Mac等。

>Servlet是健壮的,因为servlet容器负责管理servlet的生命周期,我们不需要担心内存泄漏、安全、垃圾收集等问题。

>Servlet是易维护的,并且学习曲线小。因为在使用Servlet的时候我们只需要关注业务逻辑就可以了。

Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

自MVC规范出现后,Servlet的作用被明确为仅仅作为控制器使用,不在生成页面标签,也不作为视图层角色使用。

Servlet 的主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。这个过程为:

① 客户端发送请求至服务器端;
② 服务器将请求信息发送至 Servlet;
③ Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
④服务器将响应返回给客户端。

一个 Servlet 就是 Java 编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。虽然 Servlet 可以对任何类型的请求产生响应,但通常只用来扩展 Web 服务器的应用程序。

Servlet API

javax.servlet.Servlet是Servlet API的最上层接口。还有一些其他的接口和类是我们在使用servlet的时候需要关注的。在Servlet 3.0规范中,建议使用的注解我们也需要了解。先了解一下Servlet API层次结构。

这里写图片描述

Servlet接口

javax.servlet.Servlet 是Servlet API的最上层接口,Servlet接口定义了一系列servlet的生命周期方法(init、service、destory等)。所有的Servlet类都需要继承这个接口。

这里写图片描述

该接口中定义了以下方法:

这里写图片描述

public abstract void init(ServletConfig paramServletConfig) throws ServletException- 该方法由servlet容器调用,用于初始化servlet以及servlet配置参数。在init()方法执行之前,servlet是无法处理用户请求的。在servlet生命周期中该方法只会被调用一次,他会使servlet类不同区别于普通的java对象。我们可以扩展该方法来初始化资源,如数据库连接、socket连接等。

public abstract ServletConfig getServletConfig() - 该方法返回一个servlet配置对象,其中包含servlet中所有初始化参数和启动配置。我们可以用这个方法来获取servlet的初始化参数,这些参数一般被定义在web.xml或servlet 3的注解中。后面会介绍ServletConfig接口。

public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException- 该方法负责处理客户端请求。当servlet容器收到客户端请求时,它会创建一个新线程并执行service()方法,并把request 和 response作为参数传递给该方法。servlet通常运行在多线程环境中,所以开发人员应该使用同步来保证访问共享资源的线程安全性问题。

public abstract String getServletInfo() - 这个方法返回包含servlet信息的字符串,比如它的作者、版本和版权。返回的字符串应该是纯文本,不能有标记符号。

public abstract void destroy() - 这个方法在整个servlet生命周期中只会被调用一次来关闭所有资源。有点像Java中的finalize方法。

GenericServlet抽象类

GenericServlet抽象类实现了Servlet接口、ServletConfig接口和Serializable接口。GenericServlet使得开发人员更加容易地编写自定义servlets,它提供了生命周期的init()和destroy()方法以及ServletConfig接口的方法的“简易版本”,该类中定义的大部分方法都是让用户更放方便的使用Servlet和ServletConfig接口中定义的常用方法。开发者自定义的servlet只要继承该抽象类,然后重写service()方法即可。

这里写图片描述

GenericServlet里主要实现了Servlet接口、ServletConfig接口的方法,还实现了log()方法,该方法在ServletContext接口里声明。

这里写图片描述

GenericServlet里还有一个重要的方法——无参数的init方法。如果我们必须在处理请求之前初始化一些资源,那么可以重写该方法。

HTTPServlet抽象类

HTTPServlet 类是GenericServlet类的子类,开发者通过开发自定类继承该抽象类,来创建基于HTTP的web应用程序。继承HTTPServlet抽象类的子类至少要重写一个HTTPServlet抽象类里的方法。

这里写图片描述

HTTPServlet抽象类里的结构。

这里写图片描述

通常客户端的请求主要有GET和POST请求,自定义Servlet类为了响应这两种请求,必须重写doGet()和doPost()方法,默认调用doGet方法。get方法会在地址栏中显示用户名和密码,post方法不会,在安全性上get小于post;提交内容的大小上get小于post,get提交的数据小于2k,post提交的数据理论上不受限制,实际应用中一般不大于64k;响应速度上get要快于post,get要求服务器立即处理请求,而post请求可能形成一个队列请求。

如果自定义Servlet类为了响应4种方式的请求,则需要重写上面的4个方法。
一般情况下,自定义Servlet类对应所有请求的响应都是一样的。这样可以重写一个方法来代替上面的几个方法,即只要重写service()方法及可响应客户端的所用请求。

- init(ServletConfig config): 创建Servlet实例时,调用该方法初始化Servlet资源;

- destroy(): 消耗Servlet实例时,自动调用该方法的回收资源。

通常这两个方法不需要重写,除了要在初始化Servlet时,完成某些资源初始化的方法,才考虑重写init()方法。如果要在销毁Servlet之前,先完成某些资源的回收,比如数据库连接等,才需要重写destroy()方法。

不用为自定义Servlet类写构造器,如果需要初始化该自定义Servlet类,应将初始化操作放在自定义Servlet类的init()方法中定义。如果重写了init(ServletConfig config)方法,则应在重写该方法的第一行调用super.init(config),该方法将调用HttpServlet的init方法。

ServletConfig 接口

当一个servlet初始化期间servlet容器会通过servlet配置对象传递信息给该servlet。

这里写图片描述

ServletConfig用于描述servlet本身的相关配置信息。每个servlet都有属于它自己的ServletConfig对象,该对象由servlet容器负责实例化。可以在web.xml中提供初始化参数,当然在servlet3.0中可以使用注解。我们可以使用getServletConfig()方法来获取ServletConfig的对象。看该接口里的结构。

这里写图片描述

ServletContext 接口

ServletContext接口用于描述应用程序的相关信息。ServletContext是一个独立的对象,可用于web应用程序中所有的servlet。当我们想要一些初始化的参数可用于web应用程序中多个或全部servlet时,我们可以使用ServletContext对象并且在web.xml中使用标签定义参数。我们可以通过ServletConfig 中的 getServletContext()方法得到ServletContext对象。

这里写图片描述

接口结构。

这里写图片描述这里写图片描述


使用Servlet示例

package com.afy.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class FirstServletDemo extends HttpServlet {    @Override    public void init() throws ServletException {        System.out.println("=========init without parameters=======");        super.init();    }    @Override    public void init(ServletConfig config) throws ServletException {        System.out.println("=========init with parameters=======");        super.init(config);    }    @Override    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("========= service =======");        PrintWriter pw = response .getWriter();        pw.println("Hi there,would you wanna play a game?");        pw.close();    }    @Override    public void destroy() {        System.out.println("=========destroy=======");        super.destroy();    }   }

FirstServletDemo类继承了HttpServlet类,表明它可以作为Servlet使用。其中定义了service方法来响应用户请求,通过HttpServletRequest获取客户端的form请求参数与,并显示请求参数的值。
Servlet与JSP相比:

  • Servlet中没有内置对象,原理JSP中的内置对象都必须有程序显式创建;
  • 对应静态的HTML标签,Servlet都必须使用页面输出流逐行输出。

JSP是Servlet的简化,使用JSP只需程序员输出到客户端的内容,至于JSP脚本如何嵌入一个类中,则有JSP容器完成。而Servlet是个完整的Java类,这个类的service()方法用于生成对客户端的响应。
普通Servlet类里的service方法的作用等同于JSP生成Servlet类的_jspServlet()方法。

Servlet的配置

写好的Servlet源文件不能响应用户的请求,必须将其编译成class文件。一般.class文件放在WEB-INF/classes路径下

要Servlet响应用户请求,必须将Servlet配置在Web应用中。配置Servlet一般是在web.xml文件中操作的。
Servlet3.0开始,配置Servlet有两种方式

  • 在Servlet类中使用@WebServlet注解进行配置
 @WebServlet(name="FirstServletDemo",urlPattern={"/Hi"})
  • 通过web.xml文件配置

这里写图片描述

因此,配置一个响应客户请求的Servlet,至少需要配置两个元素:Servlet的名字和Servlet的URL。

以上示例中,如果在web.xml中配置了Servlet的名字和URL,则该Servlet的URL为/Hello,如果没有配置web.xml文件,则该Servlet类上的@WebServlet注解就会起作用,该Servlet的URL为/Hi。

JSP/Servlet的生命周期

JSP本质就是Servlet,写好的JSP页面将由Web容器编译成对应的Servlet,当Servlet在容器中运行时,其实例的创建和销毁等都不是由程序员决定的,而是由Web容器进行控制的。
创建Servlet实例有两种情况
- 客户端第一次请求某个Servlet时,系统创建Servlet的实例:大部分的Servlet是这种情况创建的;
- Web应用启动时立即创建Servlet实例,即load-on-startup Servlet。


每个Servlet的运行都遵循如下生命周期

1. 创建Servlet实例;
2. Web容器调用Servlet的init方法,对Servlet进行初始化;
3. Servlet初始化后,将一直存在容器中,用于响应客户端请求。如果客户端发送Get请求,容器调用Servlet的doGet方法处理并响应请求;如果客户端发送Post请求,容器调用Servlet的doPost方法处理并响应请求。或者统一使用service()方法处理响应用户请求。
4. Web容器决定销毁Servlet时,先调用Servlet的destroy方法,通常在关闭Web应用之时销毁Servlet。

这里写图片描述


load-on-startup Servlet

我们已经知道创建Servlet实例有两个时机:用户请求时应用启动时。应用启动时就创建Servlet,通常用于某些后台服务的Servlet,或者需要拦截很多请求的Servlet;这种Servlet通常作为应用的基础Servlet使用,提供重要的后台服务。配置load-on-startup的Servlet有两种方式。

  • 在web.xml文件中通过< servlet…/>元素的< load-on-startup…/>子元素进行配置;
  • 通过@WebServlet注解的loadOnStartup属性指定。

< load-on-startup…/>元素或loadOnStartup属性都只接收一个整型值,这个整型值越小,Servlet就越优先优化实例化。
代码示例

@WebServlet(loadOnStartup=1)public class TimerServlet extends HttpServlet{    public void init(ServletConfig config)throws ServletException{    super.init(config);    Timer t = new Timer(1000,new ActionListener(){    public void actionPerformed(ActionEvent e){        System.out.println(new Date());    }    });    t.start();    }}


这个Servlet没有提供service()方法,这表明它不能响应用户请求,所以无须为它配置URL映射。该Servlet仅仅执行计数器功能,每隔一段时间会在控制台打印出当前时间。由于它不能接收用户请求,所以只能在应用启动时实例化。
web.xml文件中配置代码

< servlet>    <load-on-startup>1</load-on-startup>< /servlet>

1 0
原创粉丝点击