ServletRequest和ServletResponse

基于Servlet的web应用交互过程

web应用通常是基于http的请求响应模式,一个使用servlet实现的web应用典型的交互过程以下:
 
1) 客户端向web服务器发起一个HTTP请求;
2) HTTP请求被web服务器接受,并移交给servlet引擎;
3) servlet引擎根据配置决定调用那个servlet,并把request对象、response对象传给它。
4) servlet经过request获取用户信息和请求的内容,servlet处理完请求后把要返回的信息放入response对象;
5)一旦servlet完成了请求的处理,servlet引擎就会刷新response,把控制权返回给web服务器;
6)web服务器将从servlet引擎获取的内容返回给客户端;
 
 

ServletRequest和ServletResponse

在Servlet规范中,ServletRequest表明客户端对服务器的请求,ServletResponse表明服务器给给客户端的响应;
 
其中,最重要的是HttpServletRequest 和 HttpServletResponse 这两个子接口;
 
这两个接口就是对http协议的请求和响应作面向对象的封装。
 
 

HttpServletRequest

在基于servlet的web应用交互中,客户端经过http协议发送请求至服务器,请求中会包含不少信息,如客户端的浏览器信息以及请求内容等等;这些信息被包含在http头和消息体中,而且以name-value的形式存在,一个name能够对应多个value。
 
web服务器接到客户端的http请求后会转发给内部的servlet容器处理;
 
serlve容器拿到请求后,会解析http请求包含的信息,而后将这些信息封装成HttpServletRequest对象,并传给合适的servlet实例进行处理;
 
一、请求参数
 
经过HttpServletRequest的下列方法,能够获取这些参数信息:
 
  • getParameter(String arg0)
  • getParameterNames()
  • getParameterValues(String arg0)
 
须要注意的是getParameterValues(String arg0)获取的是与arg0对应的value数组,getParameter(String arg0)获取的是value数组中的第一个值;
 
若是过URI中的参数为a=1;POST中的参数为a=2,a=3;请求中的参数a={1,2,3}。
 
若是 想获取请求的路径参数,则必须经过解析方法getRequestURI()或getPathInfo()返回的字符串。
 
二、属性
 
request的属性就是一些对象;
 
容器能够将一些不能经过默认接口表达的信息经过属性的方式设置到request中;
 
也能够 设置一些属性用来在servlet之间的通讯
 
request对象中的关于属性方法有:
  • getAttribute(String arg0)
  • getAttributeNames()
  • setAttribute(String arg0,Object arg1)
与参数不一样,这里一个属性名称只能关联一个value。
 
以“java.”或“javax.”为前缀的属性名是规范保留的,相似的“sun.”“com.sun”是sun公司的保留字,这些保留的前缀是不能使用的。
 
三、头信息
 
经过HttpServletRequest的下列方法,servlet能够获取http请求的头信息:
  • getHeader
  • getHeaders
  • getHeaderNames
getHeader 方法返回头的名称。一个名称能够关联多个头信息,若是在这种状况下,getHeader
方法返回第一个头信息。
 
getHeaders返回与一个名称关联的全部头信息存放在Enumeration对象中。
 
HttpServletRequest提供了一些提取头信息的类型转换方法,如:getIntHeader 把头信息中的数据转换成int型等。
 
四、请求路径
 
一个请求映射到一个servlet上,其请求路径包含了不少重要的部分,包括Context Path、Servlet Path、PathInfo。
 
其对应的方法有以下三个:
 
  • getContextPath
  • getServletPath
  • getPathInfo
 
除了编码方式不一样外,下列等式是正确的:
 
requestURI = contextPath + servletPath + pathInfo
 
例如:
 
配置关系以下
 
Conteext Path: /catalog
 
Servlet:LawnServlet
Servlet Mapping Pattern:/lawn/*
 
Servlet:GardenServlet
Servlet Mapping Pattern:/garden/*
 
Servlet:JSPServlet
Servlet Mapping Pattern:*.jsp
 
注意下面的路径的组成
 
 
/catalog/lawn/index.htm;ContextPath:/catalog;ServletPath:/lawn;PathInfo:/index.html
 
/catalog/garden/implements/;ContextPath:/catalog;ServletPath:/garden;PathInfo:/implements/
 
/catalog/help/feedback.jsp;ContextPath:/catalog;ServletPath:/help/feedback.jsp;PathInfo:null
 
 
五、路径转换方法
 
在API中有两个简单的方法容许开发者得到文件系统的路径:
  • ServletContext.getRealPath
  • HttpServletRequet.getPathTranslated
getRealPath(String aPath)方法返回本地文件系统的绝对路径。
 
getPathTranslated方法计算出请求pathInfo中的绝对路径。
 
以上的两个方法,servlet引擎不能辨认文件的路径是否有效,当web应用调用一个不肯定远程文件系统,或数据库路径中的文件时,会返回null。
 
 
六、cookie
 
 
HttpServletRequest接口中提供了getCookies方法来返回请求中的cookies数组;
 
在每次客户端请求时cookies数据就从客户端发送给服务器。
 
客户端返回的cookie信息是cookie的name和cookie的value。
 
当cookie被发送至浏览器时,cookie的信息就会被设置。
 
 
七、SSL属性
 
若是一个请求是经过一个安全协议进行传输的,例如HTTPS,那么这个信息必须经过ServletRequest的isSecure方法进行暴露。并且web容器必须将下列属性暴露给开发人员:
 
Attribute Atrribute Name Java type
Cipher suite javax.servlet.request.cipher_suite String
bit size of the algo-rithm javax.servlet.request.key_size Integer
 
 
 
 
 
若是过一个请求中包含一个SSL证书信息,servlet引擎必须把它做为一个数组对象暴露给servlet开发者,能够经过ServletRequest属性中的javax.servlet.request.X509Certificate属性得到,该数组的类型为java.security.cert.X509Certificate。
 
数组排列的顺序是按照信任程度的升序,第一个证书是客户端设置的,第二个用来验证第一个,以此类推。
 
八、国际化
 
客户端能够经过http头信息的 Accept-Language来告诉web服务器客户端想要哪种语言的响应;
 
ServletRequest中提供的相关方法以下:
  • getLocale
  • getLocales
getLocale方法将返回客户端首选的Locale。
 
getLocales方法返回一个Enumeration,从首选的locale开始递减。
 
若是客户端没有制定首选的locale, servlet引擎必定要提供一个默认的locale供getLocale方法返回,getLocales方法必须包含一个默认的locale的locale element
 
 
九、请求数据的编码
 
 
有许多web浏览器不发送带有“content-type”头信息的字符编码限定符, 而由读取http请求的代码来决定字符的编码方式。
 
默认状况下, 若是客户端请求未定义编码限定符,容器(如tomcat)会用“ISO-8859-1”去建立request reader和解析POST的数据;
 
为了向开发者指明客户端没有发送字符编码信息的状况,容器对getCharacterEncoding方法返回null。
 
若是客户端不设置字符编码方式,而且request不是按照以上缺省编码方式(ISO-8859-1)来编码,则会发生问题。
 
为了解决这个问题,在接口ServletRequest中加入了一个新的方法setcharacterencoding(string encoding)。开发者能够调用这个方法来替换包容器提供的缺省字符编码方式。
 
可是,必须在从request中分析任何post数据或者读取任何输入以前调用这个方法。 一旦数据已被读取,则调用这个方法将不会影响编码方式
 
注意: 自从Tomcat5.x开始,GET和POST方法提交的信息,tomcat采用了不一样的方式来处理编码,对于POST请求,Tomcat会仍然使用request.setCharacterEncoding方法所设置的编码来处理,若是未设置,则使用默认的iso-8859-1编码。而GET请求则不一样,Tomcat对于GET请求并不会考虑使用request.setCharacterEncoding方法设置的编码,而会永远使用iso-8859-1编码
 
 
十、request对象的生命周期
 
request对象只有在servlet的service()方法或者filter的doFilter()方法中才有效;
 
为了不建立request对象的性能消耗, 容器会重用request对象
 
因此不能在上述范围之外持有对request的引用,不然会出现难以预料的错误。

HttpServletResponse

请求被servlet处理后,通常都会返回处理的结果信息,这些信息被封装到HttpServletResponse对象中并返回给servlet容器;
 
servlet容器将HttpServletResponse对象转化成http响应交给web服务器,web服务器获得响应后将其转发给客户端;
 
一、缓存
 
为了提升效率,servlet容器容许将发送给客户端的内容进行缓存;典型的服务器都会使用缓存,而且容许servlet指定缓存参数。
 
ServletRequest接口中关于缓存的方法以下:
  • getBufferSize
  • setBufferSize
  • isCommitted
  • Reset
  • resetBuffer
  • flushBuffer
这些方法只在servlet调用ServletOutputStream或者Writer以前有效。
 
当使用的缓存已满时,容器必须马上刷新把缓存的内容发送到客户端,若是这是第一个被发送到客户端的数据,那么response也会被认为是已提交。
 
二、头信息
 
servlet能够经过ServletResponse接口设置响应的头信息,以下方法:
  • setHeader
  • addHeader
  • setIntHeader
  • setDateHeader
  • addIntHeader
  • addDateHeader
在response被提交前头信息必须被设置,不然无效。
 
开发人员有责任设置Content-Type头信息,用来表示servlet生成的内容类型。
 
HTTP1.1规范没有要求设置这个头信息,因此当开发人员没有设置这个类型时容器不必设置一个默认值。
 
三、简单的方法
 
在HttpServletResponse接口中有下列简单的方法:
  • sendRedirect
  • sendError
sendRedirect方法会设置合适的头信息和消息体,使客户端重定向到两一个url;
 
若是参数是一个相对路径,底层容器会将其转换成绝对路径发送给客户端;若是转换失败则抛出IllegalArgumentException;
 
sendError方法同上。
 
四、国际化
 
servlet应该设置一个response的local和字符编码。
 
local使用ServletRespnse的setLocal方法,若是response被提交前没有设置local,容器的默认local会被使用。
 
setCharacterEncoding用来设置字符编码,response默认的编码方式是“ISO-8859-1”。
 
五、response对象的关闭
 
当一个response对象被关闭,容器必须当即将缓存中的内容发送给客户端。下列条件表示servlet已经知足请求的内容并关闭response对象:
 
  • servlet方法service结束;
  • response中经过setContentLength设置的指定数量的信息被写入到response;
  • 调用sendError方法;
  • 调用sendRedirect方法。
 
六、response对象的生命周期
 
同request对象的生命周期。
 
 

问题:

 
一、HttpServletRequest对象是怎么被容器重用的?
 
能够参考http://bbs.csdn.net/topics/300088535