会话技术
Http:超文本传输协议,不可靠。
不保持连接的协议。无状态的。
什么是会话
会话是在一次会话中包含多次请求和响应
一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
会话的作用
由于Http是一个无状态协议,同一个会话的连续两个请求相互独立,彼此并不了解,不能共享数据!
用于存储浏览器与服务器在请求和响应过程中产生的数据
会话技术
Cookie
什么是Cookie
在一次会话的多次请求之间共享数据,将数据保存到客户端(浏览器)
浏览器历史记录:记录的是网址;
网易、孔夫子旧书网 、哔哩哔哩,输入自己的用户名 密码 ,记住密码;下一次直接可以弹出的方式,要么可以进入。
cookie 的原理
cookie-api详解
使用步骤
-
创建Cookie对象
Cookie cookie = new Cookie(String name, String value) //创建cookie对象
-
发送Cookie对象
response.addCookie(Cookie cookie) //响应给浏览器,可以发送多次
-
获取Cookie
Cookie[] request.getCookies() //获取服务器发送过来的所有的cookie cookie.getName() //获取cookie中的name cookie.getValue() //返回cookie的值 cookie.setValue() //修改cookie里面的值,把原来的值,替换成新的值
-
遍历数组
使用for循环遍历,获取每一个Cookie
代码实现
@WebServlet("/setServlet")
public class SetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.创建cookie对象,设置数据
Cookie cookie = new Cookie("name","jack");
// 2.通过response,响应(返回)cookie
response.addCookie(cookie);
}
}
@WebServlet("/getServlet")
public class GetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.通过request对象,接收cookie数组
Cookie[] cookies = request.getCookies();
// 2.遍历数组
if(cookies != null){
for(Cookie cookie : cookies){
if(cookie.getName().equals("name")){
String value = cookie.getValue();
response.getWriter().write(value);
}
}
}
}
}
案例-记录上一次访问时间
package cn.yanqi.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.text.SimpleDateFormat;
import java.util.Date;
/**
* @Auther: yanqi
* @Desc
*/
@WebServlet(urlPatterns = "/ServletCookie")
public class ServletCookie extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//获取所有的cookie
Cookie[] cookies = request.getCookies();
//除谷歌以外的浏览器
if(cookies == null){
//创建cookie
Cookie cookie = new Cookie("lastVisit",new Date().toLocaleString().replace(" ","-"));
//发送给浏览器
response.addCookie(cookie);
response.getWriter().write("您是第一次访问!!");
return;
}
//谷歌浏览器中会带有idea的cookie所以不为空,直接判断
for(Cookie cookie : cookies){
if(!"last".equals(cookie.getName())){
//创建cookie
cookie = new Cookie("last",new Date().toLocaleString().replace(" ","-"));
//发送给浏览器
response.addCookie(cookie);
response.getWriter().write("您是第一次访问!!");
}
if("last".equals(cookie.getName())){
//直接获取
String value = cookie.getValue();
response.getWriter().write("您上一次访问的时间是:"+value);
cookie.setValue(new Date().toLocaleString().replace(" ","-"));
response.addCookie(cookie);
}
}
}
}
cookie工具类代码
public class CookieUtils {
public static Cookie getCookies(Cookie[] cookie , String name){
//判断是不是null 如果是null 不用再走
if(cookie == null){
return null;
}
//不是null
for(Cookie c : cookie){
if(name.equals(c.getName())){
return c;
}
}
return null;
}
}
工具类测试
@WebServlet(urlPatterns = "/ServletTestCookieUtils")
public class ServletTestCookieUtils extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, IOException {
response.setContentType("text/html;charset=utf-8");
Date date = new Date();
//cookie的值不能出现 分号(;)、逗号(,)、等号(=)等特殊符号,否则会出现异常
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/ddHH:mm:ss");
String format1 = format.format(date);
System.out.println(format1);
//改进我们cookie,使cookieutils
Cookie[] cookies = request.getCookies();
//使用cookie工具来获取cookie对象
Cookie cookie = CookieUtils.getCookies(cookies, "last");
//如果是null表示第一次访问
if(cookie == null ){
// cookie = new Cookie("last",new Date().toLocaleString().replace(" ","-"));
cookie = new Cookie("last",format1);
response.addCookie(cookie);
response.getWriter().write("您是第一次访问!");
}else{
//否则就key匹配,直接取value
String value = cookie.getValue();
//重新设置值
// cookie = new Cookie("last",new Date().toLocaleString().replace(" ","-"));
cookie = new Cookie("last",format1);
response.addCookie(cookie);
response.getWriter().write("欢迎回来,上次访问的时间是:"+value);
}
}
}
cookie的生存时间
默认情况下,cookie存活在当前会话中,当浏览器关闭之后,会消失。那么如何让浏览器关闭之后仍然保存cookie
setMaxage();
设置cookie的过期时间。参数的单位是秒。cookie 将在经过该值表示的秒数后过期
@WebServlet(urlPatterns = "/ServletCookie")
public class ServletCookie extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//改进我们cookie,使cookieutils
Cookie[] cookies = request.getCookies();
//使用cookie工具来获取cookie对象
Cookie cookie = CookieUtils.getCookies(cookies, "last");
//如果是null表示第一次访问
if(cookie == null ){
cookie = new Cookie("last",new Date().toLocaleString().replace(" ","-"));
//设置cookie的生存时间,单位是秒
cookie.setMaxAge(60*60*2);//两个小时
response.addCookie(cookie);
response.getWriter().print("您是第一次访问!");
}else{
//否则就key匹配,直接取value
String value = cookie.getValue();
//重新设置值
cookie = new Cookie("last",new Date().toLocaleString().replace(" ","-"));
//设置cookie的生存时间,单位是秒
cookie.setMaxAge(60*60*2);//两个小时
response.addCookie(cookie);
response.getWriter().print("您上一次访问时间是:"+value);
}
}
}
删除cookie
cookie.setMaxAge();
参数:
如果参数是负数: 表示关闭浏览器之后cookie删除
如果参数是0 , 表示浏览器会马上删除cookie
cookie.setMaxAge(0); //浏览器会马上删除cookie
cookie.setMaxAge(-1); //关闭浏览器之后cookie删除
cookie访问有效路径
public void setPath(String url)
CookieWrite.jsp
<%
//创建cookie
Cookie cookie = new Cookie("abc","yanqi");
//设置cookie的有效访问路径,只能在/cookiepath下才能读出cookie
cookie.setPath("/cookiepath/");
//响应给浏览器
response.addCookie(cookie);
%>
CookieRead.jsp
<%
//定义变量
String cookieValue = null;
//获取所有的cookie
Cookie[] cookies = request.getCookies();
//判断
if(cookies != null && cookies.length>0){
//遍历cookie
for(Cookie cookie : cookies){
//判断cookie中的key和访问的key是否一致
if("abc".equals(cookie.getName())){
//如查相同就取出值
cookieValue = cookie.getValue();
}
}
}
if(cookieValue != null){
out.print(cookieValue);
}else{
out.print("没有找到cookie!");
}
%>
Cookie的特点和作用
Cooke的特点
1. cookie存储数据在客户端浏览器
2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(50个)
3. 浏览器可以存储cookie的总数量为300个
Cookie的作用
1. cookie一般用于存出少量的不太敏感的数据
2. 在不登录的情况下,完成服务器对客户端的身份识别
Cookie的缺陷
1.不太安全
2.Cookie的value是String类型的,一个Cookie只能存储一个数据,如果需要存储多个数据,就得创建N个Cookie
3.一个站点对Cookie是有限制
Cookie的存储的内容限制在4KB之内
一台服务器在一个客户端最多保存50个Cookie
一个浏览器最多可以存储300个Cookie
4.在设计上就有问题
Cookie是浏览器与服务器之间数据交互的凭证。如果客户端把Cookie给清除掉了,服务器就获取不到数据
一般来说,我们会把数据存储到服务器端即可
Session
什么是Session
在一次会话的多次请求之间共享数据,将数据保存到服务器端
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的每一个浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把用户各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
你怎么知道哪个session是属于哪个浏览器的呢?通过jsessionid来找的,jsessionid是以cookie的方式来保存的(其实就是cookie)
jsessionid:xxxxxxxxxxxxx具体的内容
Session的生命周期
-
Session何时创建
用户第一次调用request.getSession()方法时,session创建
如果第一次访问jsp页面也会创建一个session
-
何时销毁
服务器非正常关闭 非活跃状态30分钟后 tomcat进行配置 /tocmat安装目录/conf/web.xml 默认30分钟 大概590行 session.invalidate(); 手动销毁
web.xml中配置当前项目下的session过期时间
<!--设置当前项目的session过期时间,如果不配置默认是tomcat中的30分钟--> <session-config> <session-timeout>40</session-timeout> </session-config>
-
作用范围
一次会话中,多次请求之间
注意:每一个浏览器跟服务器都是独立的会话
session-api
request.getSession() | Session对象的获取 |
---|---|
session.setAttribute(String name,Object value) | session存入数据 |
session.getAttribute(String name) | session取出数据 |
session.removeAttribute(String name) | 删除session中数据 |
session.invalidate() | 手动销毁 |
案例-记住用户名
案例分析
代码实现
页面
<body>
<c:if test="${not empty sessionScope.username}" >
你当前用户是: <span style="color: red">${sessionScope.username}</span>
</c:if>
<form action="userServlet" method="post">
用户名:<input type="text" name="username" value="${sessionScope.username}"><br>
密码:<input type="text" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
代码
@WebServlet(urlPatterns = "/userServlet")
public class userServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
//模拟登录
if(username.equals(password)){
//登录成功把用户用写入session中
request.getSession().setAttribute("username",username);
//跳转到index.jsp
request.getRequestDispatcher("main.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
main.jsp
<body>
欢迎:<span style="color: red">${sessionScope.username}</span> 登录
<a href="cat.jsp" target="_blank">购物车</a>
<a href="play.jsp" target="_blank">支付</a>
</body>
cat.jsp
<body>
欢迎:<span style="color: red">${sessionScope.username}</span> 登录
<h1>购物车</h1>
</body>
play.jsp
<body>
欢迎:<span style="color: red">${sessionScope.username}</span> 登录
<h1>支付页面</h1>
</body>
退出登录
main.jsp
<body>
欢迎:<span style="color: red">${sessionScope.username}</span> 登录
<a href="outLoginServlet">退出登录</a>
<a href="cat.jsp" target="_blank">购物车</a>
<a href="play.jsp" target="_blank">支付</a>
</body>
servlet代码
@WebServlet(urlPatterns = "/outLoginServlet")
public class outLoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//request.getSession().invalidate();
request.getSession().removeAttribute("username");
request.getRequestDispatcher("login.jsp").forward(request,response);
}
}
Session的特点
1. session存储数据在服务器
2. session存储类型任意(Object)
3. session存储大小和数量没有限制(相对于内存)
4. session存储相对安全
Session与Cookie的区别
1. session存储数据在服务器端,Cookie在客户端
2. session没有数据大小限制,Cookie有
3. session数据安全,Cookie相对于不安全
Cookie和Session的选择
- cookie将数据保存在浏览器端,数据相对不安全.建议敏感的数据不要放在cookie中,而且数据大小是有限制的
- 成本低,对服务器要求不高
- session将数据保存在服务器端,数据相对安全.数据的大小要比cookie中数据灵活很多
- 成本较高,对服务器压力较大
实际应用中,浏览器不要禁止Cookie,如果禁止Cookie,那么服务器的应用将不能使用
面试题
当浏览器关闭后,Session对象是否销毁?
浏览器属于客户端。session保存在服务器端。
关闭浏览器对服务器没有任何的影响。Session对象仍然存在,只是找不 到原来的jsessionid了
cookie被禁用,session是否还可以被使用?
默认的情况,不能使用session,因为jsessionid找不到了
其实也可以通过url重写的方式,再找回来,继续使用(代码如下)
如果工作中,遇到用户把cookie禁止。session不能使用。告诉用户不能够禁止cookie。
URL重写
Session基于Cookie技术实现;浏览器的Cookie是可以禁用的,一旦禁用了之后,Session就会出现问题了。
开发中,一般我们是不关注用户的cookie是否禁用的,若用户禁用了cookie,只能别用网站了。若真想处理用户端的cookie禁用,我们可以使用url重写技术:
实现步骤:
1、setSession 存入session数据
2、getSession 获取session数据
3、用户禁用cookie,getSession获取不了数据
4、通过代码重写
5、即使禁用依然可以使用session,找到session数据
/**
* @Auther: yanqi
* @Desc 添加session数据
*/
@WebServlet(urlPatterns = "/setSession")
public class setSession extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取session对象
HttpSession session = request.getSession();
// 向session中存数据
session.setAttribute("username", "哈哈,即使浏览器禁用了cookie,也不影响我使用");
//浏览器禁用cookie,通过url重写的方式找回session
// 定义url
String url = "/getSession";
// 重写url,拼接JSESSIONID
url = response.encodeURL(url);
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<a href='" + url + "'>跳转到获取session内容</a>");
}
}
* @Auther: yanqi
* @Desc 获取session数据
*/
@WebServlet(urlPatterns = "/getSession")
public class getSession extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object username = request.getSession().getAttribute("username");
System.out.println("username:"+username);
}
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<a href='" + url + "'>跳转到获取session内容</a>");
}
}
```java
* @Auther: yanqi
* @Desc 获取session数据
*/
@WebServlet(urlPatterns = "/getSession")
public class getSession extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object username = request.getSession().getAttribute("username");
System.out.println("username:"+username);
}
}