Servlet与JSP快速参考指南
1. 常见HTTP请求头
在HTTP请求中,有一些常见的请求头,它们各自有着不同的作用:
- Cookie :服务器之前发送给客户端的cookie,使用 getCookies 方法获取,而非 getHeader 。
- Host :原始URL中给出的主机名,这是HTTP 1.1中的必选头。
- If-Modified-Since :表示客户端仅在页面在指定日期之后有更改时才需要该页面,建议实现 getLastModified 方法来处理。
- Referer :引用网页的URL。
- User-Agent :标识发出请求的浏览器的字符串。
2. 标准CGI变量的访问
通常应从请求信息、响应信息和服务器信息的角度考虑,而非CGI变量。以下是一些相关的功能和对应的Servlet方法:
| CGI变量 | Servlet等效方法 |
| ---- | ---- |
| AUTH_TYPE | request.getAuthType() |
| CONTENT_LENGTH | request.getContentLength() |
| CONTENT_TYPE | request.getContentType() |
| DOCUMENT_ROOT | getServletContext().getRealPath(“/”) |
| HTTP_XXX_YYY | request.getHeader(“Xxx - Yyy”) |
| PATH_INFO | request.getPathInfo() |
| PATH_TRANSLATED | request.getPathTranslated() |
| QUERY_STRING | request.getQueryString() |
| REMOTE_ADDR | request.getRemoteAddr() |
| REMOTE_HOST | request.getRemoteHost() |
| REMOTE_USER | request.getRemoteUser() |
| REQUEST_METHOD | request.getMethod() |
| SCRIPT_NAME | request.getServletPath() |
| SERVER_NAME | request.getServerName() |
| SERVER_PORT | request.getServerPort() |
| SERVER_PROTOCOL | request.getProtocol() |
| SERVER_SOFTWARE | getServletContext().getServerInfo() |
3. HTTP状态码
3.1 HTTP响应格式
HTTP响应的格式依次为:状态行(HTTP版本、状态码、消息)、响应头、空行、文档。例如:
HTTP/1.1 200 OK
Content-Type: text/plain
Hello World
3.2 设置状态码的方法
在 HttpServletResponse 中有以下设置状态码的方法,需在向浏览器发送文档内容之前设置状态码:
- public void setStatus(int statusCode) :使用常量表示状态码,而非显式的整数。
- public void sendError(int code, String message) :将消息包装在一个小的HTML文档中。
- public void sendRedirect(String url) :在2.2版本中允许使用相对URL。
3.3 状态码分类
| 状态码范围 | 含义 |
|---|---|
| 100 - 199 | 信息性状态码,客户端应采取其他操作 |
| 200 - 299 | 请求成功 |
| 300 - 399 | 文件已移动,通常包含一个Location头指示新地址 |
| 400 - 499 | 客户端错误 |
| 500 - 599 | 服务器错误 |
3.4 常见HTTP 1.1状态码
- 200 (OK) :一切正常,文档随后返回,这是Servlet的默认状态码。
- 204 (No Content) :浏览器应继续显示上一个文档。
- 301 (Moved Permanently) :请求的文档已永久移动到其他位置(在Location头中指示),浏览器会自动转到新位置。
- 302 (Found) :请求的文档临时移动到其他位置(在Location头中指示),浏览器会自动转到新位置,Servlet设置此头时应使用
sendRedirect,而非setStatus。 - 401 (Unauthorized) :浏览器试图访问受密码保护的页面,但没有提供正确的Authorization头。
- 404 (Not Found) :没有该页面,Servlet应使用
sendError设置此头。
4. HTTP响应头
4.1 设置任意响应头
在 HttpServletResponse 中有以下设置响应头的方法,需在向浏览器发送文档内容之前设置:
- public void setHeader(String headerName, String headerValue) :设置任意头。
- public void setDateHeader(String headerName, long milliseconds) :将自1970年以来的毫秒数转换为GMT格式的日期字符串。
- public void setIntHeader(String headerName, int headerValue) :避免在调用 setHeader 之前将整数转换为字符串。
- addHeader 、 addDateHeader 、 addIntHeader :添加头的新实例,而非替换,仅在2.2版本中可用。
4.2 设置常见响应头
-
setContentType:设置Content-Type头,Servlet几乎总是使用此方法。 -
setContentLength:设置Content-Length头,用于持久HTTP连接,可使用ByteArrayOutputStream缓冲文档以确定大小。 -
addCookie:向Set-Cookie头添加值。 -
sendRedirect:设置Location头(并更改状态码)。
4.3 常见HTTP 1.1响应头
| 响应头 | 含义 |
|---|---|
| Allow | 服务器支持的请求方法,当Servlet收到OPTIONS请求时,默认的 service 方法会自动设置。 |
| Cache-Control | no-cache 值可防止浏览器缓存结果,同时发送相同值的 Pragma 头,以防浏览器仅支持HTTP 1.0。 |
| Content-Encoding | 文档的编码方式,浏览器在处理文档之前会反转此编码,Servlet在使用之前必须确认浏览器支持该编码。 |
| Content-Length | 响应中的字节数。 |
| Content-Type | 返回文档的MIME类型。 |
| Expires | 文档应被视为过期的时间,使用 setDateHeader 设置此头。 |
| Last-Modified | 文档最后更改的时间,建议提供 getLastModified 方法,而非显式设置此头。 |
| Location | 浏览器应重新连接的URL,建议使用 sendRedirect ,而非直接设置此头。 |
| Pragma | no-cache 值指示HTTP 1.0客户端不缓存文档。 |
| Refresh | 浏览器应重新加载页面的秒数,也可包含要连接的URL。 |
| Set-Cookie | 浏览器应记住的cookie,建议使用 addCookie ,而非直接设置此头。 |
| WWW-Authenticate | 客户端应在下一个请求的 Authorization 头中提供的授权类型和领域。 |
5. 从Servlet生成GIF图像
以下是从Servlet生成GIF图像的步骤:
1. 创建一个图像:使用 Component 的 createImage 方法。
2. 绘制图像:调用图像的 getGraphics 方法,然后进行正常的绘图操作。
3. 设置 Content-Type 响应头:使用 response.setContentType("image/gif") 。
4. 获取输出流:使用 response.getOutputStream() 。
5. 以GIF格式将图像发送到输出流:使用Jef Poskanzer的 GifEncoder ,可参考 http://www.acme.com/java/ 。
6. 处理Cookie
6.1 Cookie的典型用途
- 在电子商务会话中识别用户。
- 避免输入用户名和密码。
- 定制网站。
- 聚焦广告。
6.2 Cookie存在的问题
主要是隐私问题,而非安全问题。例如,服务器可以记住用户在以前会话中的操作,若用户提供个人信息,服务器可以将该信息与用户的先前操作关联起来,服务器还可以通过合作的第三方(如doubleclick.net)共享cookie信息,设计不佳的网站可能会直接在cookie中存储敏感信息(如信用卡号)。
6.3 Cookie的一般用法
- 发送cookie到浏览器(标准方法) :
Cookie c = new Cookie("name", "value");
c.setMaxAge(...);
// 设置其他属性
response.addCookie(c);
- 发送cookie到浏览器(简化方法) :使用
LongLivedCookie类。 - 从浏览器读取cookie(标准方法) :
Cookie[] cookies = response.getCookies();
for(int i = 0; i < cookies.length; i++) {
Cookie c = cookies[i];
if (c.getName().equals("someName")) {
doSomethingWith(c);
break;
}
}
- 从浏览器读取cookie(简化方法) :使用
ServletUtilities.getCookie或ServletUtilities.getCookieValue从cookie数组中提取cookie或cookie值。
6.4 Cookie方法
| 方法 | 描述 |
|---|---|
| getComment/setComment | 获取/设置注释,大多数浏览器支持的版本0的cookie不支持此方法。 |
| getDomain/setDomain | 指定cookie适用的域名,当前主机必须是指定域名的一部分。 |
| getMaxAge/setMaxAge | 获取/设置cookie的过期时间(以秒为单位),若未设置,cookie仅适用于当前浏览会话。 |
| getName/setName | 获取/设置cookie名称,新cookie通过构造函数提供名称,对于传入的cookie数组,使用 getName 查找感兴趣的cookie。 |
| getPath/setPath | 获取/设置cookie适用的路径,若未指定,cookie适用于包含当前页面的目录内或以下的URL。 |
| getSecure/setSecure | 获取/设置标志,指示cookie是否仅适用于SSL连接。 |
| getValue/setValue | 获取/设置与cookie关联的值,新cookie通过构造函数提供值,对于传入的cookie数组,使用 getName 查找感兴趣的cookie,然后调用 getValue 。 |
| getVersion/setVersion | 获取/设置cookie协议版本,默认版本为0,在浏览器开始支持版本1之前,建议使用版本0。 |
7. 会话跟踪
7.1 查找会话信息
HttpSession session = request.getSession(true);
ShoppingCart cart = (ShoppingCart)session.getValue("shoppingCart");
if (cart == null) { // 会话中没有购物车
cart = new ShoppingCart();
session.putValue("shoppingCart", cart);
}
doSomethingWith(cart);
7.2 将会话信息关联起来
HttpSession session = request.getSession(true);
session.putValue("referringPage", request.getHeader("Referer"));
ShoppingCart cart = (ShoppingCart)session.getValue("previousItems");
if (cart == null) { // 会话中没有购物车
cart = new ShoppingCart();
session.putValue("previousItems", cart);
}
String itemID = request.getParameter("itemID");
if (itemID != null) {
cart.addItem(Catalog.getItem(itemID));
}
7.3 HttpSession方法
| 方法 | 描述 |
|---|---|
| public Object getValue(String name) [2.1] public Object getAttribute(String name) [2.2] | 从会话对象中提取先前存储的值,若没有与给定名称关联的值,则返回null。 |
| public void putValue(String name, Object value) [2.1] public void setAttribute(String name, Object value) [2.2] | 将值与名称关联起来,若值实现了 HttpSessionBindingListener 接口,会调用其 valueBound 方法,若先前的值实现了该接口,会调用其 valueUnbound 方法。 |
| public void removeValue(String name) [2.1] public void removeAttribute(String name) [2.2] | 移除与指定名称关联的任何值,若要移除的值实现了 HttpSessionBindingListener 接口,会调用其 valueUnbound 方法。 |
| public String[] getValueNames() [2.1] public Enumeration getAttributeNames() [2.2] | 返回会话中所有属性的名称。 |
| public String getId() | 返回为每个会话生成的唯一标识符。 |
| public boolean isNew() | 若客户端(浏览器)从未见过该会话,则返回true,否则返回false。 |
| public long getCreationTime() | 返回会话首次创建的时间(自1970年以来的毫秒数),若要获取可用于打印的值,可将该值传递给 Date 构造函数或 GregorianCalendar 的 setTimeInMillis 方法。 |
| public long getLastAccessedTime() | 返回会话最后一次从客户端发送的时间。 |
| public int getMaxInactiveInterval() public void setMaxInactiveInterval(int seconds) | 获取/设置会话在自动失效之前应无访问的时间(以秒为单位),负值表示会话永不过期,与cookie过期日期不同。 |
| public void invalidate() | 使会话无效,并解除与它关联的所有对象的绑定。 |
8. JSP脚本元素
8.1 脚本元素类型
- 表达式 :
<%= expression %>,表达式会被求值并插入到Servlet的输出中,也可使用<jsp:expression> expression </jsp:expression>。 - 脚本段 :
<% code %>,脚本段会插入到Servlet的_jspService方法中(由service调用),也可使用<jsp:scriptlet> code </jsp:scriptlet>。 - 声明 :
<%! code %>,声明会插入到Servlet类的主体中,在任何现有方法之外,也可使用<jsp:declaration> code </jsp:declaration>。
8.2 模板文本
- 使用
<\%在输出中获取<%。 -
<%-- JSP注释 --%>是JSP注释。 -
<!-- HTML注释 -->是HTML注释。 - 所有其他非JSP特定的文本会直接传递到输出页面。
8.3 预定义变量
在表达式和脚本段(不包括声明)中自动可用的隐式对象:
| 变量 | 描述 |
| ---- | ---- |
| request | 与请求关联的 HttpServletRequest 。 |
| response | 与客户端响应关联的 HttpServletResponse 。 |
| out | 用于向客户端发送输出的 JspWriter ( PrintWriter 的子类)。 |
| session | 与请求关联的 HttpSession 对象。 |
| application | 通过 getServletConfig().getContext() 获得的 ServletContext ,由服务器或Web应用程序中的所有Servlet和JSP页面共享。 |
| config | 此页面的 ServletConfig 对象。 |
| pageContext | 与当前页面关联的 PageContext 对象。 |
| page | 等同于 this (当前Servlet实例),目前不太有用,为未来预留。 |
9. JSP页面指令:构建生成的Servlet
9.1 import属性
-
<%@ page import="package.class" %> -
<%@ page import="package.class1,...,package.classN" %>
9.2 contentType属性
-
<%@ page contentType="MIME-Type" %> -
<%@ page contentType="MIME-Type; charset=Character-Set" %>
该属性不能有条件地调用,若需要有条件地设置,可使用<% response.setContentType("..."); %>。
示例:使用 contentType
<%@ page contentType="application/vnd.ms-excel" %>
<%-- 注意列之间是制表符,而非空格 --%>
1997
1998
1999
2000
2001 (Anticipated)
12.3
13.4
14.5
15.6
16.7
9.3 isThreadSafe属性
-
<%@ page isThreadSafe="true" %>(默认) -
<%@ page isThreadSafe="false" %>
值为true表示代码是线程安全的,系统可以发送多个并发请求;值为false表示JSP文档生成的Servlet将实现SingleThreadModel。
非线程安全代码示例 :
<%! private int idNum = 0; %>
<% String userID = "userID" + idNum;
out.println("Your ID is " + userID + ".");
idNum = idNum + 1; %>
线程安全代码示例 :
<%! private int idNum = 0; %>
<% synchronized(this) {
String userID = "userID" + idNum;
out.println("Your ID is " + userID + ".");
idNum = idNum + 1;
} %>
9.4 其他属性
| 属性 | 描述 |
|---|---|
| session | <%@ page session="true" %> (默认), <%@ page session="false" %> 。 |
| buffer | <%@ page buffer="sizekb" %> , <%@ page buffer="none" %> ,服务器可以使用比指定更大的缓冲区,但不能更小。 |
| autoflush | <%@ page autoflush="true" %> (默认), <%@ page autoflush="false" %> ,当 buffer="none" 时, autoflush 不能为 false 。 |
| extends | <%@ page extends="package.class" %> 。 |
| info | <%@ page info="Some Message" %> 。 |
| errorPage | <%@ page errorPage="Relative URL" %> ,抛出的异常会通过 exception 变量自动提供给指定的错误页面。 |
| isErrorPage | <%@ page isErrorPage="true" %> , <%@ page isErrorPage="false" %> (默认)。 |
| language | <%@ page language="cobol" %> ,目前Java是默认且唯一合法的选择,无需关注此属性。 |
9.5 XML语法
- 通常语法:
<%@ page attribute="value" %>,<%@ page import="java.util.*" %>。 - XML等效语法:
<jsp:directive.page attribute="value" />,<jsp:directive.page import="java.util.*" />。
10. 在JSP文档中包含文件和小程序
10.1 在页面翻译时包含文件
-
<%@ include file="Relative URL" %>,更改包含的文件不一定会导致JSP文档重新翻译,需要手动更改JSP文档或更新其修改日期,例如:
<%-- Navbar.jsp modified 3/1/00 --%>
<%@ include file="Navbar.jsp" %>
10.2 在请求时包含文件
-
<jsp:include page="Relative URL" flush="true" />,Servlet可以使用RequestDispatcher的include方法实现类似结果,使用Java Web Server时,包含的文件必须使用.html或.htm扩展名。
10.3 Java插件的小程序(简单情况)
- 常规形式 :
<APPLET CODE="MyApplet.class" WIDTH=475 HEIGHT=350>
</APPLET>
- JSP形式(Java插件) :
<jsp:plugin type="applet"
code="MyApplet.class"
width="475" height="350">
</jsp:plugin>
10.4 jsp:plugin属性
| 属性 | 描述 |
|---|---|
| type | 对于小程序,此属性值应为 applet 。 |
| code | 与 APPLET 的 CODE 属性相同。 |
| width | 与 APPLET 的 WIDTH 属性相同。 |
| height | 与 APPLET 的 HEIGHT 属性相同。 |
| codebase | 与 APPLET 的 CODEBASE 属性相同。 |
| align | 与 APPLET 和 IMG 的 ALIGN 属性相同。 |
| hspace | 与 APPLET 的 HSPACE 属性相同。 |
| vspace | 与 APPLET 的 VSPACE 属性相同。 |
| archive | 与 APPLET 的 ARCHIVE 属性相同。 |
| name | 与 APPLET 的 NAME 属性相同。 |
| title | 与 APPLET (以及HTML 4.0中几乎所有其他HTML元素)罕见的 TITLE 属性相同,用于指定可用于工具提示或索引的标题。 |
| jreversion | 标识所需的Java运行时环境(JRE)版本,默认值为1.1。 |
| iepluginurl | 指定可从其下载Internet Explorer插件的URL。 |
| nspluginurl | 指定可从其下载Netscape插件的URL。 |
10.5 HTML中的参数:jsp:param
- 常规形式 :
<APPLET CODE="MyApplet.class" WIDTH=475 HEIGHT=350>
<PARAM NAME="PARAM1" VALUE="VALUE1">
<PARAM NAME="PARAM2" VALUE="VALUE2">
</APPLET>
- JSP形式(Java插件) :
<jsp:plugin type="applet"
code="MyApplet.class"
width="475" height="350">
<jsp:params>
<jsp:param name="PARAM1" value="VALUE1" />
<jsp:param name="PARAM2" value="VALUE2" />
</jsp:params>
</jsp:plugin>
10.6 替代文本
- 常规形式 :
<APPLET CODE="MyApplet.class" WIDTH=475 HEIGHT=350>
<B>Error: this example requires Java.</B>
</APPLET>
- JSP形式(Java插件) :
<jsp:plugin type="applet"
code="MyApplet.class"
width="475" height="350">
<!-- 替代文本 -->
</jsp:plugin>
Servlet与JSP快速参考指南
11. URL编码
为了确保在Servlet使用URL重写实现会话跟踪时,系统有机会对URL进行编码,需要对不同类型的URL进行处理:
- 常规URL :
String originalURL = someRelativeOrAbsoluteURL;
String encodedURL = response.encodeURL(originalURL);
out.println("<A HREF=\"" + encodedURL + "\">...</A>");
- 重定向URL :
String originalURL = someURL; // 2.2版本中相对URL也可行
String encodedURL = response.encodeRedirectURL(originalURL);
response.sendRedirect(encodedURL);
12. 总结与注意事项
在使用Servlet和JSP进行开发时,有许多关键的知识点和操作需要注意,以下通过表格形式进行总结:
| 类别 | 关键知识点 | 注意事项 |
| ---- | ---- | ---- |
| HTTP请求头 | Cookie、Host、If - Modified - Since、Referer、User - Agent等 | 使用正确的方法获取请求头信息,如使用 getCookies 获取Cookie |
| CGI变量访问 | 了解各CGI变量对应的Servlet等效方法 | 从请求、响应和服务器信息角度考虑,而非单纯依赖CGI变量 |
| HTTP状态码 | 不同状态码范围的含义及常见状态码 | 设置状态码要在发送文档内容之前,使用常量表示状态码 |
| HTTP响应头 | 设置任意和常见响应头的方法 | 同样要在发送文档内容之前设置响应头 |
| 生成GIF图像 | 创建、绘制图像,设置响应头,发送图像到输出流 | 使用指定的 GifEncoder 库 |
| 处理Cookie | 典型用途、存在问题及一般用法 | 注意隐私问题,使用合适的方法操作Cookie |
| 会话跟踪 | 查找和关联会话信息的方法 | 了解 HttpSession 的各种方法及使用场景 |
| JSP脚本元素 | 表达式、脚本段、声明的使用及预定义变量 | 注意不同脚本元素的插入位置和预定义变量的作用范围 |
| JSP页面指令 | 多个属性的使用及XML语法 | 注意各属性的功能和使用条件,如 contentType 不能有条件调用 |
| 包含文件和小程序 | 不同时机包含文件及小程序的使用 | 注意文件扩展名和 jsp:plugin 属性的设置 |
| URL编码 | 常规URL和重定向URL的编码 | 确保系统有机会对URL进行编码 |
13. 实际应用流程示例
以下是一个简单的Servlet和JSP开发的实际应用流程示例,使用mermaid流程图展示:
graph LR
A[接收HTTP请求] --> B[处理请求头信息]
B --> C{判断请求类型}
C -->|静态资源请求| D[返回静态资源]
C -->|动态资源请求| E[调用Servlet或JSP]
E --> F[处理业务逻辑]
F --> G[设置响应头和状态码]
G --> H[生成响应内容]
H --> I[发送响应到客户端]
14. 代码示例整合
为了更好地理解上述知识点的综合应用,以下是一个简单的JSP示例,展示了如何使用会话跟踪、设置响应头和包含文件:
<%@ page import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page session="true" %>
<%@ include file="header.jsp" %>
<%
HttpSession session = request.getSession(true);
String username = (String) session.getAttribute("username");
if (username == null) {
username = "Guest";
session.setAttribute("username", username);
}
%>
<!DOCTYPE html>
<html>
<head>
<title>Welcome Page</title>
</head>
<body>
<h1>Welcome, <%= username %>!</h1>
<p>You are now in our system.</p>
<jsp:include page="footer.jsp" flush="true" />
</body>
</html>
15. 常见错误及解决方法
在Servlet和JSP开发过程中,可能会遇到一些常见的错误,以下通过列表形式给出常见错误及解决方法:
- 状态码设置错误 :
- 错误表现 :页面显示异常,状态码不符合预期。
- 解决方法 :检查设置状态码的代码,确保在发送文档内容之前设置,使用常量表示状态码。
- Cookie操作问题 :
- 错误表现 :无法正确获取或设置Cookie。
- 解决方法 :检查Cookie的名称、值和属性设置,使用正确的方法操作Cookie,如 addCookie 、 getCookies 等。
- JSP页面指令使用错误 :
- 错误表现 :页面出现编译错误或显示异常。
- 解决方法 :检查各属性的使用条件,如 contentType 不能有条件调用, autoflush 在 buffer="none" 时不能为 false 。
- URL编码问题 :
- 错误表现 :会话跟踪失效,页面跳转异常。
- 解决方法 :确保对常规URL和重定向URL进行正确的编码,使用 response.encodeURL 和 response.encodeRedirectURL 。
16. 性能优化建议
为了提高Servlet和JSP应用的性能,可以考虑以下优化建议:
- 合理使用缓存 :通过设置 Cache - Control 和 Expires 响应头,合理控制页面和资源的缓存,减少服务器的负载。
- 优化会话管理 :设置合理的会话超时时间,避免长时间占用服务器资源,及时清理不再使用的会话信息。
- 减少文件包含 :尽量减少不必要的文件包含,避免在页面翻译时包含过多的文件,提高页面加载速度。
- 使用线程安全代码 :在多线程环境下,确保代码是线程安全的,避免出现数据不一致的问题。
17. 未来趋势与展望
随着Web技术的不断发展,Servlet和JSP仍然在企业级Web开发中占据重要地位。未来可能会朝着以下方向发展:
- 与新兴框架的融合 :与Spring、Spring Boot等框架进一步融合,提供更强大的功能和更便捷的开发体验。
- 性能和安全性的提升 :不断优化性能,加强安全性,以应对日益增长的Web应用需求。
- 支持更多的Web标准 :更好地支持HTML5、CSS3等Web标准,提供更好的用户体验。
通过对上述知识点的深入理解和实践,开发者可以更好地掌握Servlet和JSP技术,开发出高效、稳定的Web应用程序。希望本文能为大家在Servlet和JSP开发过程中提供有价值的参考。
超级会员免费看
3859

被折叠的 条评论
为什么被折叠?



