JavaWeb-Session

博客
JavaWeb

seesion

1. 概念

Session技术是将数据存储在服务器端的技术,会为每个客户端都创建一块内存空间 存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内 存空间。所以说Session的实现是基于Cookie,Session需要借助于Cookie存储客 户的唯一性标识JSESSIONID。

2. 快速入门
  1. 获取HttpSession对象:
    HttpSession session = request.getSession();
    此方法会获得专属于当前会话的Session对象,如果服务器端没有该会话的Session 对象会创建一个新的Session返回,如果已经有了属于该会话的Session直接将已有的Session返回。(实质就是根据JSESSIONID判断该客户端是否在服务器上已经存在session了。)

  2. 使用HttpSession对象(session也是一个域对象)
    Session也是存储数据的区域对象,所以session对象也具有如下三个方法:
    Object getAttribute(String name) ;
    void setAttribute(String name, Object value);
    void removeAttribute(String name) ;

3. session原理

基于响应头set-cookie和请求头cookie实现图解
在这里插入图片描述

4. session细节
1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?

默认情况下。不是。因为cookie默认是一次会话,JSESSIONID会被销毁掉。就没办法根据JSESSIONID去找session。
如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。

代码演示

@WebServlet("/sessionServlet3")
public class SessionServlet3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建session对象
        HttpSession session = request.getSession();
        //设置参数
        session.setAttribute("daye","heibangjiaofu");

        //创建servletContext对象
        ServletContext servletContext = this.getServletContext();
        //将创建的session对象存储到servletContext域中。用于比对session的地址值
        servletContext.setAttribute("session", session);
        //创建Cookie对象存储sessionID
        Cookie cookie = new Cookie("JSESSIONID",session.getId());
        //设置cookie持久化时间
        cookie.setMaxAge(60*10);//持久化10分钟
        //写回cookie
        response.addCookie(cookie);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

访问/sessionServlet3将JSESSIONID存储到Cookie中
在这里插入图片描述

测试持久化JSESSIONID。

@WebServlet("/sessionServlet4")
public class SessionServlet4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取session对象
        HttpSession session = request.getSession();
        //获取session中的值
        String daye = (String) session.getAttribute("daye");
        System.out.println(daye);

        //获取servletContxt对象
        ServletContext servletContext = this.getServletContext();
        Object session2 = servletContext.getAttribute("session");
        System.out.println(session==session2);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

关闭浏览器后在访问/sessionServlet4会携带持久化cookie里面有JSESSIONID
在这里插入图片描述
访问结果:

heibangjiaofu 	session中的值。
true 	证明获取的两个session对象是同一个对象。
2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?

不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作。(在tomcat/work目录下)

session的钝化:
			在服务器正常关闭之前,将session对象系列化到硬盘上
session的活化:
			在服务器启动后,将session文件转化为内存中的session对象即可

1.演示服务器钝化和活化,在IDEA中演示不了钝化和活化。所以把out目录下有关案例:验证码项目打成压缩包并改成war包。
IDEA为什么不能演示session钝化活化?
IDEA配置文件C:\Users\Administrator.IntelliJIdea2017.3\system\tomcat_basic-code下有一个work目录,每次在IDEA启动的时候,就会先删除work目录在创建一个新的work目录,新的work目录就找不到以前的SESSION.ser文件,就演示不了session钝化和活化,这个其实没什么关系,因为项目最终是要部署在服务器上面的,而不是在IDEA上。

在这里插入图片描述
2.将war包放入到tomcat7服务器下的webapps目录下,并启动服务器,服务器自动解压war包成day66。
在这里插入图片描述
3.访问登录页面服务器就会有客户端对应的session
在这里插入图片描述
4.然后正常关闭服务器,在tomcat7服务器的work\Catalina\localhost\day66下自动生成SESSION.ser,其实当服务器关闭后,这就是session的钝化。
在这里插入图片描述
5.在启动服务器SESSIONS.ser文件已经没有了,这就是session活化。
在这里插入图片描述

3. session什么时候被销毁?
1. 服务器关闭
2. session对象调用invalidate() 。
3. session默认失效时间 30分钟
	在tomcat自带的web.xml选择性配置修改,当然也可以在自己的项目中覆盖掉web.xml配置。	
		<session-config>
	       <session-timeout>30</session-timeout>
	    </session-config>
session特点
  1. session用于存储一次会话的多次请求的数据,存在服务器端。
  2. session可以存储任意类型,任意大小的数据。
  3. session与Cookie的区别:
		1. session存储数据在服务器端,Cookie在客户端
		2. session没有数据大小限制,Cookie有
		3. session数据安全,Cookie相对于不安全
案例:验证码
案例需求:
		1. 访问带有验证码的登录页面login.jsp
		2. 用户输入用户名,密码以及验证码。
				如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
			    如果验证码输入有误,跳转登录页面,提示:验证码错误
			    如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您

后端登录代码

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置中文乱码
        request.setCharacterEncoding("utf-8");
        //获取所有的请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
       /* Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        for (Map.Entry<String, String[]> entry : entries) {
            System.out.print(entry.getKey()+":");
            String[] strings = entry.getValue();
            for (String string : strings) {
                System.out.print(string);
            }
            System.out.println();
        }*/
        //使用BeanUtils封装数据
        User user = new User();
        try {
            BeanUtils.populate(user, parameterMap);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //获取checkImgServlet中存储的session
        //这里获取到的就是成语
        String checkcode_session = (String) request.getSession().getAttribute("checkcode_session");
        request.getSession().removeAttribute("checkcode_session");//保证验证码的一次性
        //判断验证码和用户输入的验证码是否一致
        if (checkcode_session!=null && checkcode_session.equals(user.getCheckcode())) {
            //一致
            //再接着判断用户名和密码是否一致
            if ("geleifusi".equals(user.getUsername()) && "123456".equals(user.getPassword())) {
                //登录成功了重定向到成功页面
                HttpSession session = request.getSession();
                session.setAttribute("user-session",user.getUsername() );
                response.sendRedirect("/ginger/success.jsp");
            } else {
                //用户名和密码不一致,转发到登录页面
                request.setAttribute("login_error", "用户名或者密码错误。");
                request.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        } else {
            //不一致转发到登录页面
            request.setAttribute("login_error", "验证码错误,请重新输入。");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

验证码程序

@WebServlet("/checkImgServlet")
public class CheckImgServlet extends HttpServlet {
    // 集合中保存所有成语
    private List<String> words = new ArrayList<String>();
    @Override
    public void init() throws ServletException {
        // 初始化阶段,读取new_words.txt
        // web工程中读取 文件,必须使用绝对磁盘路径
        String path = getServletContext().getRealPath("/chengyu.txt");
        try {
            BufferedReader reader = new BufferedReader(new FileReader(path));
            String line;
            while ((line = reader.readLine()) != null) {
                line = new String(line.getBytes("gbk"), "utf-8");
                words.add(line);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 禁止缓存
        // response.setHeader("Cache-Control", "no-cache");
        // response.setHeader("Pragma", "no-cache");
        // response.setDateHeader("Expires", -1);
        int width = 120;
        int height = 30;

        // 步骤一 绘制一张内存中图片
        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, 18));
        Random random = new Random();// 生成随机数
        int index = random.nextInt(words.size());
        String word = words.get(index);// 获得成语
        // 定义x坐标
        int x = 10;
        for (int i = 0; i < word.length(); 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;
            // 获得字母数字
            char c = word.charAt(i);
            // 将c 输出到图片
            graphics2d.rotate(theta, x, 20);
            graphics2d.drawString(String.valueOf(c), x, 20);
            graphics2d.rotate(-theta, x, 20);
            x += 30;
        }
        // 将验证码内容保存session
        request.getSession().setAttribute("checkcode_session", word);

        // 步骤五 绘制干扰线
        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();// 释放资源

        //将图片写到response.getOutputStream()中
        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);
    }
}

验证码依赖的文件chengyu.txt

一唱一和
一呼百应
一干二净
一举两得
一落千丈
一模一样
一暴十寒
一日千里
一五一十
一心一意
两面三刀
三长两短
三番五次
三三两两
三头六臂
三心二意
三言两语
四分五裂
四面八方
四通八达
四平八稳
五光十色
五湖四海
五花八门
五颜六色
六神无主
七颠八倒
七零八落
七拼八凑
七上八下
七手八脚
七嘴八舌
八面玲珑
九死一生
十全十美
百发百中
百孔千疮
百战百胜
百依百顺
千变万化
千差万别
千军万马
千山万水
千丝万缕
千辛万苦
千言万语
千真万确

实体类

public class User {
    private String username;
    private String password;
    private String checkcode;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getCheckcode() {
        return checkcode;
    }
    public void setCheckcode(String checkcode) {
        this.checkcode = checkcode;
    }
}

登录页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login</title>
</head>
<script>
    window.onload = function () {
        document.getElementById("checkCode").onclick =function() {
            this.src="/ginger/checkImgServlet?"+new Date().getTime();
        }
    }
</script>
<body>
<form action="/ginger/loginServlet" method="post">
    姓名:<input type="text" name="username"><br>
    用户名:<input type="text" name="password"><br>
    验证码:<input type="text" name="checkcode"><br>
    <img id="checkCode" src="/ginger/checkImgServlet" style="width:200px;height:60px"><br>

    <div style="color:red"><%=request.getAttribute("login_error")==null? "":request.getAttribute("login_error")%></div>

    <input type="submit" value="登录">
</form>
</body>
</html>

登录成功页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功页面</title>
</head>
<body>
    <h1><%=request.getSession().getAttribute("user-session")%>,欢迎您</h1>
</body>
</html>

登录测试

在这里插入图片描述
登录成功
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值