Cookie
简介
Cookie是HTTP协议的规范之一,它是服务器和客户端之间传输的小数据。
首先由服务器通过响应头把Cookie传输给客户端,客户端会将Cookie保存起来。当客户端再次请求同一服务器时,客户端会在请求头中添加该服务器保存的Cookie,发送给服务器。
Cookie规范
Cookie通过请求头和响应头在服务器与客户端之间传输;Cookie大小限制在4KB之内;
一台服务器在一个客户端最多保存20个Cookie;
一个浏览器最多可以保存300个Cookie;
虽然Cookie规范是如此,但在今天,浏览器厂商的竞争异常激烈,所以多少会超出Cookie规则的限制。但也不会超出过多!
cookie的使用
我们有两种设置cookie的方法,1 通过响应头来设置cookie 2 通过response.addcookies() 方法便捷设置cookie。
让我们来看看使用代码:
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.addHeader("set-cookie","name=123");//通过设置响应头来设置cookie
response.addHeader("set-cookie", "password=123456");
Cookie c = new Cookie("aihao" , "nv");//我们先new一个cookie对象
Cookie d = new Cookie("xingqu" , "nv");
response.addCookie(c);//将我们new 的cookie对象添加上去
response.addCookie(d);
}
}
//服务器端获取cookie
public class BServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setHeader("Content-Type", "text/html;charset=utf-8");
PrintWriter pw =response.getWriter();
Cookie[] cs = request.getCookies();
for(Cookie e : cs) {
pw.write(e.getName() + "=" + e.getValue() + "<br/>");
}
pw.close();
}
}
cookie的其他方法
1 设置其最大存活时间 Cookie的maxAge
当服务器创建Cookie对象后,可以调用setMaxAge()方法设置Cookie的最大生命。
maxAge > 0:表示Cookie在客户端硬盘上保存的最大时间,单位为秒;
maxAge < 0:表示Cookie不会被浏览器保存到硬盘上,而只在浏览器内存中存活,一旦客户端关闭浏览器在,那么Cookie就消失;
maxAge == 0:表示删除Cookie,例如客户端硬盘已经存在名为abc的Cookie,如果服务器再向客户端发送名为abc,并且maxAge为0的Cookie,那么表示删除客户端上的名为abc的Cookie。
2 设置其path路径
注意其path路径并不是你想的那样哦,当你设置了cookie的path路径后,当你访问的url路径包含在cookie的path路径中是,浏览器就会发送该cookie给服务器对象。
如果没有设置path路径,那么它的path默认为当前Servlet的所在路径。
我们了看看他的使用代码:
j's'p<%@page import="java.net.URLEncoder"%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'jsp1.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<!-- 相当于java代码中的方法体内部 -->
<h1>添加cookie</h1>
<%
/* cookie不能保存中文所以使用中文是就必须得进行url编码 */
String name = URLEncoder.encode("魏金浩", "utf-8");
String value = URLEncoder.encode("呵呵哒", "utf-8");
Cookie c = new Cookie(name , value);
c.setMaxAge(-1);
c.setPath("/day_11/jsp/jsp1.jsp");/* 当我们这是了"/day_11/jsp1.jsp"path路径,我们在请求jsp2.jsp中浏览器就不会返回这个cookie了 */
response.addCookie(c);
%>
</body>
</html>
<%@page import="java.net.URLDecoder"%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'jsp2.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h1>得到COOKIE</h1>
<%
String d = null;
String e = null;
Cookie[] c = request.getCookies();
if(c != null) {
for(Cookie s : c) {
String name = URLDecoder.decode(s.getName(),"utf-8");/* 进行解码 */
if("魏金浩".equals(name)) {
d = name;
String value = URLDecoder.decode(s.getValue(),"utf-8");/* 进行解码 */
e = value;
}
}
}
%>
cookie: <%=d %>=<%=e %>
</body>
</html>
应为cookie是不允许传递中文的,这里面还涉及到了如何传递中文的方法,大家可以参考一下。
好了,cookie的内容咱们就说到这把,让我们在来研究一下session对象吧。
HttpSession
简介
HttpSession可和http协议无关了,这是我们的三大域对象之一(request,session,application),session域对象的域自然就是这个会话的过程了。我想这个不难理解吧。
也就是说服务器会为每个会话创建一个session对象,所以session中的数据可供当前会话中所有servlet共享。
常用方法
既然是域对象自然少不了这三个方法了:
session.setAttribute();
session.getAttribute();
session.removeAttribute();
这三个方法我们已近玩烂了,我就不细说了。
那摩我们如何得到session对象呢?
request.getSession();//得到session对象
好了,我们即能得到session了,也能设置属性了,他的大部分工作已经完成了,但是为了我们更好的使用session对象来实现数据的共享,我们有必要了解一下他的原理。
session原理
1.session是依赖Cookie实现的。
2.session是服务器端对象
3.当用户第一次使用session时(表示第一次请求服务器),服务器会创建session,并创建一个Cookie,在Cookie中保存了session的id,发送给客户端。这样客户端就有了自己session的id了。但这个Cookie只在浏览器内存中存在,也就是说,在关闭浏览器窗口后,Cookie就会丢失,也就丢失了sessionId。
4.当用户第二次访问服务器时,会在请求中把保存了sessionId的Cookie发送给服务器,服务器通过sessionId查找session对象,然后给使用。也就是说,只要浏览器容器不关闭,无论访问服务器多少次,使用的都是同一个session对象。这样也就可以让多个请求共享同一个session了。
5.当用户关闭了浏览器窗口后,再打开浏览器访问服务器,这时请求中没有了sessionId,那么服务器会创建一个session,再把sessionId通过Cookie保存到浏览器中,也是一个新的会话开始了。原来的session会因为长时间无法访问而失效。
6.当用户打开某个服务器页面长时间没动作时,这样session会超时失效,当用户再有活动时,服务器通过用户提供的sessionId已经找不到session对象了,那么服务器还是会创建一个新的session对象,再把新的sessionId保存到客户端。这也是一个新的会话开始了。
哦了,再多我也就不说了,要不然你们就嫌我啰嗦了,让我们来看一个应用吧!
演示登录功能:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'log.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<!-- 当浏览器禁用了cookie时我们可以使用url重写的方法达到同样的效果 -->
<!-- response.encodeURL("/day_11/LogServlet");当客户端禁用cookie时会自动生成带JSESSIONID参数的的url路径即:/day_11/LogServlet;JSESSIONID=********
当没有禁用是会返回原值 -->
<body>
<form action=<%=response.encodeURL("/day_11/LogServlet") %> method="post">
<h1 align="center">登陆</h1>
<table align="center">
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td><input type="submit" value="登陆"></td>
<td><input type="submit" value="注册"></td>
</tr>
</table>
</form>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'success.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<%
HttpSession s = request.getSession();
String username = (String)s.getAttribute("username");
if(username == null) {
response.sendRedirect(response.encodeURL("/day_11/LogServlet"));
}
%>
hello <%=username %>
</body>
</html>
package sessiontest;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LogServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
if("weijinhao".equals(username)) {
if("123456".equals(password)) {
HttpSession s = request.getSession();
s.setAttribute("username",username);
response.setStatus(302);
response.setHeader("location", response.encodeURL("/day_11/session/success.jsp"));
}
else {
response.setStatus(302);
response.setHeader("location", response.encodeURL("/day_11/session/log.jsp"));
}
}
else {
response.setStatus(302);
response.setHeader("location", response.encodeURL("/day_11/session/log.jsp"));
}
}
}
乍一看代码挺多但其实大部分都是不用看的,就看最主要的就行了,你懂的。
我估计大家会问我为什么提交表单和重定向是使用response.encodeURL();呢我们来讲解一下:
URL重写
session依赖Cookie,这是因为服务器需要把sessionId保存到客户端。如果用户的浏览器关闭了Cookie功能,那么session不能使用了!还可以在浏览器关闭了Cookie后使用URL重写的方法保存sessionId,这需要在每个URL后面都加上sessionId!这样用户的请求中就包含了sessionId,服务器就可以通过sessionId找到对应的session对象了。
使用response.encodeURL()方法对URL进行编码,这样URL中会智能的添加sessionId。
当浏览器支持cookie时,response.encodeURL()方法不会在URL后追加sessionId
当浏览器不支持cookie时,response.encodeURL()方法会在URL后追加sessionId
session的API:
String getId():获取sessionId;
nt getMaxInactiveInterval():获取session可以的最大不活动时间(秒),默认为30分钟。当session在30分钟内没有使用,那么Tomcat会在session池中移除这个session;
void setMaxInactiveInterval(int interval):设置session允许的最大不活动时间(秒),如果设置为1秒,那么只要session在1秒内不被使用,那么session就会被移除;
long getCreationTime():返回session的创建时间,返回值为当前时间的毫秒值;
long getLastAccessedTime():返回session的最后活动时间,返回值为当前时间的毫秒值;
void invalidate():让session失效!调用这个方法会被session失效,当session失效后,客户端再次请求,服务器会给客户端创建一个新的session,并在响应中给客户端新session的sessionId;
boolean isNew():查看session是否为新。当客户端第一次请求时,服务器为客户端创建session,但这时服务器还没有响应客户端,也就是还没有把sessionId响应给客户端时,这时session的状态为新。
最后还得说一下:
session与浏览器
session对象是保存在服务器端的,而sessionId是通过Cookie保存在客户端的。
因为Cookie不能在多个浏览器中共享,所以session也不能在多个浏览器中共享。也就是说,使用IE登录后,再使用FireFox访问服务器还是没有登录的状态。
而且同时打开多个相同浏览器的窗口,是在使用同一session。如果你使用的是老浏览器,例如IE6,那么就会每个窗口一个session。
哦了,我们就聊到这里,我要去睡觉了。