Session概述
Session是一种在服务端记录用户会话信息的技术
Session的创建和获取
/*** HttpServletRequest对象中的方法:* public HttpSession getSession()* 如果当前服务端没有session,那就在服务端新建一个session对象* 如果在服务端有这个session,那么就直接返回这个session* HttpSession中的方法:* void setAttribute(String name, Object value)* 向Session中添加数据*/@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//没有session就创建,有就返回HttpSession session = request.getSession();//添加数据session.setAttribute("username","zs");//新值覆盖老值session.setAttribute("username","ls");}@Overrideprotected 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
@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {HttpSession session = request.getSession();//销毁cookiesession.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);// 将生成字母数字 加入bufferbuffer.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);}// 将上面图片输出到浏览器 ImageIOgraphics.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
//判断用户输入的验证码与随机生成的验证码是否相等@Overrideprotected 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("验证码输入错误");}}