Servlet3.0规范

Servlet3.0规范

​ HTTP协议规定了客户端与服务之间的通信规范。那么当client请求的数据到达服务端的时候,我们应该怎么处理它,应该以什么样的数据接口代表它呢?

​ servlet规范定义了java web处理请求的一整套接口规范,包括请求数据结构,响应数据结构,请求处理逻辑等等。

servlet容器

​ servlet容器是web server或应用服务的一部分,该Web服务器或应用程序服务器提供通过其发送请求并返回响应的网络服务,解码基于MIME的请求并格式化基于MIME的响应。

​ servlet处理请求的逻辑:

  1. 客户端向一个web服务器发送一个http请求
  2. 请求被web服务器接收,并移交给servlet容器进行处理。
  3. servlet容器根据servelt配置以及url决定那个servlet被调用来处理这个请求,并使用表示请求和响应的对象调用它。
  4. Servlet使用请求对象来查找远程用户是谁,请求已经发送了哪些HTTP POST参数以及其他相关数据。servlet自行自定义逻辑,并通过response将响应数据发送给客户端。
  5. servlet处理完请求后,servlet容器将响应对象中的数据输出到客户端,将response控制权返回给web server。

​ 所以,servlet定义请求处理逻辑,request构建请求数据结构,response构建响应数据,再加上session等一些辅助对象,一起完成整个HTTP通信。

Servlet接口

​ servlet接口是java servlet api的抽象,它定义了一系列的模板方法,用来执行处理http请求的逻辑。所有的servlet实现类必须直接或间接的实现改接口。为了减少开发者的工作量,在java servlet api中由两个实现了改接口的类,分别是GenericServlet和HttpServlet。在大多数情况下,开发者会继承HttpServlet来实现他们自己的servlet。

service方法请求处理方法

​ servlet容器将请求路由到一个servlet实例,然后调用service方法处理该请求。servlet开发人员需要保证service方法的并发调用,应为web容器经常(但不是必须)将并发请求映射到同一个servlet实例,再不同线程中进行并发处理。

特定请求处理方法

​ HttpServlet增加了常用请求的处理方法,当HttpServlet实现类(未重写service方法)被调用的时候,service方法会根据HTTP method调用对应的方法经处理改请求。所以当开发者通过继承HttpServlet来开发自己的servlet时,它可以通过重写下列方法来处理自己关心的请求:

  • doGet
  • doPost
  • doPut
  • doDelete
  • doHead
  • doOptions
  • doTrace

生命周期

​ servlet的生命周期由loading,instantiated,initialized,handle request,destroy等几个阶段。servlet在启动或者在第一次调用的时候进行加载,实例化,初始化等操作,在每次调用的时候处理请求,在服务器判断需要销毁servlet 的时候,调用它的destroy方法,然后被gc回收。

​ servlet在各个阶段都可能会遇到exception,会抛出响应的Exception实例,由响应的处理机制。

异步处理

​ 有时servlet需要等待一些资源,才能对请求做出对应的响应。如果在servlet方法中阻塞不仅效率低下,还浪费了计算机资源(线程,jdbc连接其他有限的资源等)。

​ servlet3.0增加了异步处理请求的特性,让线程完成这个请求,将结果返回给容器,等待处理其他请求。异步处理的基本步骤如下:

  1. 接收请求,通过filter和权限验证等,到达servlet。
  2. servlet根据请求参数得出这个请求的性质。
  3. servlet发出对资源或数据的请求。
  4. servlet返回但是不生成response
  5. 一段时间后,资源和数据获取完毕,处理该事件的线程继续处理,或者将改请求进行转发。

​ 异步处理很多问题待完善!

deployment descriptor

​ 在容器启动的时候,需要知道一些参数信息,来支持程序的启动,比如由哪些servlet,以及servlet与URL的映射关系,有哪些filter,filter的映射关系等等。deployment descriptor用来保存web容器的配置信息的文件。

deployment descriptor支持下列元素进行配置程序需要的信息:

  • ServletContext初始化参数
  • Session configuration
  • servlet Declaration
  • Servlet Mapping
  • Application lifecycle Listener class
  • Filter Declaration and filter mapping
  • MIME type mapping
  • welcome file list
  • error page
  • local and encoding mappings
  • security configuration,including login configuration,security-constraint,security-role,security-role-ref and run-as

在Java servlet 2.4及其以前,the deployment descriptor以XML方式进行配置,文件名规定为web.xml。

通过解析deployment descriptor,servlet容器获取了改web应用程序的所有信息,就可以构建一个web application。

ServletContext

​ 在解析deployment descriptor后,servlet容器构建一个ServletContext用来存储部署描述符中的这些信息。ServletContext代表一个web application,映射到一个特定的URL,所有该URL的请求都交给这个web application 进行处理。这个ServletContext又会根据URL的sub Component寻找到特定的servlet进行处理这个URL。

​ 一个deployment descriptor都可以配置ServletContext的初始化参数。可以通过ServletContext接口的getInitParameter和getInitParameterNames方法访问这些参数。

​ 可以用ServletContext接口的一些方法配置servlet,listener,filter和URL pattern等信息。

​ 可以通过ServletContext接口的setAttribute,getAttribute,getAttributeNames,removeAttribute等方法在ServletContext中操作属性,在servlet之间进行消息传递,但是当时在一个分布式系统中的时候,需要借用其他工具来达到在所有servlet之间共享数据的目的。

​ ServletContext接口的getResource,getResourceAsStream方法可以获取web application下面的静态文件(html,jpg,git等)。这两个方法接收一个字符串作为参数。这些方法首先在web application的根路径下找寻符合参数的路径,如果找不到,会到WEB-INF/lib下的jar中的META-INF/resources路径下查找。

​ 这些方法不会去寻找动态文件,比如jsp。

request

​ servlet规范用request对象封装http请求的所有数据。并通过一定的方法来访问请求消息数据。

​ request message中有三类数据,请求行,请求头,请求体。request对象有三类数据结构用来封装request message中的数据,parameter,header,body。他们的对应关系如下:

​ 请求行中的url结构如下:

​ <scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

​ 其中qury部分会被封装到parameter数据集里。初次之外,http或者https的post请求中,如果请求头content type的值是 application/x-www-form-urlencoded,当调用了getParameter或相关方法时,该请求体中的数据会被放入parameter中,不可以通过request输入流获取,如果没有调用过,那么请求体里面的依然可以通过request对象的输入流获取。

​ 另外一点,get请求中的路径参数没有被封装到parameter中,而是需要通过getRequestURI或getPathInfo方法访问。

​ 如果请求类型是multipart/form-data,且servlet上有@MultipartConfig注解,那么可以通过getParts()或getPart(String name).访问part的内容,这两个方法都会返回Part类型,通过part对象,可以访问part中头 ,内容类型,也可以通过getInputStream内容返回part中的内容。对于使用form-data作为Content-Disposition但没有文件名的part,还可以使用part的名称通过HttpServletRequest上的getParameter / getParameterValues方法获得部件的字符串值。

​ attribute是request扩展的一个数据集,它是用来在服务端进行数据传输的,只有在服务端设置,才能在其他地方访问它。

​ servlet规范将request message中的请求头内容封装到了request对象的header数据集中,通过getHeader getHeaders
■ getHeaderNames方法可以访问这些对象。

​ 在http请求中,请求行中的url结构如下:

​ <scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

​ request对象对url的结构中的path部分做了处理,将<path>分为了三个部分,Context Path,Servlet path,PathInfo。.request到servlet的映射过程如下:

  1. request请求到达servlet容器,servlet容器取出url中的path部分,servlet容器根据配置信息,将path和各个servlet context的配置前缀做对比,如果成功,这个servlet context的配置前缀就是context path;如果匹配失败,将该请求匹配到默认的servlet context,context path就是空字符串。
  2. 匹配到一个servlet context上后,去除context path,我们path剩余部分继续和servlet的匹配路径做匹配。这一部分就是servlet path,如果servlet匹配路径时/*和“”,那么servlet path时空字符串。
  3. path去除context path和servlet path只有即使pathinfo了。它要么时null,要么就是一个/开头的字符串。

response

​ respone对象封装了server向client返回的所有信息,client一般通过response的响应头和响应体获取响应信息。

​ 我们知道http响应消息分为响应行,响应头,响应体三部分。不像请求体时可选的,响应体时必须要有的(header方法除外),响应消息大部分都是通过响应体来传递的。而无论是响应头还是响应体,我们都是通过流的方式取读取和写入的。在server向response写入请求体时,先写入response中的一个buffer中(为了效率),这个buffer的一些参数可以通过一些方法来控制。

​ 当buffer满了以后,或者调用flush方法,response方法会将buffer中数据传递给客户端,这时候,response的状态就是已提交状态,就不能reset buffer了。特别的,当response为close状态时,buffer中的内容会立即返回给客户端。以下动作会将response状态改为close。

  • servlet的service方法运行结束

    • 输出内容达到ContentLength的大小。

    • sendErr方法被调用

    • sendRedirect方法被调用

    • 异步响应时,complete方法被调用。

参考资料:

《servlet3.0规范》

浏览器对form表单的处理方式

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

推荐阅读更多精彩内容

  • 这部分主要是与Java Web和Web Service相关的面试题。 96、阐述Servlet和CGI的区别? 答...
    杂货铺老板阅读 1,396评论 0 10
  • IOC 控制反转容器控制程序对象之间的关系,而不是传统实现中,有程序代码之间控制,又名依赖注入。All 类的创建,...
    irckwk1阅读 924评论 0 0
  • Servlet接口 Servlet规范的核心接口即是Servlet接口,它是所有Servlet类必须实现的接口,在...
    java日记阅读 1,812评论 0 2
  • 1.web服务器(web server)和应用服务器(appliction server)的区别是什么? web服...
    onlyHalfSoul阅读 600评论 0 0
  • 1.web服务器(web server)和应用服务器(appliction server)的区别是什么? web服...
    伐无道阅读 935评论 0 0