会话:一次会话中包含多次请求和响应。
一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
功能:在一次会话的范围内的多次请求间,共享数据
方式:
1.客户端会话技术:Cookie
2.服务器端会话技术: session-
Cookie:
概念∶客户端会话技术,将数据保存到客户端
使用步骤︰
1.创建cookie对象,绑定数据
new Cookie(string name, string value)
2.发送cookie对象
response.addcookie(cookie cookie)
3.获取cookie,拿到数据
cookier[] request.getcookies()
实现原理
基于响应头set-cookie和请求头cookie实现-
cookie的细节:
一次可不可以发送多个cookie?
可以创建多个cookie对象,使用response调用多次addcookie方法发送cookie即可。-
cookie在浏览器中保存多长时间?
1.默认情况下,当浏览器关闭后,cookie数据被销毁
2.持久化存储:setMaxAge(int seconds)
1.正数∶将cookie数据写到硬盘的文件中。持久化存储。cookie存活时间。
2.负数︰默认值
3.零:删除cookie信息 cookie能不能存中文?
在tomcat 8 之前cookie中不能直接存储中文数据。【需要将中文数据转码---—般采用URL编码(%E3)】
在tomcat 8 之后,cookie支持中文数据。cookie共享问题?
1.假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
*默认情况下cookie不能共享
setPath(string path):
设置cookie的获取范围。默认情况下,设置当前的虚拟目录
*如果要共享,则可以将path设置为"/”
2.不同的tomcat服务器间cookie共享问题?
setDomain(string path):
如果设置一级域名相同,那么多个服务器之间cookie可以共享
setDomain(".baidu.com") ,那么tieba.baidu.com和news.baidu.com中cookie可以共享
-
cookie的特点和作用
1.cookie存储数据在客户端浏览器
2.浏览器对于单个cookie的大小有限制(4kb)以及对同一个域名下的总cookie数量也有限制(20个)
*作用∶
1.cookie—般用于存出少量的不太敏感的数据
2.在不登录的情况下,完成服务器对客户端的身份识别 - 例子
response.setContentType("text/html;charset=utf-8");
//获取cookie
Cookie[] cookies = request.getCookies();//获取cookies
Boolean flag=false; //是否第一次访问
/**不是第一次访问**/
if(cookies!=null&&cookies.length>0){ //如果cookie存在
for (Cookie cookie:cookies) { //循环cookie
if("lastTime".equals(cookie.getName())){ //如果cookie的名字是lastTime说明cookie存在
flag=true; //不是第一次访问
Date date = new Date(); //创建系统时间
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//格式化时间对象
String str_date = dateFormat.format(date); //格式化时间
//编码
str_date=URLEncoder.encode(str_date,"utf-8"); //特殊字符空格会报错,用URL编码
cookie.setValue(str_date); //设置lastTime的值是系统时间
cookie.setMaxAge(30*24*60*60);//保存一个月
response.addCookie(cookie); //保存cookie
String value = cookie.getValue();//获取cookie的值
//解码
value=URLDecoder.decode(value,"utf-8"); //输出的时候要解码
response.getWriter().write("<h1>欢迎回来你上次访问的时间是"+value+"</h1>");
break;
}
}
}
/**第一次访问**/
if(cookies==null||cookies.length==0||flag==false){
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str_date = dateFormat.format(date);
//编码
str_date=URLEncoder.encode(str_date,"utf-8");
Cookie cookie=new Cookie("lastTime",str_date);
cookie.setMaxAge(30*24*60*60);
response.addCookie(cookie);
response.getWriter().write("<h1>欢迎你首次访问</h1>");
}
-
Session :
概念∶服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。Httpsession
1.获取Httpsession对象:
Httpsession session = request.getsession();
2.使用Httpsession对象︰
object getAttribute(string name)
void setAttribute(string name,object value)
void removeAttribute(string name)
-
原理:
-
细节:
- 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
默认情况下。不是。
如果需要相同,则可以创建cookie,键为"SESSIONID,设置最大存活时间,让cookie持久化保存。
cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addcookie(c); - 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
不是同一个,但是要确保数据不丢失
session的钝化:在服务器正常关闭之前,将session对象系列化到硬盘上
session的活化:在服务器启动后,将session文件转化为内存中的session对象即可。 - session什么时候被销毁?|
1.服务器关闭
2.session对象调用invalidate() 。
3.session默认失效时间30分钟
选择性配置修改:web.xml
<session-config>
<session-timeout>30</session-timeout>
</session-config>
- 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
-
session的特点
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型,任意大小的数据
-
session与cookie的区别:
- session存储数据在服务器端,Cookie在客户端
- session没有数据大小限制,Cookie有
- session数据安全,Cookie相对于不安全
案例,验证码
jdbc工具类:
public class Druid {
private static DataSource ds;
static {
try {
Properties pro=new Properties();
//查找数据库连接的配置文件
InputStream is= Druid.class.getClassLoader().getResourceAsStream("jdbc.properties");
pro.load(is);
ds= DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接池
public static DataSource getDataSource(){
return ds;
}
//获取数据库连接对象
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
dao提供的login方法
public class UserDao {
private JdbcTemplate template=new JdbcTemplate(Druid.getDataSource());
public User login(User user) {
try {
String sql="select * from user where username=? and password=?";
User BeanUser = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), user.getUsername(), user.getPassword());
return BeanUser;
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
}
sessionLogin.jsp
<form action="/newServlet/SessionLoginServlet">
<table>
<tr><td>用户名</td><td><input type="text" name="username"></td></tr>
<tr><td>密码</td><td><input type="password" name="password"></td></tr>
<tr><td>验证码</td><td><input type="text" name="checkCode"></td></tr>
<tr><td colspan="2"><img id="checkCodeImg" src="/newServlet/CheckCodeServlet" alt=""></td></tr>
<tr><td colspan="2"><input type="submit" value="提交"></td></tr>
</table>
</form>
<div><%= request.getAttribute("error_login")==null?"":request.getAttribute("error_login") %></div>
<div><%= request.getAttribute("error_code")==null?"":request.getAttribute("error_code") %></div>
<script>
document.getElementById("checkCodeImg").onclick=function(){
this.src="/newServlet/CheckCodeServlet?"+new Date().getTime();
}
</script>
验证码图片
package com.xjbt.session;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* 画验证码
* */
int width=100;
int height=50;
//1.创建—对象,在内存中图片(验证码图片对象)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.美化图片
Graphics graphics = image.getGraphics();//画笔对象
//填充粉红色
graphics.setColor(Color.pink);//设置画笔颜色
graphics.fillRect(0,0,width,height);//填充
//蓝色边框
graphics.setColor(Color.blue);
graphics.drawRect(0,0,width-1,height-1);
//写数字
String str="ABCDEFGHIJKLMNOPQISCUVWSYZabcdefghijklmnopqiscuvwsyz0123456789";
//生成随机角标
Random rand = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 1; i <=4 ; i++) {
int index = rand.nextInt(str.length());
//获取随机字符
char c = str.charAt(index);//随机字符
sb.append(c);
graphics.drawString(c+"",width/5*i,height/2);
}
String checkCode_session = sb.toString();
request.getSession().setAttribute("checkCode_session",checkCode_session);//将验证码存入session
//4画干扰线
graphics.setColor(Color.green);
for (int i = 1; i <=10; i++) {
int x1=rand.nextInt(width);
int y1=rand.nextInt(height);
int x2=rand.nextInt(width);
int y2=rand.nextInt(height);
graphics.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面展示
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1><%= request.getSession().getAttribute("user")%>,欢迎你!</h1>
</body>
</html>
sessionLoginServlet.java
@WebServlet("/SessionLoginServlet")
public class SessionLoginServlet 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");
String checkCode = request.getParameter("checkCode");
*/
/**
* 获取用户信息(包含了用户id,username,password)
*/
Map<String, String[]> map = request.getParameterMap();
User loginUser=new User();//登录对象(包含了所有的用户信息)
try {
//使用beanutils
BeanUtils.populate(loginUser,map);//将传入的参数(输入框的内容),作为loginUser对象的成员变量的值
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
/**
*判断验证码是否添加正确
*/
//获取传入参数的验证码
String checkCode = request.getParameter("checkCode");
//获取session
HttpSession session = request.getSession();
//创建dao
UserDao userDao = new UserDao();
//获取存入session的checkCode_session【验证码】的值
String checkCode_session = (String) session.getAttribute("checkCode_session");
//删除验证码
session.removeAttribute("checkCode_session");//解决登陆成功后点击返回验证码还是原来的
if(checkCode_session!=null&&checkCode_session.equalsIgnoreCase(checkCode)){//忽略大小写(如果传入的验证码等于存入session的验证码)
//验证用户名密码
User user = userDao.login(loginUser);
if(user!=null){
//存用户信息
session.setAttribute("user",user.getUsername());
//重定向到登录成功页面
response.sendRedirect(request.getContextPath()+"/success.jsp");
}else{
//登录失败
//存入提示信息
request.setAttribute("error_login","用户名或密码错误");
request.getRequestDispatcher("/sessionLogin.jsp").forward(request,response);
}
}else{
//存入提示信息
request.setAttribute("error_code","验证码输入错误");
request.getRequestDispatcher("/sessionLogin.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}