会话机制(session)

实现登录功能

  • 步骤1:数据库当中添加一个用户表:t_user

    t_user表当中存储的是用户的登录信息,最基本的也包括:登录的用户名和登录的密码。
    密码一般在数据库表当中存储的是密文。一般不以明文的形式存储。(这里先使用明文方式。)

  • 步骤2:再实现一个登录页面。

    登录页面上应该有一个登录的表单。有用户名和密码输入的框。
    用户点击登录,提交表单,提交用户名和密码。form是post方式提交。

  • 步骤3:后台要有一个对应的Servlet来处理登录的请求。

    登录成功:跳转到登录成功页面。
    登录失败:跳转到失败的页面。

index.jsp页面


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>欢迎登录</title>
  </head>
  <body>
  <h1>用户登录</h1><hr>
  <form action="<%=request.getContextPath()%>/user/login" method="post">
    username:<input type="text" name="username"><br>
    password:<input type="password" name="password"><br>
    <input type="submit" value="login">
  </form>
  </body>
</html>

UserServlet

@WebServlet("/user/login")
public class UserServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        boolean success = false;
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DButil.getConnection();
            String sql = "select * from t_user where loginName=? and loginPwd=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,username);
            ps.setString(2,password);
            rs = ps.executeQuery();
            if (rs.next()) {
                success = true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DButil.close(conn,ps,rs);
        }
        if (success) {
            response.sendRedirect(""+request.getContextPath()+"/success.html");//跳成功页面
        }else{
            response.sendRedirect(""+request.getContextPath()+"/fail.html");//跳失败页面
        }
    }
}

DButil数据库工具类

登录功能实现了,目前存在的最大的问题:
如果在后面有一些登录后才能操作的功能,在浏览器地址栏输入http://localhost:8080/项目名/路径,只要知道路径就可以直接不用登录进行操作。
这个登录功能目前只是一个摆设,没有任何作用。只要用户知道后端的请求路径,照样可以在不登录的情况下访问。

为什么?
发现代码中登录只是一种请求,而request的生命周期很短,一次请求一个对象。
HttpServletRequest接口详解
如果用ServletContext保存的话,生命周期又很长,服务器启动时创建,关闭是销毁。
ServletContext应用域详解

会话机制(session)

在HttpServletReauest有一个获取会话的对象方法

    	public HttpSession getSession();

然后编写代码打印输出到浏览器

		HttpSession session = request.getSession();
    	response.setContentType("text/html,charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print(session);

发现只要不关闭浏览器,无论打开多少个窗口,都会输出同一个对象,只要重新打开浏览器重新访问,输出的对象就不是同一个。

会话机制(session):用户打开浏览器,进行一系列操作,然后最终将浏览器关闭,这个整个过程叫做:一次会话。java对象叫做:session。

  1. session对象是存储在服务端的
  2. 一个session对象对应一个会话
  3. 一次会话包含多次请求

在java的servlet规范当中,session对应的类名:HttpSession(jarkata.servlet.http.HttpSession),session机制属于B/S结构的一部分。

为什么需要session对象来保存会话状态呢?
因为HTTP协议是一种无状态协议(请求的时候,B和S是连接的,但是请求结束之后,连接就断了。)。

会话实现原理

有这样一个问题,服务器有很多个session,那怎么保证,用户获取到的是同一个对象,不会获取到另一个用户的session呢?

在web服务器有一个session列表,类似于Map集合
Map集合key存储的是session的id,value存储的是对应的session对象

  • 当用户发送第一次请求的时候:服务器会创建一个新的session对象,同时给它生成一个id,然后会将这个id发给浏览器,浏览器会把这个id保存在浏览器缓存中。
  • 当用户发送第二次请求的时候:会自动将浏览器缓存中的session的id自动发送服务器,然后服务器根据id就会从session列表中查找对应的session对象。
  • 当用户关闭浏览器之后,这个保存的缓存id就消失了,下次重新打开浏览器的之后,服务器自然就找不到session对象,等同于会话结束。
  • 当用户关闭浏览器,会话结束,但是服务器里之前的session对象还存在,这时候会有个超时机制,当长时间未操作的时候,会自动销毁session对象。
  • 当用户重新打开浏览器时,再次访问,就会生成新的session

超时时长可以在web.xml文件配置,例如配置60分钟
默认时长可以在服务器的web.xml查看

	<session-config>
        <session-timeout>60</session-timeout>
    </session-config>

Cookie

还是上面的代码进行测试,打开浏览器,按F12,查看第一次访问
请添加图片描述
发现第一次访问,会响应一个Set-Cookie:JSESSIONID=XXX过来,点击刷新,再次发送请求
请添加图片描述
查看请求,发现会发送一个Cookie:JSESSIONID=XXX过去,且内容与第一次响应过来的一样。
所以JSESSIONID是以Cookie的形式保存在浏览器里面,浏览器只要关闭。这个Cookie就没有了。

Cookie禁用了,session还能找到吗?

  • 服务器正常发送cookie给浏览器,但是浏览器拒收了。并不是服务器不发了。
  • 找不到了。每一次请求都会获取到新的session对象。
  • cookie禁用了,session机制还能实现吗?
    • 可以。需要使用URL重写机制。
    • http://localhost:8080/项目名/路径;jsessionid=XXX
    • URL重写机制会提高开发者的成本。开发人员在编写任何请求路径的时候,后面都要添加一个sessionid,给开发带来了很大的难度,很大的成本。

session会话的常用方法

Object getAttribute​(String name)//返回在此会话中绑定了指定名称的对象,或者如果该名称下没有绑定任何对象,则返回该对象null
void setAttribute​(String name, Object value)//使用指定的名称将对象绑定到此会话。
void removeAttribute​(String name)//从此会话中删除绑定了指定名称的对象。
void invalidate()//结束会话,然后取消绑定到它的任何对象。

改造登录功能

UserServlet

@WebServlet("/user/login")
public class UserServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        boolean success = false;
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DButil.getConnection();
            String sql = "select * from t_user where loginName=? and loginPwd=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,username);
            ps.setString(2,password);
            rs = ps.executeQuery();
            if (rs.next()) {
                success = true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DButil.close(conn,ps,rs);
        }
        if (success) {
            HttpSession session = request.getSession();//获取session,必须获取到
            session.setAttribute("username",username);//把用户名存进去
            response.sendRedirect(""+request.getContextPath()+"/user/success");//跳到另一个servlet进行处理
        }else{
            response.sendRedirect(""+request.getContextPath()+"/fail.html");
        }
    }
}

UserLoginServlet

public class UserLoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("username") != null) {//获取到,可以在里面写功能,这里直接就跳到登录成功页面
            response.sendRedirect(request.getContextPath()+"/success.html");
        }else {
            response.sendRedirect(request.getContextPath());//重新跳到登录页面
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

登录成功之后,可以将用户的登录信息存储到session当中。也就是说session中如果有用户的信息就代表用户登录成功了。session中没有用户信息,表示用户没有登录过。则跳转到登录页面。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忆亦何为

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值