4、客户请求的处理:表单数据
- 表单数据可以跟在问号后附加到URL的结尾(Get);表单数据还可以在单独的行中发送到服务器(Post)
- 使用FORM元素创建HTML表单
<form action="…"></form>
使用输入元素收集用户数据<input type="text" name="…">
在接近表单的尾部放置提交按钮<input type="submit">
-
在servlet中读取表单数据
- getParameter:单个值单独读取,参数名对大小写敏感;返回单个字符串,对应参数首次出现时的值。如果参数存在但没有相应的值,返回空的String;如果没有这样的参数,返回null
- getParameterValues:多个值的读取,返回字符串的数组;最好保证每个文本字段、复选框或其他用户界面元素都有唯一名称,以避免使用getParameterValues
- getParameterNames和getParameterMap:参数名的查找,不要指望getParameterNames会以任何特定的次序返回参数名;getParameterNames以Enumeration的形式返回参数列表,其中的每一项都可以转化成String,并可以用在getParameterNames或getParameterValues调用中。Enumeration只是一个接口,保证实际的类实现了hasMoreElements和nextElement方法。替代方案是getParameterMap,返回一个Map——参数名(字符串)是表的键,参数的值(字符串数据,与getParameterNames返回值相同)是表的值。
- getReader或getInputStream:原始表单数据的读取及对上载文件的分析;当数据来自于定制的客户程序或上载的文件时,可能需要读取原始的输入
- setCharacterEncoding:多字符集输入的读取;按照某个字符集读取参数,然后将它转换到另外的字符集或者使用某些字符串提供的自动检测特性
- 在表单中,一定要使用相对ACTION URL,不要使用绝对URL。以斜杠开头的表单URL可以增进可移植性。
- 要检查字符串是否为空字符串,可以使用equals方法与“”比较,或将字符串长度与0比较。不要使用==运算符,==总是用来测试两个参数是否为同一对象,而非相似性。为了安全起见,最好调用trim移除用户输入的任何空格
if((param == null) || (param.trim().equals("")))
。在设计servlet时要使之能够优雅地处理参数缺失(null或空字符串)或格式不正确的情况。 - 如果你在循环中执行字符串拼接操作,不要使用String,要使用StringBuffer、
5、客户请求的处理:HTTP请求报头
- 在使用请求报头(
request.getHeader("报头的名称")
)之前要确保它不是null。报头名称对大小写不敏感。- getCookies:Cookie报头,存储在由Cookie对象构成的数组中
- getAuthType和getRemoteUser:Authorization报头
- getContentLength:返回Content-Length报头的值(作为一个int值)
- getContentType:返回Content-Type报头的值(作为一个String)
- getDateHeader和getIntHeader:读取指定报头,转换成Date和int值
- getHeadNames:得到一个Enumeration,枚举当前特定请求中所有的报头名称
- getHeaders:获取一个Enumeration,枚举报头每次出现对应的值
- getMethod:返回主请求方法(一般是GET或POST,也可能是HEAD、PUT、DELETE)
- getRequestURI:返回URL中主机和端口之后,表单数据之前的部分
- getQueryString:返回表单数据
- getProtocol:返回请求行的第三部分,一般为HTTP/1.0或HTTP/1.1
- HTTP1.1请求报头:对请求报头的访问,使得servlet能够执行许多优化,并提供大量特性
- Accept:能够处理的MIME类型
- Accept-Charset:使用的字符集
- Accept-Encoding:能够处理的编码类型(gzip、compress)
- Accept-Language:客户程序首选的语言(en、en-us、da等)
- Authorization:在访问密码保护的web页面时,用来标识身份
- Connection:标明客户是否能够处理持续性HTTP连接
- Content-Length:给定POST数据的大小,以字节为单位
- Cookie:向服务器返回cookie,使用request.getCookies
- Host:标明原始URL中给出的主机名和端口名
- If-Modified-Since:仅当页面在指定的日期之后发生更改的情况下重载,应该实现getLastModified方法,让系统自动处理修改日期;用在GET请求中“仅当文档比我缓存的版本要新时,才传送该文档”
- If-Unmodified-Since:用在PUT请求中“仅当我生成这个文档后,没有其他人对它做出更改时,才更新这个文档”
- Referer:标明引用Web页面的URL,一种跟踪请求来源的有用方式
- User-Agent:生成请求的浏览器或其他客户程序,可以针对不同类型的浏览器返回不同的内容
- gzip文本压缩方案能够极大地减少HTML页面的大小;对于篇幅较长的文本页面,Gzip压缩可以极大地降低下载时间。实现压缩:servlet首先检查Accept-Encoding报头,检查它是否包含有关gzip的项;如果支持,使用PrintWriter封装GZIPOutputStream,并指定Content-Encoding响应报头的值为gzip;如果不支持,使用正常的PrintWriter,并省掉Content-Encoding报头。
- 使用getServletContext().getRealPath得出URL的实际路径;使用request.getRemoteHost和reque.getRemoteAddress获取客户端的名称和IP地址
- 来自浏览器或其他客户程序的请求,由一个HTTP命令、0或多个请求报头(Host是必须的)、一个空行以及一些查询数据(POST请求)
6、服务器响应的生成:HTTP状态代码
- Web服务器对请求的响应,一般由一个状态行、一些响应报头、一个空行和相应的文档构成。状态行由HTTP版本、一个状态代码、一段对应状态代码的简短消息。如HTTP/1.1 200 OK
- 设置任意状态代码:使用HttpServletResponse的setStatus方法;在向客户程序发送任何文档内容之前设置状态代码。setStatus(状态代码,int类型)尽量使用常量,如SC_NOT_FOUND,不使用明确数字,如404
response.setStatus(response.SC_NO_CONTENT
- 设置302和404状态代码,HttpServletResponse专为两种常见情况提供快捷方法
- public void sendRedirect(String url):302命令浏览器连接到新的位置
- public void sendError(int code, String message):404用于服务器没有找到文档的情况
- 要牢记,如果要发送输出,必须首先调用setStatus或sendError
- HTTP 1.1 状态代码(通过检查
request.getRequestProtocol
检验客户程序是否支持HTTP 1.1)- 100-199:信息性的,标示客户应该采取的其他动作
- 100(SC_Continue,继续):客户程序询问是否可以在随后的请求中发送附加文档;417(SC_EXPECTATION_FAILED)告诉浏览器不接受该文档
- 200-299:表示请求成功
- 200(SC_OK,一切正常)
- 202(SC_ACCEPTED,已接受):请求已接受,但处理尚未完成
- 204(SC_NO_CONTENT,没有新文档):继续显示之前的文档
- 205(SC_RESET_CONTENT,重置内容):指示浏览器清楚表单的字段
- 300-399:用于那些已经移走的文件,包括Location报头,指出新的地址
- 301(SC_MOVED_PERMANENTLY,被永久移动):所请求的文件已被移往别处
- 302(SC_MOVED_TEMPORARILY,找到):浏览器立即重新连接到新的URL,并不显示任何中间输出
- 303(SC_SEE_OTHER,检查其他文档)
- 304(SC_NOT_MODIFIED,未发生更改):表示缓存的版本是最新的,客户程序应该使用它
- 307(Temporary Redirect,临时重定向):对于GET请求的重定向继续进行,对于POST请求的重定向不再进行
- 400-499:由客户引发的错误
- 400(SC_BAD_REQUEST,错误请求):客户请求中含有语法错误
- 401(SC_UNAUTHORIZED,未授权):客户程序访问密码保护的页面,Authorization报头中没有正确的身份标识信息
- 404(SC_NOT_FOUND,未找到):给定的地址下找不到任何资源
- 405(SC_METHOD_NOT_ALLOWED,方法不允许)
- 415(SC_UNSUPPORTED_MEDIA_TYPE,不支持的媒体类型):服务器不知道如何处理请求附加文件的类型
- 417(Expectation Failed,期望不能满足)
- 500-599:由服务器引发的错误
- 500(SC_INTERNAL_SERVER_ERROR,服务器内部错误):服务器陷入混乱
- 501(SC_NOT_IMPLEMENTED,未实现):服务器不支持客户程序发送的命令
- 503(SC_SERVICE_UNAVAILABLE,服务不可用):由于维护工作或超负荷工作,服务器不能做出响应
- 505(SC_HTTP_VERSION_NOT_SUPPORTED,不支持的HTTP版本)
- 100-199:信息性的,标示客户应该采取的其他动作
-
重定向主要用于:
- 计算目的地
- 跟踪用户的行为
- 执行边界效应
7、服务器响应的生成:HTTP响应报头
- 响应报头可以用来:指定cookie;提供页面的修改日期用于客户端缓存;指示浏览器在指定的时间间隔后重载页面;给出文件的大小使持续性HTTP连接的应用成为可能;指定生成文档的类型以及执行许多其他任务
- 指定报头必须在返回实际的文档之前,通用的方式
setHeader(String headerName, String headerValue
;两个专门用来设置含有日期和整数的报头:setDateHeader(String header, long milliseconds)
和setIntHeader(String header, int headerValue)
- 指定常用报头的方法:
- setContentType(String mimeType)
- setContentLength(int length)
- addCookie(Cookie c)
- sendRedirect(String address)
- HTTP 1.1 响应报头(使用HTTP 1.1之前最好用request.getRequestProtocol检查HTTP的版本):
- Allow:指定服务器支持的请求方法
- Cache-Control:什么环境可以安全地缓存文档,可能取值有public、private、no-cache、no-store、must-revalidate、proxy-revalidate、max-age=xxx、s-max-age=xxx
- Connection:持续性连接需要Content-Length响应报头,servlet没有必要显示使用Connection报头。不使用持续性连接可以省略Content-Length报头
- Content-Disposition:向客户发送非HTML响应时尤其有用
- Content-Encoding:编码方式
- Content-Language:文档使用的语言
- Content-Length:响应中的字节数
- Content-Type:给出响应文档的MIME类型
- Expires:规定内容的过期时间,例如指示浏览器不要缓存文档超过10分钟
long currentTime = System.currentTimeMillis();
long tenMinutes = 10*60*1000; // in milliseconds
response.setDateHeader("Expires",currentTime + tenMinutes);
- Last-Modified:文件的最后修改时间
- Location:通知浏览器文档的地址
- Pragma:设为no-cache,指示HTTP1.1客户不要缓存文档
- Refresh:指定下一次多长时间更新,不支持持续性更新;30秒后请求新的副本
response.setIntHeader("Refresh", 30);
;通过在刷新时间之后添加分号和一个URL,实现指定载入页面response.setHeader("Refresh", "5; URL=http://host/path/");
(可以用来显示闪屏splash screens)
间接地设置<META HTTP-EQUIV="Refresh" CONTENT="5"; URL=http;//host/path/">
- Retry-After
- set-Cookie:不属于HTTP1.1,最初是一项Netscape扩展,但现在被各种浏览器广泛支持
- WWW-Authenticate:客户在Authorization报头中提供哪种验证类型和域
- 常见MIME类型(Multipurpose Internet Mail Extension,多用因特网邮件扩展):
- 处理耗时较长的请求时,你需要
- 一种跨请求存储数据的方式:对于不专属任意客户的数据,可以将其存储在servlet的字段中;用户专属数据存储在HttpSession对象中;对于其他servlet和JSP页面需要用到的数据存储ServletContext中
- 一种在请求发送给用户之后,保持运算继续运行的方式:只需启动一个线程。系统为了应答请求而启动的线程,在响应完成之后自动结束,但其他的线程会保持运行。唯一细微差别是:要将线程的优先级别设为一个较低的值,这样不致于影响整个服务器的运行
- 一种在更新的结果就绪后,使浏览器得到它的方式:浏览器并不维护一个与服务器保持打开的连接,所以应该指示浏览器请求更新(Refresh的用途)
- 构建多媒体内容时,servlet必须执行的两个主要步骤:
- 通知浏览器内容类型:
response.setContentType("type/subtype");
- 以恰当的格式发送输出:一般使用getOutputStream方法获取原始的输出流(二进制数据)
OutputStream out = response.getOutputStream();
- 通知浏览器内容类型: