上一篇介绍了在Web项目中web.xml文件的配置信息,本篇主要介绍里面非常重要的配置——Servlet配置,重点介绍与Servlet相关的几个接口和类,包括Servlet接口、ServletConfig接口、ServletContext接口、GenericServlet类、HttpServlet类。

1、Servlet介绍

什么是Servlet:

百度的解释是“小服务程序或服务连接器,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容”。Servlet是Java语言里面的一个接口,任何直接或间接实现了Servlet接口的类都可称为Servlet类。

Servlet与Tomcat的关系:

Tomcat 是Web应用服务器,是Servlet的容器。Tomcat 作为Servlet容器,在启动时可以创建Servlet类的实例,调用init()方法对Servlet进行初始化,同时负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户。可以说,Servlet是一种运行在支持Java语言的服务器上的组件。在web.xml文件中,通过<servlet>标签配置Servlet类的相关信息,详细配置请见 http://www.cnblogs.com/Y-oung/p/8401549.html 。

2、Servlet接口

先看源码:

package javax.servlet;

import java.io.IOException;

public abstract interface Servlet {
public abstract void init(ServletConfig paramServletConfig)
throws ServletException; public abstract ServletConfig getServletConfig(); public abstract void service(ServletRequest paramServletRequest,
ServletResponse paramServletResponse) throws ServletException,
IOException; public abstract String getServletInfo(); public abstract void destroy();
}

init():初始化方法,在Tomcat对Servlet实例化后,Servlet容器会调用init()方法来初始化该对象,让Servlet对象在处理客户请求前可以完成一些初始化工作,例如:建立数据库的连接,获取配置信息等。在Servlet的整个生命周期中,init()方法自始至终只会被调用一次。init()方法有一个类型为ServletConfig的参数,Servlet容器通过这个参数向Servlet传递配置信息。Servlet使用ServletConfig对象从web.xml文件中获取以名-值对形式提供的初始化参数。另外,在Servlet中,还可以通过ServletConfig对象获取描述Servlet运行环境的ServletContext对象,使用该对象,Servlet可以和它的Servlet容器进行通信。

如图中红圈里面的配置信息可以在MainServlet类的init()方法里面解析。

getServletConfig():该方法返回容器调用init()方法时传递给Servlet对象的ServletConfig对象,ServletConfig对象包含了Servlet的初始化参数(如上图红圈里的配置信息)。关于ServletConfig接口下面会介绍。

service():该方法是用来处理客户端请求(在service()方法被容器调用之前,必须确保init()方法正确完成)的核心方法。容器会构造一个表示客户端请求信息的请求对象(类型为ServletRequest)和一个用于对客户端进行响应的响应对象(类型为ServletResponse)作为参数传递给service()。在service()方法中,Servlet对象通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。

getServletInfo():该方法返回一个包括了关于Servlet的信息的字符串(如作者、版本和版权等信息),返回的应该是纯文本字符串,而不是任何类型的标记。

destroy():该方法用来销毁Servlet对象。当容器检测到一个Servlet对象应该从服务中被移除的时候,容器会调用该对象的destroy()方法,以便让Servlet对象可以释放它所使用的资源,该方法同样只会执行一次。当需要释放内存或者容器关闭时,容器就会调用Servlet对象的destroy()方法,在Servlet容器调用destroy()方法前,如果还有其他的线程正在service()方法中执行容器会等待这些线程执行完毕或者等待服务器设定的超时值到达。一旦Servlet对象的destroy()方法被调用,容器不回再把请求发送给该对象。如果需要改Servlet再次为客户端服务,容器将会重新产生一个Servlet对象来处理客户端的请求。在destroy()方法调用之后,容器会释放这个Servlet对象,在随后的时间内,该对象会被java的垃圾收集器所回收。

可以看到,Servlet接口里面只有五个方法:init()、getServletConfig()、service()、getServletInfo()、destroy()。其中init()、service()、destroy()三个方法是和servlet生命周期相关的方法,在生命周期的不同时间段内会执行不同的方法,其顺序是init()->service()->destroy()。其中init()、destroy()方法在servlet生命周期中都只执行一次,而service()方法可以多次执行。Servlet接口是Servlet类最底层、最基础、最重要的接口。

        3、ServletConfig接口

        先看源码:

package javax.servlet;

import java.util.Enumeration;

public abstract interface ServletConfig {
public abstract String getServletName(); public abstract ServletContext getServletContext(); public abstract String getInitParameter(String paramString); public abstract Enumeration<String> getInitParameterNames();
}

getServletName():获取web.xml文件里面的servlet的名字(即<servlet-name>标签配置的名字)。

getServletContext():获取ServletContext对象,下面会介绍ServletContext接口。

getInitParameter():获取web.xml文件在servlet标签中配置的参数值(注意是servlet标签,而不是其他标签配置的参数值)。

getInitParameterNames():获取在Servlet中所有初始化参数的名字,也就是key值,可以通过key值,来找到各个初始化参数的value值(注意返回的是枚举类型)。

       

可以看到,ServletConfig接口里面的方法主要是获取web.xml文件里和servlet相关的配置信息。

        4、ServletContext接口

        先看源码:

package javax.servlet;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Map;
import java.util.Set;
import javax.servlet.descriptor.JspConfigDescriptor; public abstract interface ServletContext {
public static final String TEMPDIR = "javax.servlet.context.tempdir";
public static final String ORDERED_LIBS = "javax.servlet.context.orderedLibs"; public abstract ServletContext getContext(String paramString); public abstract String getContextPath(); public abstract int getMajorVersion(); public abstract int getMinorVersion(); public abstract int getEffectiveMajorVersion(); public abstract int getEffectiveMinorVersion(); public abstract String getMimeType(String paramString); public abstract Set<String> getResourcePaths(String paramString); public abstract URL getResource(String paramString)
throws MalformedURLException; public abstract InputStream getResourceAsStream(String paramString); public abstract RequestDispatcher getRequestDispatcher(String paramString); public abstract RequestDispatcher getNamedDispatcher(String paramString); public abstract Servlet getServlet(String paramString)
throws ServletException; public abstract Enumeration<Servlet> getServlets(); public abstract Enumeration<String> getServletNames(); public abstract void log(String paramString); public abstract void log(Exception paramException, String paramString); public abstract void log(String paramString, Throwable paramThrowable); public abstract String getRealPath(String paramString); public abstract String getServerInfo(); public abstract String getInitParameter(String paramString); public abstract Enumeration<String> getInitParameterNames(); public abstract boolean setInitParameter(String paramString1,
String paramString2); public abstract Object getAttribute(String paramString); public abstract Enumeration<String> getAttributeNames(); public abstract void setAttribute(String paramString, Object paramObject); public abstract void removeAttribute(String paramString); public abstract String getServletContextName(); public abstract ServletRegistration.Dynamic addServlet(String paramString1,
String paramString2); public abstract ServletRegistration.Dynamic addServlet(String paramString,
Servlet paramServlet); public abstract ServletRegistration.Dynamic addServlet(String paramString,
Class<? extends Servlet> paramClass); public abstract <T extends Servlet> T createServlet(Class<T> paramClass)
throws ServletException; public abstract ServletRegistration getServletRegistration(
String paramString); public abstract Map<String, ? extends ServletRegistration> getServletRegistrations(); public abstract FilterRegistration.Dynamic addFilter(String paramString1,
String paramString2); public abstract FilterRegistration.Dynamic addFilter(String paramString,
Filter paramFilter); public abstract FilterRegistration.Dynamic addFilter(String paramString,
Class<? extends Filter> paramClass); public abstract <T extends Filter> T createFilter(Class<T> paramClass)
throws ServletException; public abstract FilterRegistration getFilterRegistration(String paramString); public abstract Map<String, ? extends FilterRegistration> getFilterRegistrations(); public abstract SessionCookieConfig getSessionCookieConfig(); public abstract void setSessionTrackingModes(
Set<SessionTrackingMode> paramSet) throws IllegalStateException,
IllegalArgumentException; public abstract Set<SessionTrackingMode> getDefaultSessionTrackingModes(); public abstract Set<SessionTrackingMode> getEffectiveSessionTrackingModes(); public abstract void addListener(String paramString); public abstract <T extends EventListener> void addListener(T paramT); public abstract void addListener(Class<? extends EventListener> paramClass); public abstract <T extends EventListener> T createListener(
Class<T> paramClass) throws ServletException; public abstract void declareRoles(String[] paramArrayOfString); public abstract ClassLoader getClassLoader(); public abstract JspConfigDescriptor getJspConfigDescriptor();
}

Tomcat为每个web项目都创建一个ServletContext实例,在Tomcat启动时创建,服务器关闭时销毁,在一个web项目中共享数据,管理web项目资源,为整个web配置公共信息等。每一个web项目都存在一个ServletContext实例,每个Servlet都可以访问它。可以看到,ServletContext接口里面的方法很多,下面根据功能介绍其中的方法。

在Web应用范围内存取共享数据的方法:

setAttribute(String paramString, Object paramObject):把一个Java对象与一个属性名绑定,并把它存入到ServletContext中。paramString参数指定属性名,paramObject参数标识共享的数据。
        getAttribute(String name):根据参数给定的属性名,返回一个Object类型的对象,它表示ServletContext中与属性名匹配的属性值。
        getAttributeNames():返回一个Enumeration对象,该对象包含了所有存放在ServletContext中的属性名。
        removeAttribute(String name):根据参数指定的属性名,从ServletContext中删除匹配的属性。

访问当前Web应用的资源:
        getContextPath():返回当前Web应用的URL入口。
        getInitParameter(String name):根据给定的参数名,返回Web应用范围内初始化参数值。在web.xml文件中,直接在<web-app>跟元素下定义的<context-param>元素表示应用范围内的初始化参数。
        getInitParameterNames():返回一个Enumeration对象,它包含了Web应用范围内的所有初始化参数。
        getServletContextName():返回Web应用的名字,即web.xml文件中<display-name>元素的值。
        getRequestDispatcher(String path):返回一个用于向其他Web组件转发请求的RequestDispatcher对象。

访问Servlet容器中的其他Web应用:
        getContext(String uripath):根据参数指定的URI,返回当前Servlet容器中其他Web应用的ServletContext对象。
        访问Servlet容器的相关信息:
        getMajorVersion():返回Servlet容器支持的Java Servlet API的主版本号。
        getMinorVersion();返回Servlet容器支持的Java Servlet API的次版本号。
        getServletInfo():返回Servlet容器的名字和版本。

访问服务器端的文件系统资源:
        getRealPath(String path):根据参数指定的虚拟路径,返回文件系统中的一个真实路径。
        getResource(String path):返回一个映射到参数指定的路径的URL。
        getResourceAsStream(String path):返回一个用于读取参数指定的文件的输入流。
        getMimeType(String file):返回参数指定的文件的MIME类型。

输出日志:
        log(String msg)向Servlet的日志文件中写日志。
        log(String message , java.lang.Throwable throwable):向Servlet的日志中写错误日志,以及异常的堆栈信息。

5、GenericServlet类

        先看源码:

package javax.servlet;

import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration; public abstract class GenericServlet implements Servlet, ServletConfig,
Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config; public void destroy() {
} public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
} public Enumeration<String> getInitParameterNames() {
return getServletConfig().getInitParameterNames();
} public ServletConfig getServletConfig() {
return this.config;
} public ServletContext getServletContext() {
return getServletConfig().getServletContext();
} public String getServletInfo() {
return "";
} public void init(ServletConfig config) throws ServletException {
this.config = config;
init();
} public void init() throws ServletException {
} public void log(String msg) {
getServletContext().log(getServletName() + ": " + msg);
} public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
} public abstract void service(ServletRequest paramServletRequest,
ServletResponse paramServletResponse) throws ServletException,
IOException; public String getServletName() {
return this.config.getServletName();
}
}

可以看到,GenericServlet类是一个抽象的(abstract)类,所以它无法被实例化。它继承了三个接口,其中Servlet和ServletConfig接口是前面介绍过的,可以看出GenericServlet类里面大多数方法都是这两个接口里面的方法,所以这个类其实是整合了这两个接口,给出了设计servlet的一些骨架,定义了servlet生命周期,还有一些得到名字、配置、初始化参数的方法,使得编写servlet类时更方便。GenericServlet类里面所有继承了这两个接口的方法的功能,在本文前面已经详细介绍,这里只说明一下这个类里面新增的方法:log(String msg)、log(String message, Throwable t)、init()。

两个log()方法:通过ServletContext对象将Servlet的类名和给定的信息写入log文件中。

两个init()方法:init(ServletConfig config)方法是实现了Servlet接口中的方法,作用是可以通过getServletConfig()方法获取ServletConfig对象。如果你覆盖了这个方法,你必须调用super.init(config),这样GenericServlet类的其他方法才能正常工作。而它下面还调用了无参的init()方法,也就是GenericServlet类自定义的无参方法。为什么还要定义这个无参数的init()方法呢?其实这个无参数的init()方法是专门留给开发者使用的,开发者只需要覆盖这个方法就可以很方便的在方法里面扩充一些功能,比如对自己写的Servlet类初始化时可以在这个方法里面进行,解析web.xml文件里面关于servlet配置的信息时可以在这个方法里面。这样就不需要覆盖init(ServletConfig config)方法了,不需要存储config对象,也不需要调用super.init(config)。

尽管GenericServlet类实现了Servlet和ServletConfig接口的功能,但它的service方法中的参数还是ServletRequest,ServletResponse,它处理的还只一般的Servlet请求,并没有跟http相关对象挂钩。service方法是和应用层协议无关的,也就是说你有可能用非http协议实现它。而我们平时通过浏览器访问网站时,基本上都是HTTP请求(当然还有FTP请求),请求方式包括GET、POST等,显然如果直接使用service方法会很繁琐,所以提供了一个HttpServlet类来解决这些问题,这个类继承了GenericServlet类,除了能实现其所有方法,还根据HTTP请求的特性进行了扩充,使得其更能有效地处理基于HTTP协议的请求。

6、HttpServlet类

这个类的源码有点长,不再详细展示,有兴趣可以去看源码,这里通过类的结构图说明。

其中HTTP协议的请求类型与其对应的实现方法见下表:

该类继承了GenericServlet类,用于接收基于Http协议的请求,并对请求进行处理,然后做出响应。一般在web开发中,开发者自己编写的Servlet类只需要继承HttpServlet类即可。这里我们重点介绍两个service()方法。

service(ServletRequest req, ServletResponse res):通过源码可以发现,此方法是GenericServlet类的service()方法的实现,他把ServletRequest和ServletResponse对象分别强制转化为HttpServletRequest和HttpServletResponse对象,并把强制转化后的对象作为参数,调用另一个重载的service(HttpServletRequest req, HttpServletResponse resp)方法。

service(HttpServletRequest req, HttpServletResponse resp):通过源码可以看出,这个方法会根据不同的HTTP请求类型(GET、POST或其他),调用不同的实现方法(doGet()、doPost()或其他)。这样一来,当开发者自己编写Servlet类时(继承HttpServlet类),我们只需要覆盖(重写)doGet()、doPost()或其他doXXX()方法就可以了,而不需要覆盖(重写)service()方法,这样就简化了许多。实际上笔者在开发中遇到的几个项目的servlet类中都是覆盖(重写)了doGet()、doPost()方法,而没有覆盖(重写)service()方法。

 7、总结

本篇着重介绍了和servlet相关的几个比较重要的接口和类,下面通过图片说明它们之间的继承关系:

在实际的web项目中,如果需要开发者自己写servlet类,一般直接继承HttpServlet类即可。在用Tomcat加载servlet类时,如果需要初始化一些信息(比如解析web.xml文件中<servlet>标签下的配置信息),可以覆盖(重写)无参的init()方法;如果要处理GET请求,可以覆盖(重写)doGet()方法;如果要处理POST请求,可以覆盖(重写)doPost()方法。init()、doGet()、doPost()这三个方法是笔者在开发web项目中遇到最多的,基本上自己写的servlet类里面,都是继承了HttpServlet类,覆盖(重写)了这三个方法。

Servlet及相关类和接口的更多相关文章

  1. Web---演示Servlet的相关类、下载技术、线程问题、自定义404页面

    Servlet的其他相关类: ServletConfig – 代表Servlet的初始化配置参数. ServletContext – 代表整个Web项目. ServletRequest – 代表用户的 ...

  2. Servlet的相关类--ServletConfig(接口)

    ServletConfig是一个接口,有关配置文件的 servlet的配置信息<---对应--->ServletConfig web.xml配置文件会被加载到内存中,然后解析器会对它进行解 ...

  3. Web---演示Servlet的相关类、表单多参数接收、文件上传简单入门

    说明: Servlet的其他相关类: ServletConfig – 代表Servlet的初始化配置参数. ServletContext – 代表整个Web项目. ServletRequest – 代 ...

  4. Servlet主要相关类核心类 容器调用的过程浅析 servlet解读 怎么调用 Servlet是什么 工作机制

      WEB简介   Web项目 是 B/S结构 浏览器/服务器模式的 浏览器发起请求,服务器作出响应   请求的发起和响应使用HTTP协议进行通讯 所谓协议也就是一种固定格式   而Socket是应用 ...

  5. Eclipse检出原MyEclipse项目后 javax.servlet.http相关类都报错【我,体现着一类jar包问题的处理方法】

    用Eclipse检出原来为myEclipse搭建的一个项目,检出后,所有关于httpservlet的类都报异常,说有没实现的方法? 但这个项目之前人家用MyEclipse运行都是没有问题的, 按住CT ...

  6. Hibernate的常用关键类以及接口介绍

    上一篇初步的对Hibernate进行了认识,并测试了Hibernate的HelloWorld, 这里主要介绍HibernateTest类中的相关类和接口,以及其作用和特性,关于Session中的相关方 ...

  7. Java基础之Java常用类--Object类,字符串相关类,包装类,日期相关类,数字相关类

    Java是一种面向对象的语言,也就是将万事万物可以描述为对象,特点如下: 1.面向对象是常见的一种思考习惯,符合人们的思考习惯.2.面向对象的出现,将复杂的事情简单化.3.面向对象的出现,将之前过程中 ...

  8. Servlet API遍程常用接口和类

    本文主要总结Servlet  API遍程常用接口和类 Servlet API http://tomcat.apache.org/tomcat-5.5-doc/servletapi/index.html ...

  9. JavaWeb知识回顾-Servlet常用类、接口及其方法

    今天主要把servlet的一些常用的类.接口和方法简单回顾一下. javax.servlet包 1.javax.servlet.Servlet接口 接口用于开发servlet,所有的servlet都要 ...

随机推荐

  1. Java 内存区域和GC机制(转载)

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  2. SpringMVC 异常记录

    在使用SpringMVC中开发过程中,遇到的一些坑,简单记录一下. 1.The request sent by the client was syntactically incorrect 从字面意思 ...

  3. C# -- 使用递归列出文件夹目录及目录下的文件 神技do{}while(false)

    C# -- 使用递归列出文件夹目录及目录下的文件 使用递归列出文件夹目录及目录的下文件 1.使用递归列出文件夹目录及目录下文件,并将文件目录结构在TreeView控件中显示出来. 新建一个WinFor ...

  4. linode下更换内核(debian,ubuntu,centos)

    1.首先到这个网址下载你需要得内核文件,以genric:http://kernel.ubuntu.com/~kernel-ppa/mainline/ 如果系统是 64 位,则下载 amd64 的 li ...

  5. python学习之pypandoc

    对于程序员来说,文件格式之间的转换是一件非常费劲的事!比如md文件转化为html文件. 于是乎,就有一群牛人搞出了个神器,他就是pandoc. 而python中,对应的第三方模块就是pypandoc. ...

  6. hMailServer之允许用户自己修改密码

    使用hMailServer搭建邮件系统,使用webmail实现web收发邮件,但是又个问题是在webmail中用户自己无法修改密码. 可以使用hMailServer自带的PhpWebAdmin来实现让 ...

  7. java创建web服务

    java开发web服务的方法有很多,但是常用的就两种一种是开发时用,一种发布时用.开发时使用jax-ws注解的方式开发调试,发布时使用tomcat. 注解方式: http://www.cnblogs. ...

  8. Centos6.5 --配置 vsftp server

    事实上我这么懒得人是不想配置什么ftpserver的(毕竟动起来都认为麻烦).可是因为本菜鸟才刚開始步入linux的大坑.尽管有装Centos7的真机,可是因为一时还是脱离不了Windows平台,所以 ...

  9. FastDFS 常见问题

    FastDFS 常见问题 Q:/fdfs_trackerd: error while loading shared libraries: libevent-1.4.so.2: cannot open ...

  10. Linux 下使用静态google protocl buffer

    在Linux上编译google protobuff时,configure 默认选项是生成动态库,即libprotobuf.so文件.如果同时在多个动态库(动态库以dlopen方式动态加载)中使用同一b ...