-
什么叫做会话技术?
答:服务器与浏览器之间进行一问一答的行为。 -
为什么要会话技术?
答:因为HTTP协议其实是一个无状态的协议。对于服务器来说,服务器是无法区别每个HTTP请求时来自于同一个客户端,还是来自于不同的客户端,因为HTTP请求报文全部长得都是一个样,报文里面并没有任何可以表明客户端身份的一个信息。简单来说,服务器不能区分客户端。
但是,我们有这样的需求:希望服务器能够帮我们客户端去存储一些数据。
所有,引入专门的会话技术来解决整个问题。 -
会话技术有哪些?
Cookie 和 Session
Cookie
一、什么是cookie
Cookie是一小串数据。数据是由服务器生成的,然后在响应的过程中传给客户端(以set-Cookie响应头的形式发送给客户端),客户端及时保存下来,等到下次访问服务器的时候(以Cookie请求头的形式发回给服务端),就会把这个cookie给携带上。服务器通过解析请求报文就知道谁在访问。
通过键值对的形式可以定义一个Cookie
Cookie是一个实体类,构造方法:
Cookie(java.lang.String name, java.lang.String value)
二、Cookie的应用案例
案例一:显示用户上次访问时间
@WebServlet("/last")
public class LastLoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// cookie的值必须是字符串,并且里面不能有空格
//获取cookie请求头 cookie:key=value;key=value
//也就是对于获取cookie请求头的封装
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
if("lastLogin".equals(cookie.getName())){
String value = cookie.getValue();
long time = Long.parseLong(value);
Date date = new Date(time);
response.getWriter().println(date);
}
}
}
Cookie cookie = new Cookie("lastLogin", System.currentTimeMillis() + "");
//这行代码其实就是对于设置Set-Cookie:key=value的封装
response.addCookie(cookie);
}
}
案例二:登陆成功之后跳转到一个个人主页
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
//不做任何校验,只要输入就当作登录成功
Cookie cookie = new Cookie("username", username);
response.addCookie(cookie);
response.getWriter().println("登录成功,即将跳转至个人主页....");
response.setHeader("refresh", "2;url=" + request.getContextPath() + "/info");
//Context域不可以
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
@WebServlet("/info")
public class InfoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//
String username = "";
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
if("username".equals(cookie.getName())){
username = cookie.getValue();
}
}
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Title</title>\n" +
"</head>\n" +
"<body>");
response.getWriter().println("欢迎您," + username);
response.getWriter().println("</body>\n" +
"</html>");
}
}
三、Cookie的设置
- 设置存活时间
cookie.setMaxAge(180);
默认情况下,参数为负数,当参数为负数的时候,cookie仅在浏览器内存中保存,浏览器关闭则cookie失效。
如果希望cookie能够进行持久化保存,需要设置一个正数的存活时间,单位是秒。
如果参数设为0,则立即删除该cookie。
- 设置路径
cookie.setPath(request.getContextPath() + "/info");
设置path的意义:比如设置某些情况下不需要带cookie,比如请求一个静态资源文件,js、css文件。
默认情况下,如果没有设置path的话,则当访问当前域名下任意资源时,均会带上该cookie,如果想仅部分路径携带cookie,则可以通过设置path来实现。
注意:如果cookie中设置了path,直接设置MaxAge=0不能立即删除cookie。此时需要把设置path的代码再写一遍
cookie.setMaxAge(0);
cookie.setPath(request.getContextPath() + "/info");
response.addCookie(cookie);
- 设置域名
cookie.setDomain("octavius.com");
如果没有设置,则cookie默认在当前域名下有效,如果超出当前域名,则失效。
你不可以设置一个和当前域名无关的cookie信息
子域名均可以"继承"得到父域名的cookie
四、细节补充
- cookie的name和value值均是字符串类型
- cookie它只能存储少量的数据,一般不超过4k
- 不同浏览器之间不可以共享cookie
Session
一、什么是Session?
服务器技术。客户端访问服务器上的资源时,服务器会给浏览器开辟一块内存空间,不同的内存空间和对应的浏览器一一绑定,后续如果浏览器想存储数据,直接在对应的内存空间种存储即可。
二、session如何和浏览器关联在一起?
实际上Session底层实现依赖于cookie。
浏览器访问服务器时,服务器会再特定的条件下生成一个session对象,该对象有一个唯一的id,接下来当响应时,会把该session的id 通过cookie返回给当前客户端,客户端接收到该cookie数据之后,随机保存下来;
当下次再次访问服务器其他站点时,会把该cookie重新携带回来,此时服务器可以取出session的id,通过session的id就可以拿到对应的session对象。将当前浏览器和当前session对象关联在一起了。
三、Session的创建
request.getSession();
request.getSession(boolean create)
区别:
那么,如何判断当前request是否有session对象的呢?
判断当前请求种是否含有一个有效的cookie: JSESSIONID=xxxxxxxxxxxxx
,如果有的话,则根据这个id找到对应的session对象;如果没有的话,或者说是一个无效的id,那么这个时候给它创建一个新的session对象。
四、Session发挥功能——Session域
通过下列api对Session中的数据进行操作
session.setAttribute();
session.getAttribute();
session.removeAttribute();
context域、request域、session域的区别:
- context域:当前应用内只有一个。不同的servlet之间也可以进行共享数据。
- request域:仅仅在一次请求内有效。
- session域:当前应用内有多少个浏览器,就有多少个session。范围也比较广。不同的servlet之间也可以进行共享数据。
在实际应用中:
- session域可以用来存储和用户相关的数据,比如用户的用户名、用户的信息、购物车等
- context可以用来存储和用户无关的数据,比如当前商城的商品分类,数码、服装、食品
五、Session的销毁
-
关闭浏览器session对象会不会销毁?
不会。此时session对象类似于一种不可达的状态:当关闭浏览器后再用该浏览器访问,服务器会给该浏览器一个新的JSESSIONID。
但如果一段时间不用,就会被销毁。 -
关闭服务器session对象会不会销毁?
会。关闭服务器或者卸载应用都会销毁session对象。
但是,session里面的数据不会丢失, session的id以及域里面存储的数据序列化到了本地硬盘上面。
注意:不要通过关闭idea的tomcat再启动来验证这个过程。因为idea的tomcat每次启动前都会将配置文件删除,重新赋值新的tomcat配置文件过来,所以看不到该现象。
如果想持久化保存,则需要设置maxAge:
@WebServlet("/session")
public class ServletSession extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
//cookie的name必须为JSESSIONID
//你创建的这个cookie和浏览器内部的cookie是两个cookie,只不过当你关闭浏览器的时候
//浏览器内部的cookie就失效了,而你创建的cookie存活了下来
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60 * 60);
response.addCookie(cookie);
session.setAttribute("name", "session");
//获取JSESSIONID
String id = session.getId();
System.out.println(id);
}
}
- 如何主动销毁Session中的数据
①有效期到达,session里面的数据会丢失(30min)
②主动调用session.invalidate(),将整个session对象失效
③session.removeAttribute,仅仅是将一个属性给移除