Servlet技术(上)

Servlet技术(上)

Tomcat的<CATALINA_HOME>/lib/servlet-api.jar文件为Servlet API的类库文件。Servlet API主要由两个Java包组成:

  • Javax.Servlet 包中定义了Servlet接口以及相关的通用接口和类
  • Javax.servlet.http 主要定义了与HTTP协议相关的HttpServlet、HttpServletRequest接口和HttpServletResponse接口

Servlet接口

所有的Servlet类都必须实现这个接口,Servlet接口中定义了5个方法,其中3个方法都由Servlet容器来调用,容器会在Servlet的生命周期的不同阶段调用特定的方法

  • init(ServletConfig config) 该方法负责初始化Servlet对象,容器在创建好Servlet对象后,就会调用该方法
  • service(ServletRequest req,ServletResponse resp):负责响应客户的请求,为客户提供相应服务。容器接收到客户端要求访问特定Servlet对象的请求,就会调用该Servlet对象service()方法。
  • destory()方法:负责释放Servlet对象占用的资源。当Servlet对象结束生命周期时,容器会调用此方法

Servlet接口还定义了连个返回Servlet的相关信息的方法。Java Web应用中的程序代码可以访问Servlet的这两个方法,从而获取Servlet的配置信息以及其他相关信息:

  • getServletConfig():返回一个ServletConfig对象,该对象中包含了Servlet的初始化参数信息
  • getServletInfo():返回一个字符串,该字符串中包含了Servlet的创建者、版本和版权等信息

GenericServlet抽象类

GenericServlet抽象类为Servlet接口提供了通用实现,GenerivcServlet除了实现Servlet接口,还实现了ServletConfig接口和序列化Serializable接口

HttpServlet抽象类

HttpServlet类是GenericServlet类的子类,HttpServlet类为Servlet接口提供了与HTTP协议相关的通用实现。HttpServlet对象社和运行在客户端采用HTTP协议通信的Servlet容器或Web服务器中。

HttpServlet为所有针对特定请求的方式的doXXX()方法提供了默认的实现。在HttpServlet类的默认实现中,doGET()、doPost()、doPut()和doDelete()都可以向客户端返回一个错误:

  • 405
  • 400

ServletRequest接口

Servlet接口的Service方法中有一个ServletRequest类型的参数。ServletRequest类表示来自客户端的请求。当Servlet容器接收到客户端要求访问特定Servlet的请求时,容器先解析客户端的原始请求数据,将它包装成一个ServlertRequest对象。当容器调用Servlet对象的service()方法时,就会把ServletRequest对象作为参数传给service()方法

  • getContentLength() 返回请求正文的长度。如果请求正文的长度未知 返回-1
  • getContentType() 获得请求正文的MIME类型,如果请求正文的类型未知返回null
  • getInputStream() 返回用于读取请求正文的输入流
  • getLocalAddr() 返回服务器端IP地址
  • getLocalName() 返回服务器端的主机名
  • getLocalPort() 返回服务器端的FTP端口号
  • getParameter(String name) 根据指定的请求参数名,返回来自客户请求中匹配的请求参数
  • getProtocol():返回客户端与服务器端通信所用的协议的名称以及版本号
  • getReader():返回用于读取字符串形式的请求正文的BufferedReader对象
  • getRemoteAddr():返回客户端IP地址
  • getRemoteHost():返回客户端的主机名
  • getRemotePort():返回客户端的FTP端口号

HttpServletRequest接口

HttpServletRequest接口时ServletRequest接口的子接口,HttpServlet类的重载service()方法以及doGet()和doPost()等都有一个HttpServletRequest的形参

  • getContextPath() 返回客户端所请求访问的Web应用的URL入口。项目路径
  • getCookies() 返回请求中的所有cookie
  • getHeader(String name) 返回HTTP请求头部的特定项
  • getHeaderNames() 返回包含所有HTTP请求头部的所有项目名
  • getMethod() 返回HTTP请求方式
  • getRequestURI() 返回HTTP请求的头部URI
  • getQueryString() 返回请求中的查询字符串 URL中?后面的内容

HTTPServletResponse接口

Servlet通过ServletResponse对象来生成响应结果,当Servlet容器接收到客户端要求访问特定Servlet的请求时,容器会创建一个ServletResponse对象,并传递给Servlet的service()方法

  • setCharacterEncoding(String charset)设置响应正文的字符编码
  • setContentLength(int len) 设置响应正文的长度
  • setContentType(String type) 设置响应正文的MIME类型
  • getCharacterEncoding() 返回响应正文的字符编码
  • getContentType() 返回响应正文的MIME
  • setBufferSize(int size) 设置存放响应正文数据的缓冲区大小
  • getBufferSize() 获取存放响应正文数据的缓冲区大小
  • reset() 清空缓冲区内的正文数据,并且清空响应状态码以及响应头
  • resetBuffer() 仅清空缓冲区内的正文数据,不清空响应状态码以及响应头
  • flushBuffer() 强制性地把缓冲区内的响应正文发送到客户端
  • isCommitted() 用于返回数据是否以及发送到客户端
  • getOutputStream() 返回一个ServletOutputStream对象,Servlet用来输出二进制正文数据
  • getWriter() 返回PrintWriter对象,Servlet用来输出字符串形式的正文数据

在Tomcat的实现中,如果Servlet的service()方法没有调用ServletOutputStream或PrintWriter的close()方法,那么Tomcat在调用完Servlet的service()方法后,会关闭ServletOutputStream或PrintWriter

HttpServletResponse接口

HttpServletResponse接口是ServletResponse的子接口。

HttpServletResponse接口提供了与HTTP协议相关的一些方法,Servlet可通过这些方法来设置HTTP响应头或客户端写Cookie

  • addHeader(String name,String value)向HTTP响应头中加入一项内容
  • sendError(int sc) 向客户端发送一个代表特定错误的HTTP响应状态代码
  • setHeader(String name,String value):设置HTTP响应头中的一项内容,如果响应头中以及存在,原先所做的设置将被覆盖
  • setStatus(int sc):设置HTTP响应的状态代码
  • addCookie(Cookie cookie):向HTTP响应中加入一个Cookie

ServletConfig接口

当Servlet容器初始化一个Servlet对象时,会为这个Servlet对象创建一个ServletConfig对象。ServletConfig对象中包含了Servlet的初始化参数信息,ServletConfig还与当前Web应用的ServletContext对象关联。Servlet容器调用Servlet对象的init(ServletConfig config)方法时,会把ServletConfig对象作为参数传给Servlet对象。

HttpServlet继承GenericServlet类,GenericServlet实现ServletConfig接口,因此在HttpServlet类或GenericServlet类以及子类中都可以直接调用ServletConfig接口中的方法

ServletContext接口

ServletContext是Servlet与Servlet容器之间进行通信的接口,Servlet容器在启动一个Web应用时,会为它创建一个ServletContext对象。每个Web应用都有唯一的ServletContext对象。Servlet对象们可以通过这个类来访问Servlet容器中的各种资源

1. 用于在Web应用范围内存取共享数据

  • setAttribute(String name,Object object) 把java对象与一个属性名绑定,存入ServletContext中。name指定属性名
  • getAttribute(String name) 根据参数给定的属性名,返回一个Object类型的对象
  • getAttributeNames():返回所有存放在ServletContext中的属性名
  • removeAttribute(String name):根据参数指定的属性名,从ServletContext中删除匹配的属性

2. 访问当前Web应用的资源

  • getContextPath() 放回当前Web应用的URL入口
  • getInitParameter(String name):根据指定的参数名,返回Web应用范围内的匹配的初始化参数值
  • getInitParameterNames() 返回包含Web应用范围内所有的初始化参数名
  • getServletContextName() 返回Web应用的名字
  • getRequestDispatcher(String path):返回一个用于向其他Web组件转发请求的RequestDispathcer对象

3. 访问Servlet容器中的其他Web应用

  • getContext(String uripath) 根据参数指定的URI返回当前Servlet容器中其他Web应用的ServletContext对象

4. 访问Servlet容器的相关信息

  • getMajorVersion():返回Servlet容器支持的Java Servlet API的主版本号
  • getMinorVersion():返回Servlet容器支持的Java Servlet API的次版本号
  • getServerInfo() 返回Servlet容器的名字和版本

5. 访问服务器端的文件系统资源

  • getRealPath(String path) 根据参数指定的虚拟路径,返回文件系统中的一个真实路径
  • getResource(String path)返回一个映射到参数指定的路径的URL
  • getResourceAsStream(String path):返回一个用于读取参数指定文件的输入流

6. 输出日志

  • log(String msg) 向Servlet的日志文件中写日志
  • log(String message,Throwable throwable) 向Servlet的日志文件中写 错误日志,以及异常的堆栈信息

JavaWeb应用的生命周期

Java Web应用的生命周期是由Servlet容器来控制,Java Web应用的生命周期包括三个阶段

  • 启动阶段:加载Web应用的有关数据,创建ServletContext,对Filter和一些Servlet进行初始化
  • 运行时阶段:为客户端提供服务
  • 终止阶段:释放Web应用所占用的各种资源

启动阶段

Servlet容器在启动JavaWeb应用时,会完成以下操作

  1. 把web.xml文件中的数据加载到内存中
  2. 为JavaWeb应用创建一个ServletContext对象
  3. 对所有的Filter进行初始化,Filter的初始化是在JavaWeb容器启动时完成的
  4. 对需要在Web应用启动时就初始化的Servlet进行初始化。

运行时阶段

在这个阶段,它的所有Servlet都处于待命状态,随时可以响应客户端的特定请求,提供相应的服务。如果客户端请求的Servlet还不存在,Servlet容器会先加载并初始化Servlet,然后再调用它的service()服务方法

终止阶段

Servlet容器在终止JavaWeb应用时,会完成以下操作

  1. 销毁JavaWeb应用中所有处于运行时状态的Servlet。
  2. 销毁JavaWeb应用中所有处于运行状态的Filter
  3. 销毁所有与JavaWeb应用相关的对象,如ServletContext对象等,并且释放Web应用所占用的相关资源

Servlet的生命周期

初始化阶段

  1. Servlet容器加载Servlet类,把它的.class文件中的数据读入到内存中
  2. Servlet容器创建ServletConfig对象。
  3. Servlet容器创建Servlet对象
  4. Servlet容器调用Servlet对象的init方法

经过初始化步骤创建了Servlet对象和ServletConfig对象,并且Servlet对象与ServletConfig对象关联,而ServletConfig对象与当前Web应用的ServletContext对象关联。当Servlet容器初始化完Servlet后,Servlet对象只要通过getServletContext() 就能得到当前Web应用的ServletContext对象

Servlet进入初始化阶段的情况

  1. 当Web应用处于运行时阶段,Servlet被客户端首次请求访问,Servlet会被Servlet容器初始化
  2. 如果在web.xml中为Servlet设置了<load-on-startup>元素,当Servlet容器启动Servlet所属的Web应用时,就会初始化这个Servlet
  3. Web应用被重新启动时,Web应用中的所有Servlet都会重新初始化

运行时阶段

在这个阶段中,Servlet可以随时响应客户端的请求,当Servlet容器接收到要求访问特定Servlet的客户请求,Servlet容器创建针对于这个请求的ServletRequest对象和ServletResponse对象,然后调用相应的Servlet对象的service()方法。service()方法从ServletRequest对象中获得客户请求信息并处理该请求,通过ServletResponse对象生成响应结果。

销毁阶段

当Web应用被终止时,Servlet容器会先调用Web应用中所有Servlet对象的destroy)方法,然后再销毁这些Servlet对象。在destory()方法的实现中,可以释放Servlet所占用的所有资源。

容器还会销毁与Servlet关联的ServletConfig对象

ServletContext与Web应用范围

当Servlet容器在启动一个Web应用时,会为它创建唯一的ServletContext对象。当Servlet容器终止一个Web应用时,就会销毁它的ServletContext对象、

Web应用范围的含义

  • Web应用范围表示由Web应用的生命周期构成的时间段
  • 表示在Web应用生命周期内所有Web组件的集合

特点

  • 共享数据的生命周期位于Web应用的生命周期中的一个时间片段内

  • 共享数据可以被Web应用中的所有Web组件共享

  • Web应用范围内可以存放各种类型的共享数据。Java对象可有与ServletContext对象关联,该Java对象的生命周期会依附ServletContext对象的生命周期。Web组件可以通过ServletContext对象来访问它

常用API

  • setAttribute(String name,Object obj) 向Web应用范围内存入共享数据。参数name指定属性名,参数object表示共享数据
  • removeAttribute(String name):根据参数给定的属性名,从Web应用范围内删除匹配的共享数据
  • getAttribute(String name):根据参数给定的属性名,返回Web应用范围内匹配的共享数据

ServletContextListener 监听器

Servlet API中有ServletContextListener接口,它能够监听ServletContext对象的生命周期。当Servlet容器启动或终止Web应用,会触发ServletContextEvent事件,该事件由ServletContextListener处理

  • contextInitialized(ServletContextEvent sce) 当Servlet容器启动Web应用时调用该方法,调用完该方法后,会对Filter初始化,并对需要在Web应用启动时就需要初始化的Servlet进行初始化
  • contextDestroyed(ServletContextEvent sce) 当Servlet容器终止Web应用时调用该方法。在调用该方法之前,容器会销毁所有的Servlet和Filter过滤器

防止页面被客户端浏览器缓存

浏览器为了快速向用户展示所请求的页面,会将来自服务器端的网页存放在客户端的缓存中。如果浏览器的缓存中已经存在该网页,那么浏览器只需从缓存中获取该网页,而不再请求服务器上的网页

但是有一些情况我们不希望数据被浏览器缓存

  • 当网页包含随时会被更新的动态内容。防止数据展示出现异常
  • 网页中包含敏感数据

服务器端的HttpServlet可通过设置特定HTTP响应头来禁止客户端缓存网页

response.setHeader("Cache-Control","no-cache");
或者
response.setHeader("Expires","0");

Expires用于设定网页过期的时间,如果为0,表示立即过期

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容