JavaWeb(四)
2.4 JSP 指令
JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。
语法格式如下:
<%@ directive attribute="value" %>
指令可以有很多个属性,它们以键值对的形式存在,并用逗号隔开。
JSP中的三种指令标签:
| 指令 | 描述 |
|---|---|
| <%@ page ... %> | 定义网页依赖属性,比如脚本语言、error页面、缓存需求等等 |
| <%@ include ... %> | 包含其他文件 |
| <%@ taglib ... %> | 引入标签库的定义 |
2.4.1 Page指令
Page指令为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令。
<%@ page attribute="value" %>
等价的XML格式:
<jsp:directive.page attribute="value" />
属性
下表列出与Page指令相关的属性:
| 属性 | 描述 |
|---|---|
| buffer | 指定out对象使用缓冲区的大小 |
| autoFlush | 控制out对象的 缓存区 |
| contentType | 指定当前JSP页面的MIME类型和字符编码 |
| errorPage | 指定当JSP页面发生异常时需要转向的错误处理页面 |
| isErrorPage | 指定当前页面是否可以作为另一个JSP页面的错误处理页面 |
| extends | 指定servlet从哪一个类继承 |
| import | 导入要使用的Java类 |
| info | 定义JSP页面的描述信息 |
| isThreadSafe | 指定对JSP页面的访问是否为线程安全 |
| language | 定义JSP页面所用的脚本语言,默认是Java |
| session | 指定JSP页面是否使用session |
| isELIgnored | 指定是否执行EL表达式 |
| isScriptingEnabled | 确定脚本元素能否被使用 |
2.4.2 Include指令
JSP可以通过include指令来包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是该JSP文件的一部分,会被同时编译执行。
<%@ include file="文件相对 url 地址" %>
例如:
<%@ include file="common/Herder.jsp"%>
<h1>这是主体部分</h1>
<%@ include file="common/Footer.jsp"%>
include 指令中的文件名实际上是一个相对的 URL 地址。
如果您没有给文件关联一个路径,JSP编译器默认在当前路径下寻找。
2.4.3 Taglib指令
JSP API允许用户自定义标签,一个自定义标签库就是自定义标签的集合。
Taglib指令引入一个自定义标签集合的定义,包括库路径、自定义标签。
<%@ taglib uri="uri" prefix="prefixOfTag" %>
uri属性确定标签库的位置,prefix属性指定标签库的前缀。
等价的XML语法:
<jsp:directive.taglib uri="uri" prefix="prefixOfTag" />
2.5 JSP 客户端请求
当浏览器请求一个网页时,它会向网络服务器发送一系列不能被直接读取的信息,因为这些信息是作为HTTP信息头的一部分来传送的。您可以查阅HTTP协议来获得更多的信息。
下表列出了浏览器端信息头的一些重要内容,在以后的网络编程中将会经常见到这些信息:
| 信息 | 描述 |
|---|---|
| Accept | 指定浏览器或其他客户端可以处理的MIME类型。它的值通常为 image/png 或 image/jpeg |
| Accept-Charset | 指定浏览器要使用的字符集。比如 ISO-8859-1 |
| Accept-Encoding | 指定编码类型。它的值通常为 gzip 或compress |
| Accept-Language | 指定客户端首选语言,servlet会优先返回以当前语言构成的结果集,如果servlet支持这种语言的话。比如 en,en-us,ru等等 |
| Authorization | 在访问受密码保护的网页时识别不同的用户 |
| Connection | 表明客户端是否可以处理HTTP持久连接。持久连接允许客户端或浏览器在一个请求中获取多个文件。Keep-Alive 表示启用持久连接 |
| Content-Length | 仅适用于POST请求,表示 POST 数据的字节数 |
| Cookie | 返回先前发送给浏览器的cookies至服务器 |
| Host | 指出原始URL中的主机名和端口号 |
| If-Modified-Since | 表明只有当网页在指定的日期被修改后客户端才需要这个网页。 服务器发送304码给客户端,表示没有更新的资源 |
| If-Unmodified-Since | 与If-Modified-Since相反, 只有文档在指定日期后仍未被修改过,操作才会成功 |
| Referer | 标志着所引用页面的URL。比如,如果你在页面1,然后点了个链接至页面2,那么页面1的URL就会包含在浏览器请求页面2的信息头中 |
| User-Agent | 用来区分不同浏览器或客户端发送的请求,并对不同类型的浏览器返回不同的内容 |
HttpServletRequest类
request对象是javax.servlet.http.HttpServletRequest类的实例。每当客户端请求一个页面时,JSP引擎就会产生一个新的对象来代表这个请求。
request对象提供了一系列方法来获取HTTP信息头,包括表单数据,cookies,HTTP方法等等。
接下来将会介绍一些在JSP编程中常用的获取HTTP信息头的方法。详细内容请见下表:
| 序号 | 方法& 描述 |
|---|---|
| 1 | Cookie[] getCookies()返回客户端所有的Cookie的数组 |
| 2 | Enumeration getAttributeNames()返回request对象的所有属性名称的集合 |
| 3 | Enumeration getHeaderNames()返回所有HTTP头的名称集合 |
| 4 | Enumeration getParameterNames()返回请求中所有参数的集合 |
| 5 | HttpSession getSession()返回request对应的session对象,如果没有,则创建一个 |
| 6 | HttpSession getSession(boolean create)返回request对应的session对象,如果没有并且参数create为true,则返回一个新的session对象 |
| 7 | Locale getLocale()返回当前页的Locale对象,可以在response中设置 |
| 8 | Object getAttribute(String name)返回名称为name的属性值,如果不存在则返回null。 |
| 9 | ServletInputStream getInputStream()返回请求的输入流 |
| 10 | String getAuthType()返回认证方案的名称,用来保护servlet,比如 "BASIC" 或者 "SSL" 或 null 如果 JSP没设置保护措施 |
| 11 | String getCharacterEncoding()返回request的字符编码集名称 |
| 12 | String getContentType()返回request主体的MIME类型,若未知则返回null |
| 13 | String getContextPath()返回request URI中指明的上下文路径 |
| 14 | String getHeader(String name)返回name指定的信息头 |
| 15 | String getMethod()返回此request中的HTTP方法,比如 GET,,POST,或PUT |
| 16 | String getParameter(String name)返回此request中name指定的参数,若不存在则返回null |
| 17 | String getPathInfo()返回任何额外的与此request URL相关的路径 |
| 18 | String getProtocol()返回此request所使用的协议名和版本 |
| 19 | String getQueryString()返回此 request URL包含的查询字符串 |
| 20 | String getRemoteAddr()返回客户端的IP地址 |
| 21 | String getRemoteHost()返回客户端的完整名称 |
| 22 | String getRemoteUser()返回客户端通过登录认证的用户,若用户未认证则返回null |
| 23 | String getRequestURI()返回request的URI |
| 24 | String getRequestedSessionId()返回request指定的session ID |
| 25 | String getServletPath()返回所请求的servlet路径 |
| 26 | String[] getParameterValues(String name)返回指定名称的参数的所有值,若不存在则返回null |
| 27 | boolean isSecure()返回request是否使用了加密通道,比如HTTPS |
| 28 | int getContentLength()返回request主体所包含的字节数,若未知的返回-1 |
| 29 | int getIntHeader(String name)返回指定名称的request信息头的值 |
| 30 | int getServerPort()返回服务器端口号 |
HTTP信息头示例
在这个例子中,我们会使用HttpServletRequest类的getHeaderNames()方法来读取HTTP信息头。这个方法以枚举的形式返回当前HTTP请求的头信息。
<%@ page import="java.util.Enumeration" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>HTTP 头部请求实例</h2>
<table width="100%" border="1" align="center">
<tr bgcolor="#949494">
<th>Header Name</th><th>Header Value(s)</th>
</tr>
<%
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String paramName = (String)headerNames.nextElement();
out.print("<tr><td>" + paramName + "</td>\n");
String paramValue = request.getHeader(paramName);
out.println("<td> " + paramValue + "</td></tr>\n");
}
%>
</table>
</body>
</html>

2.6 JSP 服务器响应
Response响应对象主要将JSP容器处理后的结果传回到客户端。可以通过response变量设置HTTP的状态和向客户端发送数据,如Cookie、HTTP文件头信息等。
一个典型的响应看起来就像下面这样:
HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
(空行)
<!doctype ...>
<html>
<head>...</head>
<body>
...
</body>
</html>
状态行包含HTTP版本信息,比如HTTP/1.1,一个状态码,比如200,还有一个非常短的信息对应着状态码,比如OK。
下表摘要出了HTTP1.1响应头中最有用的部分,在网络编程中您将会经常见到它们:
| 响应头 | 描述 |
|---|---|
| Allow | 指定服务器支持的request方法(GET,POST等等) |
| Cache-Control | 指定响应文档能够被安全缓存的情况。通常取值为 public,private 或no-cache 等等。 Public意味着文档可缓存,Private意味着文档只为单用户服务并且只能使用私有缓存。No-cache 意味着文档不被缓存。 |
| Connection | 命令浏览器是否要使用持久的HTTP连接。close****值 命令浏览器不使用持久HTTP连接,而keep-alive 意味着使用持久化连接。 |
| Content-Disposition | 让浏览器要求用户将响应以给定的名称存储在磁盘中 |
| Content-Encoding | 指定传输时页面的编码规则 |
| Content-Language | 表述文档所使用的语言,比如en, en-us,,ru等等 |
| Content-Length | 表明响应的字节数。只有在浏览器使用持久化 (keep-alive) HTTP 连接时才有用 |
| Content-Type | 表明文档使用的MIME类型 |
| Expires | 指明啥时候过期并从缓存中移除 |
| Last-Modified | 指明文档最后修改时间。客户端可以 缓存文档并且在后续的请求中提供一个 If-Modified-Since请求头 |
| Location | 在300秒内,包含所有的有一个状态码的响应地址,浏览器会自动重连然后检索新文档 |
| Refresh | 指明浏览器每隔多久请求更新一次页面。 |
| Retry-After | 与503 (Service Unavailable)一起使用来告诉用户多久后请求将会得到响应 |
| Set-Cookie | 指明当前页面对应的cookie |
HttpServletResponse类
response 对象是 javax.servlet.http.HttpServletResponse 类的一个实例。就像服务器会创建request对象一样,它也会创建一个客户端响应。
response对象定义了处理创建HTTP信息头的接口。通过使用这个对象,开发者们可以添加新的cookie或时间戳,还有HTTP状态码等等。
下表列出了用来设置HTTP响应头的方法,这些方法由HttpServletResponse 类提供:
| S.N. | 方法 & 描述 |
|---|---|
| 1 | String encodeRedirectURL(String url)对sendRedirect()方法使用的URL进行编码 |
| 2 | String encodeURL(String url)将URL编码,回传包含Session ID的URL |
| 3 | boolean containsHeader(String name)返回指定的响应头是否存在 |
| 4 | boolean isCommitted()返回响应是否已经提交到客户端 |
| 5 | void addCookie(Cookie cookie)添加指定的cookie至响应中 |
| 6 | void addDateHeader(String name, long date)添加指定名称的响应头和日期值 |
| 7 | void addHeader(String name, String value)添加指定名称的响应头和值 |
| 8 | void addIntHeader(String name, int value)添加指定名称的响应头和int值 |
| 9 | void flushBuffer()将任何缓存中的内容写入客户端 |
| 10 | void reset()清除任何缓存中的任何数据,包括状态码和各种响应头 |
| 11 | void resetBuffer()清除基本的缓存数据,不包括响应头和状态码 |
| 12 | void sendError(int sc)使用指定的状态码向客户端发送一个出错响应,然后清除缓存 |
| 13 | void sendError(int sc, String msg)使用指定的状态码和消息向客户端发送一个出错响应 |
| 14 | void sendRedirect(String location)使用指定的URL向客户端发送一个临时的间接响应 |
| 15 | void setBufferSize(int size)设置响应体的缓存区大小 |
| 16 | void setCharacterEncoding(String charset)指定响应的编码集(MIME字符集),例如UTF-8 |
| 17 | void setContentLength(int len)指定HTTP servlets中响应的内容的长度,此方法用来设置 HTTP Content-Length 信息头 |
| 18 | void setContentType(String type)设置响应的内容的类型,如果响应还未被提交的话 |
| 19 | void setDateHeader(String name, long date)使用指定名称和日期设置响应头的名称和日期 |
| 20 | void setHeader(String name, String value)使用指定名称和值设置响应头的名称和内容 |
| 21 | void setIntHeader(String name, int value)指定 int 类型的值到 name 标头 |
| 22 | void setLocale(Locale loc)设置响应的语言环境,如果响应尚未被提交的话 |
| 23 | void setStatus(int sc)设置响应的状态码 |
HTTP响应头程序示例
接下来的例子使用setIntHeader()方法和setRefreshHeader()方法来模拟一个数字时钟:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.io.*,java.util.*" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>自动刷新实例</h2>
<%
// 设置每隔5秒自动刷新
response.setIntHeader("Refresh", 5);
// 获取当前时间
Calendar calendar = new GregorianCalendar();
String am_pm;
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
if(calendar.get(Calendar.AM_PM) == 0)
am_pm = "AM";
else
am_pm = "PM";
String CT = hour+":"+ minute +":"+ second +" "+ am_pm;
out.println("当前时间: " + CT + "\n");
%>
</body>
</html>

2.7 JSP HTTP 状态码
HTTP请求与HTTP响应的格式相近,都有着如下结构:
- 以状态行+CRLF(回车换行)开始
- 零行或多行头模块+CRLF
- 一个空行,比如CRLF
- 可选的消息体比如文件,查询数据,查询输出
举例来说,一个服务器响应头看起来就像下面这样:
HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
(Blank Line)
<!doctype ...>
<html>
<head>...</head>
<body>
...
</body>
</html>
状态行包含HTTP版本,一个状态码,和状态码相对应的短消息。
下表列出了可能会从服务器返回的HTTP状态码和与之关联的消息:
| 状态码 | 消息 | 描述 |
|---|---|---|
| 100 | Continue | 只有一部分请求被服务器接收,但只要没被服务器拒绝,客户端就会延续这个请求 |
| 101 | Switching Protocols | 服务器交换机协议 |
| 200 | OK | 请求被确认 |
| 201 | Created | 请求时完整的,新的资源被创建 |
| 202 | Accepted | 请求被接受,但未处理完 |
| 203 | Non-authoritative Information | |
| 204 | No Content | |
| 205 | Reset Content | |
| 206 | Partial Content | |
| 300 | Multiple Choices | 一个超链接表,用户可以选择一个超链接并访问,最大支持5个超链接 |
| 301 | Moved Permanently | 被请求的页面已经移动到了新的URL下 |
| 302 | Found | 被请求的页面暂时性地移动到了新的URL下 |
| 303 | See Other | 被请求的页面可以在一个不同的URL下找到 |
| 304 | Not Modified | |
| 305 | Use Proxy | |
| 306 | Unused | 已经不再使用此状态码,但状态码被保留 |
| 307 | Temporary Redirect | 被请求的页面暂时性地移动到了新的URL下 |
| 400 | Bad Request | 服务器无法识别请求 |
| 401 | Unauthorized | 被请求的页面需要用户名和密码 |
| 402 | Payment Required | 目前还不能使用此状态码 |
| 403 | Forbidden | 禁止访问所请求的页面 |
| 404 | Not Found | 服务器无法找到所请求的页面 |
| 405 | Method Not Allowed | 请求中所指定的方法不被允许 |
| 406 | Not Acceptable | 服务器只能创建一个客户端无法接受的响应 |
| 407 | Proxy Authentication Required | 在请求被服务前必须认证一个代理服务器 |
| 408 | Request Timeout | 请求时间超过了服务器所能等待的时间,连接被断开 |
| 409 | Conflict | 请求有矛盾的地方 |
| 410 | Gone | 被请求的页面不再可用 |
| 411 | Length Required | "Content-Length"没有被定义,服务器拒绝接受请求 |
| 412 | Precondition Failed | 请求的前提条件被服务器评估为false |
| 413 | Request Entity Too Large | 因为请求的实体太大,服务器拒绝接受请求 |
| 414 | Request-url Too Long | 服务器拒绝接受请求,因为URL太长。多出现在把"POST"请求转换为"GET"请求时所附带的大量查询信息 |
| 415 | Unsupported Media Type | 服务器拒绝接受请求,因为媒体类型不被支持 |
| 417 | Expectation Failed | |
| 500 | Internal Server Error | 请求不完整,服务器遇见了出乎意料的状况 |
| 501 | Not Implemented | 请求不完整,服务器不提供所需要的功能 |
| 502 | Bad Gateway | 请求不完整,服务器从上游服务器接受了一个无效的响应 |
| 503 | Service Unavailable | 请求不完整,服务器暂时重启或关闭 |
| 504 | Gateway Timeout | 网关超时 |
| 505 | HTTP Version Not Supported | 服务器不支持所指定的HTTP版本 |
设置HTTP状态码的方法
下表列出了HttpServletResponse 类中用来设置状态码的方法:
| S.N. | 方法 & 描述 |
|---|---|
| 1 | public void setStatus ( int statusCode )此方法可以设置任意的状态码。如果您的响应包含一个特殊的状态码和一个文档,请确保在用PrintWriter返回任何内容前调用setStatus方法 |
| 2 | public void sendRedirect(String url)此方法产生302响应,同时产生一个 Location 头告诉URL 一个新的文档 |
| 3 | public void sendError(int code, String message)此方法将一个状态码(通常为 404)和一个短消息,自动插入HTML文档中并发回给客户端 |
HTTP状态码程序示例
接下来的例子将会发送407错误码给浏览器,然后浏览器将会告诉您"Need authentication!!!"。
<html>
<head>
<title>Setting HTTP Status Code</title>
</head>
<body>
<%
// 设置错误代码,并说明原因
response.sendError(407, "Need authentication!!!" );
%>
</body>
</html>

浙公网安备 33010602011771号