会话技术
- 客户端会话技术(Cookie)
- 服务器端会话技术(Session)
一、客户端会话技术(Cookie)
1.1、说明
Cookie,英文翻译为小甜点的意思,实际上是服务器发送给客户端的“小型文本文件”。其最初诞生的目的就是为了规避HTTP协议的无状态特性,毕竟服务器端的业务必须是有状态的。
Cookie的使用流程:服务器构造Cookie然后发送给客户端浏览器,浏览器将Cookie保存(内存/硬盘),最后浏览器的每次HTTP请求都会将Cookie发送给服务器。
Cookie作为小甜点,大小和数量都是有限制的。一般都是限制为20个,每个限制4KB。
1.2、原理
1.3、Cookie的常用方法
-
创建Cookie对象
Cookie cookie = new Cookie(String name,String value);//Cookie类只有这一个构造方法
-
获取当前Cookie的名称。
String getName();//Cookie的key不可更改
-
获取当前Cookie的值。
String getValue();
-
获取当前Cookie的最大保存时间
int getMaxAge();
-
修改Cookie的值
void setValue();
-
设置Cookie数据在客户端的保存时间
void setMaxAge(int seconds); //正数:将Cookie数据写入到客户端硬盘中,保存时间为seconds秒。 //负数:将Cookie数据存储在客户端内存中,随着浏览器的关闭而被销毁。(默认值) //零:删除Cookie信息。
-
设置Cookie数据的共享范围
void setPath(String URL); //URL:该Cookie的共享范围,默认值为当前项目的虚拟目录,比如:/project3 //如果将URL设置为"/",则表示当前服务器下部署的所有项目都共享该Cookie
Cookie和Servlet互动的方法:
1)、将Cookie对象添加到响应头中:void response.addCookie(Cookie cookie);
2)、获取请求中包含的Cookie数据:Cookie[] request.getCookies();
1.4、使用细节
-
关于Cookie的生命周期
Cookie数据默认是存储在客户端内存中的,如果需要持久化保存可以通过
setMaxAge(String seconds)
方法设置。 -
Cookie存储中文问题
在Tomcat8.0之前Cookie是不能直接存储中文数据的,直接报错。
-
关于Cookie的共享问题
Cookie默认是只能当前项目可见的,但是可以通过setPath(String URL)
方法设置其共享域。
1.5、案例
@WebServlet("/demo")
public class Demo extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
resp.setContentType("text/html;charset=utf-8");
boolean flag = true;
Cookie[] cookies = req.getCookies();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日-HH:mm:ss");//
String time = sdf.format(date);//获取当前时间字符串
time = URLEncoder.encode(time,"utf-8");//Cookie中不允许存放空格,所以要编码
if(cookies!=null){
for (Cookie cookie:cookies) {
if ("lastTime".equals(cookie.getName())){//曾经访问过
String oldTime = cookie.getValue();
oldTime = URLDecoder.decode(oldTime,"utf-8");
resp.getWriter().write("上一次访问时间为:"+oldTime);
cookie.setValue(time);//更新Cookie
cookie.setMaxAge(60*60*24*7);//cookie保质期为7天
resp.addCookie(cookie);
flag = false;
break;//结束循环
}
}
}
if (flag){//第一次访问该Servlet
Cookie cookie = new Cookie("lastTime",time);
cookie.setMaxAge(60*60*24*7);//cookie保质期为7天
resp.addCookie(cookie);
resp.getWriter().write("欢迎首次访问!");
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
this.doPost(req, resp);
}
}
二、服务器端会话(Session)
2.1、说明
Session,英文翻译为主菜,将一些不大且重要的数据临时存储在服务器内存中,用于多次请求之间的数据交互。(由于Session数据是存储在服务器端的,相比较cookie而言要安全很多)
2.2、原理
Session的实现是依赖于Cookie的!
2.3、HttpSession接口的常用方法
Session于Servlet互动的方法:
1)、获取当前会话的Session对象:HttpSession session = request.getSession();
2.4、使用细节
-
当客户端重启、服务器不重启时,两次获取的Session是否为同一个?
答:默认情况下不是。需要是同一个Session时,可以手动覆盖cookies(“JSESSIONID”,"??")并修改存活时间。
Session session = request.getSeesion(); Cookie cookie = new Cookie("JSESSIONID",session.getId()); cookie.setMaxAge(60*60);//1个小时有效期 response.addCookie(cookie);
-
session的钝化和锐化(由Tomcat后台执行,session对象文件存储在work文件夹中)
钝化:在服务器关闭之前,将session对象系列化到硬盘
活化:在服务器启动之后,将session文件转化为内存中的session对象。
-
session的失效时间。
session对象的默认失效时间为30分钟,也可以调用session对象的
invalidate()
方法提前释放session对象。<!--方法二:配置web.xml--> <session-config> <session-timeout>30</session-timeout><!--配置session失效时间--> </session-config>
2.5、经典案例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
<style>
.message{/*登陆失败时的提示信息*/
color: red;
}
</style>
</head>
<script>
window.onload=function (ev) {
document.getElementById("checkImg").onclick=function (ev1) {
this.src="/project3/printPhoto?time="+new Date().getTime();
}
};
</script>
<body>
<form action="/project3/login">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>用户名:</td>
<td><input type="text" name="userName" id="userName" placeholder="请输入用户名"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="passwd" id="passwd" placeholder="请输入密码"></td>
</tr>
<tr>
<td>验证码:</td>
<td><input type="text" name="checkCode" id="checkCode" placeholder="请输入验证码"></td>
</tr>
<tr>
<td colspan="2"><img src="/project3/printPhoto" alt="图片失效" id="checkImg"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
<div class="message"><%=request.getAttribute("loginResult")==null?"":request.getAttribute("loginResult")%></div>
<div class="message"><%=request.getAttribute("checkResult")==null?"":request.getAttribute("checkResult")%></div>
</body>
</html>
@WebServlet("/login")
public class Login extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
//1、设置编码
req.setCharacterEncoding("utf-8");
//2、获取用户输入的参数
String userName = req.getParameter("userName");
String passwd = req.getParameter("passwd");
String checkCode = req.getParameter("checkCode");
//3、获取验证码的值
HttpSession session = req.getSession();
String checkText = (String)session.getAttribute("checkText");
//4、删除验证码
session.removeAttribute("checkText");
//5、校验验证码
if(checkText!=null && checkText.equalsIgnoreCase(checkCode)){//忽略大小写比较验证码
//验证码一致
//6、用户名和密码验证
if ("张三".equals(userName) && "123456".equals(passwd)){
//登录成功
session.setAttribute("user",userName);
resp.sendRedirect(req.getContextPath()+"/jsp/main.jsp");//重定向——>>主页
}else{
//登录失败
req.setAttribute("loginResult","用户名或密码错误");
req.getRequestDispatcher("/jsp/login.jsp").forward(req,resp);//请求转发
}
}else{
//验证码不一致
req.setAttribute("checkResult","验证码不一致");
req.getRequestDispatcher("/jsp/login.jsp").forward(req,resp);//请求转发
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
req.getRequestDispatcher("/jsp/login.jsp").forward(req,resp);//请求转发
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}