Session概述
Session是一种在服务端记录用户会话信息的技术
Session的创建和获取
/**
* HttpServletRequest对象中的方法:
* public HttpSession getSession()
* 如果当前服务端没有session,那就在服务端新建一个session对象
* 如果在服务端有这个session,那么就直接返回这个session
* HttpSession中的方法:
* void setAttribute(String name, Object value)
* 向Session中添加数据
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//没有session就创建,有就返回
HttpSession session = request.getSession();
//添加数据
session.setAttribute("username","zs");
//新值覆盖老值
session.setAttribute("username","ls");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
//取出数据
//注意:session.getAttribute("username")返回值为object类型,并非String类型
response.getWriter().write(session.getAttribute("username").toString());
}
Session的生命周期
1 默认存活时间
1.Session默认存活时间:30min (类似会员截至使用期限)
session默认存活时间:如果会话静置(浏览器不做任何操作)或者关闭浏览器30min后服务端会销毁这个sessionTomcat的默认配置 conf/controller.xml:针对所有应用的session都生效
<session-config>
<session-timeout>30</session-timeout>
</session-config>如果在本应用下的web.xml中配置session超时时间,那么会覆盖掉默认session配置
<session-config>
<session-timeout>10</session-timeout><!--当前应用的session默认存活时间10min-->
</session-config>
2 手动销毁Session
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
//销毁cookie
session.invalidate();
}
3 Session的钝化与活化
Session钝化(序列化):当我们正常关闭服务器时候,服务器会把内存中session对象存储到硬盘的文件中 (Session从内存=>硬盘)
Session活化(反序列化):当我们再次启动服务器的时候,服务器会从存储session的文件中,将session对象加载到内存中(Session从硬盘=>内存)
可以把一部分Session存储到硬盘上节约服务端内存当我们正常关闭tomcat的时候,Session对象会钝化到work目录下的一个文件
在IDEA中重启Tomcat的时候,IDEA会删除work目录重新创建,导致Tomcat读取不到存储Session文件
解决方案:
在context.xml中修改钝化Session默认路径:
<Manager className="org.apache.catalina.session.PersistentManager">
<Store className="org.apache.catalina.session.FileStore" directory="D:\"> <!--设置Session文件存储位置-->
</Manager>
Session案例
GenerateCodeServlet.java
/**
* 生成验证码图片
*/
@WebServlet("/generateCode")
public class GenerateCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 120;
int height = 32;
// 步骤一 绘制一张内存中图片
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 步骤二 图片绘制背景颜色 ---通过绘图对象
Graphics graphics = bufferedImage.getGraphics();// 得到画图对象 --- 画笔
// 绘制任何图形之前 都必须指定一个颜色
graphics.setColor(getRandColor(200, 250));
graphics.fillRect(0, 0, width, height);
// 步骤三 绘制边框
graphics.setColor(Color.WHITE);
graphics.drawRect(0, 0, width - 1, height - 1);
// 步骤四 四个随机数字
Graphics2D graphics2d = (Graphics2D) graphics;
// 设置输出字体
graphics2d.setFont(new Font("宋体", Font.BOLD, 23));
String words = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
Random random = new Random();// 生成随机数
StringBuffer buffer = new StringBuffer();
// 定义x坐标
int x = 10;
for (int i = 0; i < 4; i++) {
// 随机颜色
graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random
.nextInt(110), 20 + random.nextInt(110)));
// 旋转 -30 --- 30度
int jiaodu = random.nextInt(60) - 30;
// 换算弧度
double theta = jiaodu * Math.PI / 180;
// 生成一个随机数字
int index = random.nextInt(words.length()); // 生成随机数 0 到 length - 1
// 获得字母数字
char c = words.charAt(index);
// 将生成字母数字 加入buffer
buffer.append(c);
// 将c 输出到图片
graphics2d.rotate(theta, x, 20);
graphics2d.drawString(String.valueOf(c), x, 20);
graphics2d.rotate(-theta, x, 20);
x += 30;
}
//将生成的验证码存入到session域中
request.getSession().setAttribute("code", buffer.toString());
// 步骤五 绘制干扰线
graphics.setColor(getRandColor(160, 200));
int x1;
int x2;
int y1;
int y2;
for (int i = 0; i < 30; i++) {
x1 = random.nextInt(width);
x2 = random.nextInt(12);
y1 = random.nextInt(height);
y2 = random.nextInt(12);
graphics.drawLine(x1, y1, x1 + x2, x2 + y2);
}
// 将上面图片输出到浏览器 ImageIO
graphics.dispose();// 释放资源
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
/**
* 取其某一范围的color
*
* @param fc int 范围参数1
* @param bc int 范围参数2
* @return Color
*/
private Color getRandColor(int fc, int bc) {
// 取其随机颜色
Random random = new Random();
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
}
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码</title>
<script>
function changeCode() {
var imgEle = document.getElementById("code");
//getTime()获取自1970年1月1日0时0分0秒到现在系统时间毫秒值
//每次点击图片我们请求的链接都不同,浏览器就不再访问缓存,而是每次请求都回去请求服务端的servlet
//或者直接停用缓存,浏览器就不会访问缓存
imgEle.src = "/day12_Cookie/generateCode?time=" + new Date().getTime();
}
</script>
</head>
<body>
<form action="/day12_Cookie/CheckCore" method="post">
请输入验证码:<input type="text" name="outCode">
<img src="/day12_Cookie/generateCode" id="code" onclick="changeCode()">
<br>
<input type="submit">
</form>
</body>
</html>
CheckCore.java
//判断用户输入的验证码与随机生成的验证码是否相等
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
HttpSession session = request.getSession();
//通过name值获取验证码
String code = session.getAttribute("code").toString();
//获取用户输入的验证码
String outCode = request.getParameter("outCode");
//比较
//因为验证码不区分大小写,所以采用equalsIgnoreCase()方法来进行比较
if (code.equalsIgnoreCase(outCode)){
response.getWriter().write("验证码输入正确");
}else {
response.getWriter().write("验证码输入错误");
}
}