起源之路——Servlet(二)
序
上期说完了Servlet的生命周期,这次来说一些关于请求的概念。
什么是请求
实际上请求就是一个有自描述性的文本封装成数据包通过TCP/IP协议发送给服务器,在HTTP协议中是客户端发送到服务器的HTTP头和消息体。
Http协议参数
Servlet请求参数以字符串的形式作为请求的一部分从客户端发送到servlet容器。容器从URL和Post数据域中获取数据填充参数。参数以一些列的键值对形式保存。ServletRequest中有一下方法可以访问这些参数:
- getParameter
- getParameterNames
- getParameterValues
- getParameterMap
Post表单能填充到参数集(Paramter Set)必须满足以下条件
- 该请求是HTTP或HTTPS请求
- 该HTTP请求方法是POST
- 内容类型是application/x-www-form-urlencoded
- 该servlet已经对请求对象的任意getParameter方法进行了初始调用。
文件上传
当数据内容类型为multipart/form-data时。Servlet容器支持文件上传。
如果满足以下任何一个条件,则servlet提供multipart/form-data格式数据的处理:
- servlet处理的请求使用了注解@MultipartConfig
- 部署描述符包含了一个multipart-config元素
如果容器提供multipart/form-data格式数据的处理,可以通过HTTPServletRequest中的getParts()或getPart得到数据,Part.getInputStream方法访问头部,相关内容类型和内容,对于表单数据Content-Disposition,即使没有文件名也可以通过HttpServletRequestd的getParameter和getParameterValues得到part的字符串值。
如果容器不提供multipart/form-data格式数据的处理,则这些数据可以通过HTTPServletRequest.getInputStream()得到。(这是目前很常见的方式)
属性
属性是与请求相关联的对象,可以由容器设置来表达信息或者由Servlet通过RequestDispatcher转发给另一个servlet。一个属性名只能关联一个属性值,属性通过以下方法来访问:
- getAttribute
- getAttributeNames
- setAttribute
头
通过下面方法,servlet可以访问请求的头信息:
- getHeader :返回给定头名称(键key)的头值,如果多个头的名称(键key)相同,则会返回请求中的第一个
- getHeaders: 访问所有与特定头名称(键key)相关的头值,返回一个String对象的枚举
- getHeaderNames
- getIntHeader
- getDateHeader
请求路径元素
- Context Path(上下文路径):通过getContextPath来获取路径信息,它是与ServletContext上下文相关联的路径前缀。如果这个上下文是基于Web服务器URL命名空间基础上的“默认”上下文,他们它是一个空串。如果不是基于服务器的命名空间,这个路径以“**/**开始。
- Servlet Path(Servlet路径):通过getServletPath来获取路径信息,路径部分直接与激活请求映射对应,以“/”字符开头,如果请求与“/*”或“”模式匹配,则它是一个空串。
- PathInfo Path:通过getPathInfo来获取路径信息,请求路径的一部分,如果没有额外路径,那么它是null或是以“/”开头的字符串
在编码一致的情况下,等式requestURI=contextPath+servletPath+pathInfo永远成立。
例如上下文设置如下表:
ContextPath | /catalog |
---|---|
Servlet Mapping | Pattern:/lawn/* Servlet:LawnServlet |
Servlet Mapping | Pattern:/garden/* Servlet:GardenServlet |
Servlet Mapping | Pattern:*.jsp Servlet:JSPServlet |
则必定遵守下列行为
请求路径 | 路径元素 |
---|---|
/catalog/lawn/index.html | 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 |
路径转换
通过ServletContext.getRealPath和HttpServletRequest.getPathTranslated来获取某个特定路径等价的文件系统路径。
非阻塞IO
非阻塞IO与AJAX请求数据的模式非常类似,它允许开发者在数据可用时读取数据或在数据可写时写数据,即当数据可读时,线程读取数据,读取完后交个下一线程去进行处理,当前线程无需阻塞等待,可以继续读取下一份可用数据;同理数据在处理完成后可写时,才通知线程去写数据。
cookie
HttpServletRequest.getCookies 方法来获得请求中的一个cookie数组。它是从客户端发送到服务器端的每个请求上的数据。典型地,客户端发送回的作为 cookie 的一部分的唯一信息是 cookie 的名称和 cookie 值。当 cookie 发送到浏览器时可以设置其他 cookie 属性,诸如注释,这些信息不会返回到服务器。该规范还允许的 cookies 是 HttpOnly cookie。HttpOnly cookie不会暴露给客户端脚本代码(它没有被过滤掉,除非客户端知道如何查找此属性)。使用 HttpOnly cookie 有助于减少某些类型的跨站点脚本攻击。
SSL属性
如果请求通过一个安全协议发送,如 HTTPS,必须通过ServletRequest 接口的 isSecure 方法公开该信息。Web 容器必须公开下列属性给 servlet 程序员:
属性 | 属性名称 | Java类型 |
---|---|---|
密码套件 | javax.servlet.request.cipher_suite | String |
算法的位大小 | javax.servlet.request.key_size | Integer |
SSL 会话 id | javax.servlet.request.ssl_session_id | String |
如果有一个与请求相关的 SSL 证书,它必须由 servlet 容器以java.security.cert.X509Certificate 类型的对象数组暴露给servlet 程序员并可通过一个javax.servlet.request.X509Certificate 类型的 ServletRequest属性访问。数组的顺序按照信任的升序顺序。证书链中的第一个证书由客户端设置,第二个是用来验证第一个的,等等。
国际化
通过Accept-language头信息来设定首选语言环境。通过getLocale和getLocales来获取相关信息
请求数据编码
通过Context-Type头信息来设定首选的数据编码字符集,如果客户端请求没有指定请求默认的字符编码,容器用来创建请求读取器和解析 POST 数据的编码必须是“ISO-8859-1”。ServletRequest 接口添加了一个新的方法 setCharacterEncoding(String enc)。开发人员可以通过调用此方法来覆盖由容器提供的字符编码。必须在解析任何 post 数据或从请求读取任何输入之前调用此方法。此方法一旦调用,将不会影响已经读取的数据的编码。
请求对象的生命周期
每个请求对象只在一个 servlet 的 service 方法的作用域内,或过滤器的 doFilter 方法的作用域内有效,除非该组件启用了异步处理并且调用了请求对象的 startAsync 方法。在发生异步处理的情况下,请求对象一直有效,直到调用 AsyncContext 的 complete 方法。容器通常会重复利用请求对象,以避免创建请求对象而产生的性能开销。不建议在上述范围之外保持 startAsync 方法还没有被调用的请求对象的引用,因为这样可能产生不确定的结果。
参考链接: 来自waylau翻译的《Java Servlet 3.1 规范》
自己使用整理收集,如有侵权 请联系删除!