Servlet
5. Http状态码
5.1 HTTP 状态码列表
以下是可能从 Web 服务器返回的 HTTP 状态码和相关的信息列表:
代码 | 消息 | 描述 |
---|---|---|
100 | Continue | 只有请求的一部分已经被服务器接收,但只要它没有被拒绝,客户端应继续该请求。 |
101 | Switching Protocols | 服务器切换协议。 |
200 | OK | 请求成功。 |
201 | Created | 该请求是完整的,并创建一个新的资源。 |
202 | Accepted | 该请求被接受处理,但是该处理是不完整的。 |
204 | No Content | 无内容 |
206 | Partial Content | 局部请求 |
301 | Moved Permanently | 所请求的页面已经转移到一个新的 URL,永久重定向 |
302 | Found | 所请求的页面已经临时转移到一个新的 URL。 |
303 | See Other | 所请求的页面可以在另一个不同的 URL 下被找到。 |
307 | Temporary Redirect | 所请求的页面已经临时转移到一个新的 URL,临时重定向 |
400 | Bad Request | 服务器不理解请求。 |
401 | Unauthorized | 所请求的页面需要用户名和密码。 |
402 | Payment Required | 您还不能使用该代码。 |
403 | Forbidden | 禁止访问所请求的页面。 |
404 | Not Found | 服务器无法找到所请求的页面。. |
405 | Method NotAllowed | 在请求中指定的方法是不允许的。 |
408 | Request Timeout | 请求需要的时间比服务器能够等待的时间长,超时。 |
413 | Request Entity Too Large | 服务器不接受该请求,因为请求实体过大。 |
414 | Request-url Too Long | 服务器不接受该请求,因为 URL 太长。当您转换一个 “post” 请求为一个带有长的查询信息的 “get” 请求时发生。 |
500 | Internal Server Error | 未完成的请求。服务器遇到了一个意外的情况。 |
502 | Bad Gateway | 未完成的请求。服务器从上游服务器收到无效响应。 |
503 | Service Unavailable | 未完成的请求。服务器暂时超载或死机。 |
504 | Gateway Timeout | 网关超时。 |
505 | HTTP Version Not Supported | 服务器不支持"HTTP协议"版本。 |
5.2 设置 HTTP 状态代码的方法
下面的方法可用于在 Servlet 程序中设置 HTTP 状态码。这些方法通过 HttpServletResponse 对象可用。
方法 | 描述 |
---|---|
public void setStatus ( int statusCode ) | 该方法设置一个任意的状态码。setStatus 方法接受一个int(状态码)作为参数。如果您的反应包含了一个特殊的状态码和文档,请确保在使用 PrintWriter 实际返回任何内容之前调用 setStatus。 |
public void sendRedirect(String url) | 该方法生成一个 302 响应,连同一个带有新文档 URL 的Location 头。 |
public void sendError(int code, String message) | 该方法发送一个状态码(通常为 404),连同一个在 HTML 文档内部自动格式化并发送到客户端的短消息。 |
5.3 代码示例
核心方法1-返回404错误
// 导入必需的 java 库
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// 扩展 HttpServlet 类
public class HelloServlet extends HttpServlet {
// 处理 GET 方法请求的方法
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置错误代码和原因
response.sendError(404, "Not Found!!!" );
}
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
核心方法2-重定向
// 导入必需的 java 库
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// 扩展 HttpServlet 类
public class HelloServlet extends HttpServlet {
// 处理 GET 方法请求的方法
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置错误代码和原因
response.sendRedirect("https://www.baidu.com");
}
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
6. Servlet Cookies
6.1 cookie概念回顾
定义: Cookies 是存储在客户端计算机上的文本文件,并保留了用户的各种跟踪信息
作用: 会话保持,如完成用户的登录与状态保持
6.2 cookie工作原理
- 客户端向服务器发起登录请求
- 服务器脚本向浏览器发送一组 Cookies。例如:姓名、年龄或识别号码等。
- 浏览器将这些信息存储在本地计算机上,以备将来使用。
- 当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookies 信息发送到服务器,服务器将使用这些信息来识别用户。
6.3 cookie构成
Cookies 通常设置在 HTTP 头信息中。设置 Cookie 的http请求,会向 Servlet 会发送如下的头信息:
HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9
Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT; path=/; domain=bit.com
Connection: close
Content-Type: text/html
- Set-Cookie 头包含了一个名称值对、一个 GMT 日期、一个路径和一个域。名称和值会被 URL 编码。
- expires 字段是一个指令,告诉浏览器在给定的时间和日期之后过期(“忘记”)该 Cookie。
- 如果浏览器被配置为存储 Cookies,它将会保留此信息直到到期日期。
如果用户的浏览器指向任何匹配该 Cookie 的路径和域的页面,它会重新发送 Cookie 到服务器。浏览器的头信息可能如下所示:
GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc)
Host: zink.demon.co.uk:1126
Accept: image/gif, /
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Cookie: name=xyz
Servlet 就能够通过请求方法 request.getCookies() 访问 Cookie,该方法将返回一个 Cookie 对象的数组。
6.4 Servlet 操作cookie方法
以下是在 Servlet 中操作 Cookies 时可使用的有用的方法列表。
方法 | 描述 |
---|---|
public void setDomain(String pattern) | 该方法设置 cookie 适用的域,例如 w3cschool.cn。 |
public String getDomain() | 该方法获取 cookie 适用的域,例如 w3cschool.cn。 |
public void setMaxAge(int expiry) | 该方法设置 cookie 过期的时间(以秒为单位)。如果不这样设置,cookie 只会在当前 session 会话中持续有效。 |
public int getMaxAge() | 该方法返回 cookie 的最大生存周期(以秒为单位),默认情况下,-1 表示cookie 将持续下去,直到浏览器关闭。 |
public String getName() | 该方法返回 cookie 的名称。名称在创建后不能改变。 |
public void setValue(String newValue) | 该方法设置与 cookie 关联的值。 |
public String getValue() | 该方法获取与 cookie 关联的值。 |
public void setPath(String uri) | 该方法设置 cookie 适用的路径。如果您不指定路径,与当前页面相同目录下的(包括子目录下的)所有 URL 都会返回 cookie。 |
public String getPath() | 该方法获取 cookie 适用的路径。 |
6.5 代码示例
代码示例1-提交表单,设置cookie
index.html内容:
<!DOCTYPE html>
<html lang="en">
<head>
<!--设置编码格式-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>s
<form action="hello-servlet" method="GET">
名字:<input type="text" name="first_name">
<br />
姓氏:<input type="text" name="last_name" />
<input type="submit" value="提交" />
</form>
</body>
</html>
Servlet 代码// 导入必需的 java 库
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/cookie")
public class SetCookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 为名字和姓氏创建 Cookies
Cookie firstName = new Cookie("first_name",
request.getParameter("first_name"));
Cookie lastName = new Cookie("last_name",
request.getParameter("last_name"));
// 为两个 Cookies 设置过期日期为 24 小时后
firstName.setMaxAge(60*60*24);
lastName.setMaxAge(60*60*24);
// 在响应头中添加两个 Cookies
response.addCookie( firstName );
response.addCookie( lastName );
// 设置响应内容类型
response.setContentType("text/html");
// 设置响应的编码格式
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String title = "设置 Cookies 实例";
String docType = "<!doctype html public>\n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n" +
"<body bgcolor=\"#f0f0f0\">\n" +
"<h1 align=\"center\">" + title + "</h1>\n" +
"<ul>\n" +
" <li><b>名字</b>:"
+ request.getParameter("first_name") + "\n" +
" <li><b>姓氏</b>:"
+ request.getParameter("last_name") + "\n" +
"</ul>\n" +
"</body></html>");
}
@Override
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
查看结果
获取写入的cookie
代码:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/getCookie")
public class GetCookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = null;
Cookie[] cookies = null;
// 获取与该域相关的 Cookies 的数组
cookies = request.getCookies();
// 设置响应内容类型
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String title = "Reading Cookies Example";
String docType =
"<!doctype html>\n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n" +
"<body>\n" );
if( cookies != null ){
out.println("<h2>查找 Cookies 名称和值</h2>");
for (int i = 0; i < cookies.length; i++){
cookie = cookies[i];
out.print("名称:" + cookie.getName( ) + ",");
out.print("值:" + cookie.getValue( )+" <br/>");
}
}
out.println("</body>");
out.println("</html>");
}
@Override
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
7. Servlet Session
7.1 session概念回顾
- 定义: session 是存储在服务器上的文本文件,并保留了用户的各种跟踪信息
- 作用: 会话保持,如完成用户的登录与状态保持,因为在服务器端,所以相对安全一些
7.2 Servlet 操作session方法
HttpSession 对象
- Servlet 还提供了 HttpSession 接口,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式。
- Servlet 容器使用这个接口来创建一个 HTTP 客户端和 HTTP 服务器之间的 session 会话。会话持续一个指定的时间段,跨多个连接或页面请求。
- 我们可以通过调用 HttpServletRequest 的公共方法 getSession() 来获取 HttpSession 对象,如下所示:
HttpSession session = request.getSession();
需要在向客户端发送任何文档内容之前调用 request.getSession()
下面总结了 HttpSession 对象中可用的几个重要的方法:
方法 | 描述 |
---|---|
public Object getAttribute(String name) | 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null。 |
public Enumeration getAttributeNames() | 该方法返回 String 对象的枚举,String 对象包含所有绑定到该 session 会话的对象的名称。 |
public long getCreationTime() | 该方法返回该 session 会话被创建的时间,自格林尼治标准时间 1970 年1 月 1 日午夜算起,以毫秒为单位。 |
public String getId() | 该方法返回一个包含分配给该 session 会话的唯一标识符的字符串。 |
public long getLastAccessedTime() | 该方法返回客户端最后一次发送与该 session 会话相关的请求的时间自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。 |
public int getMaxInactiveInterval() | 该方法返回 Servlet 容器在客户端访问时保持 session 会话打开的最大时间间隔,以秒为单位。 |
public void invalidate() | 该方法指示该 session 会话无效,并解除绑定到它上面的任何对象。 |
public boolean isNew() | 如果客户端还不知道该 session 会话,或者如果客户选择不参入该session 会话,则该方法返回 true。 |
public void removeAttribute(String name) | 该方法将从该 session 会话移除指定名称的对象。 |
public void setAttribute(String name, Object value) | 该方法使用指定的名称绑定一个对象到该 session 会话。 |
public void setMaxInactiveInterval(int interval) | 该方法在 Servlet 容器指示该 session 会话无效之前,指定客户端请求之间的时间,以秒为单位。 |
7.3 代码示例
本实例说明了如何使用 HttpSession 对象获取 session 会话创建时间和最后访问时间。如果不存在 session 会话,我们将通过请求创建一个新的 session 会话
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
@WebServlet("/session")
public class SessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 如果不存在 session 会话,则创建一个 session 对象
HttpSession session = request.getSession(true);
// 获取 session 创建时间
Date createTime = new Date(session.getCreationTime());
// 获取该网页的最后一次访问时间
Date lastAccessTime = new Date(session.getLastAccessedTime());
String title = "欢迎回来";
String visitCountKey = new String("visitCount");
Integer visitCount = new Integer(0);
String userIDKey = new String("userID");
String userID = new String("abcd");
// 检查网页上是否是新的访问者
if(session.isNew()){
title = "欢迎来到我的网站";
session.setAttribute(userIDKey, userID);
}
else{
visitCount = (Integer) session.getAttribute(visitCountKey);
visitCount++;
userID = (String)session.getAttribute(userIDKey);
}
session.setAttribute(visitCountKey,visitCount);
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String docType = "<!doctype html>\n";
out.println(docType + "<html>\n" +
"<head><title>" +title+ "</title></head>\n" +
"<body>\n" +
"<h1>" + title + "</h1>\n"+
"<h2> Session 信息 </h2>" +
"<p>" +
"ID: " + session.getId() + "<hr/><br/>"+
"Create Time: " + createTime + "<hr/><br/>"+
"Time of Last Access: " + lastAccessTime + "<hr/><br/>"+"User ID: " + userID + "<hr/><br/>"+
"Number of visits: " + visitCount + "<hr/><br/>"+
"</p>"+ "</body>" +
"</html>");
}
@Override
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
Step 1:发起请求,查看结果
Step 2: 分析请求结果
得到响应时,服务器会自动向浏览器设置cookie,将session id设置进浏览器
Step 3: 多次刷新
每次请求,浏览器request都会自动携带session id,以供服务器器来进行标识。
7.4 session持久化
一般情况下,session是直接存储在指定服务器的内存中的,一般使用够了,但是在集群场景当中,可能需要通过session共享,来保证用户在不同的服务器上都可以得到认证。所以我们一般可以将用户的session信息统一保存在后端的数据库服务器中[比如,mysql/redis/memcache等],从而达到不同服务器间session的共享。
我们可以简单理解:将session保存在服务器数据库或者文件中的行为称之为session持久化
8. Servlet文件上传理解
HttpServletRequest 对文件上传的支持
- 此前,Servlet 本身没有对文件上传提供直接的支持,一般需要使用第三方框架来实现,实现起来很麻烦
- 不过,Servlet 3.0 之后提供了这个功能,而且使用也非常简单。为此,HttpServletRequest 提供了两个方法用于从请求中解析出上传的文件:
Part getPart(String name) //获取请求中给定 name 的文件
Collection getParts() //获取所有的文件
其中,每一个文件用一个 javax.servlet.http.Part
对象来表示。该接口提供了处理文件的简易方法,比如 write()、delete() 等。至此,结合 HttpServletRequest 和 Part 来保存上传的文件变得非常简单.
Part img = request.getPart(“img”);
img.write("/home/user/img.jpg");
另外,可以配合前面提到的 @MultipartConfig 注解来对上传操作进行一些自定义的配置,比如限制上传文件的大小,以及保存文件的路径等。其用法非常简单,故不在此赘述了。
需要注意的是,如果请求的 MIME 类型不是 multipart/form-data,则不能使用上面的两个方法,否则将抛异常。
前端网页
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>文件上传表单</title>
</head>
<body>
<h3>文件上传:</h3>
请选择要上传的文件:<br />
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" size="50" />
<br />
<input type="submit" value="上传文件" />
</form>
</body>
</html>
UploadServlet
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/upload")
@MultipartConfig
public class UpLoadServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException{
//具体上传上来的文件放在什么地方,由自己决定
File path = new File("/home/distance");
//获取文件,文件在html中的name是“file”
Part img = request.getPart("file");
//制作文件全路径
String filePath = path.getPath() + File.separator + img.getSubmittedFileName();
//获取成功之后,写入指定路径
img.write(filePath);
//显示到标准输出
System.out.println("file Upload: " + filePath);
//同样的信息,显示给用户浏览器
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("file Upload: " + filePath);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {//上传文件,不能用GET方法
System.out.println("上传文件只能用POST方法!");
}
}
结果演示:
-
获取上传页面
-
添加文件到浏览器
-
上传文件,成功
-
查看服务器端