Session会话机制的应用(用户登录)


提示:以下是本篇文章正文内容,Java系列学习将会持续更新

程序的流程

  1. 静态页面: login.html —(POST请求)—> /login.do
  2. 静态页面: register.html —(POST请求)—> /register.do
  3. 动态页面: URL+回车 —(GET请求)—> /publish.html
  4. 注册 —> 登录 —> 个人动态页面
  5. 用户只有登录后,才能访问到动态页面。

正是Cookie + Session会话机制的应用:

  1. 用户成功登录后,服务器会生成一个session对象,来存储用户的登录状态。
  2. 服务器依赖cookie将 session-id传递给客户端(浏览器),客户端保存 cookie 值。
  3. 客户端(浏览器)每次请求的时候,都会携带 cookie 值。
    如果能对上,说明用户已经登录,则可以访问到个人动态页面。
    如果对不上,说明用户还没有登录,则访问不到,需要重新登录。

main

java

dao

UserDao
// SQL 操作
public class UserDao { // 单例模式, 饿汉式

    private static UserDao userDao = new UserDao();
    private UserDao() { }
    public static UserDao getUserDao() {
        return userDao;
    }

    public User selectOneByUsernameAndPassword(String username, String password) {
        try (Connection c = DBUtil.connection()) {
            String sql = "select uid from users where username = ? and password = ?";
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setString(1, username);
                ps.setString(2, password);

                System.out.println("执行 SQL: " + ps);
                try (ResultSet rs = ps.executeQuery()) {
                    if (!rs.next()) {
                        return null;
                    }

                    return new User(rs.getInt("uid"), username, password);
                }
            }
        } catch (SQLException exc) {
            throw new RuntimeException(exc);
        }
    }

    public User insert(String username, String password) {
        // TODO: 表中的username不能重复,暂时不考虑如何解决重复的问题
        try (Connection c = DBUtil.connection()) {
            String sql = "insert into users (username, password) values (?, ?)";
            try (PreparedStatement ps = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
                ps.setString(1, username);
                ps.setString(2, password);
                ps.executeUpdate();
                int uid;
                try (ResultSet rs = ps.getGeneratedKeys()) {
                    rs.next();
                    uid = rs.getInt(1);
                }
                // 返回当前用户
                return new User(uid, username, password);
            }
        } catch (SQLException exc) {
            throw new RuntimeException(exc);
        }
    }
}

回到目录…

model

User
public class User {
    public Integer uid;
    public String username;
    public String password;

    public User(int uid, String username, String password) {
        this.uid = uid;
        this.username = username;
        this.password = password;
    }

    // 检验用户名和密码合法性
    public static boolean isLegal(String username, String password) {
        if(username == null || password == null) {
            return false;
        }
        if(username.trim().isEmpty() || password.trim().isEmpty()) {
            return false;
        }
        return true;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(username, user.username) && Objects.equals(password, user.password);
    }

    @Override
    public int hashCode() {
        return Objects.hash(username, password);
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

回到目录…

servlet

LoginServlet

login.html发送 POST 请求,访问到 /login.do

// 登录操作
@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 读取 用户名 + 密码
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 检验输入的合法性检查
        if (!User.isLegal(username, password)) {
            // 不合法重新登录
            resp.sendRedirect("/login.html");
            return;
        }
        System.out.println("DEBUG: username=" + username);
        System.out.println("DEBUG: password=" + password);

        // 2. 在所有用户之中查找匹配(用户名和密码都相等)的用户
        UserDao userDao = UserDao.getUserDao();
        User currentUser = userDao.selectOneByUsernameAndPassword(username, password);

        // 3. 成功进行登录;失败跳回登录页
        if (currentUser == null) {
            // 登录失败
            // 重定向 /login.html
            resp.sendRedirect("/login.html");
            return;
        }

        // 进行登录 —— 只有登录才能创建会话
        HttpSession session = req.getSession(true);
        // 这里的 key 设置任何字符串都可以,只要以后一直统一使用即可
        session.setAttribute("currentUser", currentUser);

        // 表示登录成功
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/plain");
        PrintWriter writer = resp.getWriter();
        writer.printf("欢迎 %s 使用我们的系统的", currentUser);
    }
}

回到目录…

PublishServlet

用户URL+回车发送 GET 请求,访问到 /publish.html

// 动态显示页面。登陆后才能显示内容
@WebServlet("/publish.html")
public class PublishServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取当前登录用户(从会话中读取)
        User currentUser = null;
        // 1.1 获取会话对象(session 对象)
        HttpSession session = req.getSession(false); // 参数必须写 false,确保不新建 session 会话
        if (session == null) {
            // 说明之前没有会话,所以更不可能存在当前用户对象
            resp.sendRedirect("/login.html");
            return;
        }

        // 说明 session 对象存在,从 session 对象中拿 当前用户对象
        // 当前用户对象是 LoginServlet 登录成功之后放到 session 对象中的
        currentUser = (User) session.getAttribute("currentUser");
        if (currentUser == null) {
            // 说明 session 存在,但当前用户对象不存在
            resp.sendRedirect("/login.html");
            return;
        }

        // 获取到当前用户了,currentUser
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        PrintWriter writer = resp.getWriter();
        writer.printf("<h1>%s</h1>", currentUser);
    }
}

回到目录…

RegisterServlet

register.html发送 POST 请求,访问到 /register.do

// 注册操作
@WebServlet("/register.do")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 读取 username + password
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 检验输入的合法性检查
        if (!User.isLegal(username, password)) {
            // 不合法重新注册
            resp.sendRedirect("/register.html");
            return;
        }

        // 2. 注册,向表中插入数据,通过 UserDao
        UserDao userDao = UserDao.getUserDao();
        User currentUser = userDao.insert(username, password);

        // 再次跳到登录界面
        resp.sendRedirect("/login.html");
    }
}

回到目录…

util

DBUtil
public class DBUtil {
    private static final DataSource dataSource;

    static {
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        mysqlDataSource.setUrl("jdbc:mysql:///lianxi?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai");
        mysqlDataSource.setUser("root");
        mysqlDataSource.setPassword("123456");

        dataSource = mysqlDataSource;
    }

    public static Connection connection() throws SQLException {
        return dataSource.getConnection();
    }
}

回到目录…

webapp

WEB-INF

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="false">
</web-app>

回到目录…

login.html

<!DOCTYPE html>
<html lang="zh-hans">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <form action="/login.do" method="post">
        <input type="text" name="username">
        <input type="password" name="password">
        <button>登录</button>
        <a href="./register.html">注册</a>
    </form>
</body>
</html>

回到目录…

register.html

<!DOCTYPE html>
<html lang="zh-hans">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    <form action="/register.do" method="post">
        <input type="text" name="username">
        <input type="password" name="password">
        <button>注册</button>
    </form>
</body>
</html>

回到目录…

运行效果

  1. 注册
    在这里插入图片描述

  2. 登录
    在这里插入图片描述
    在这里插入图片描述

  3. 用户登录后的动态页面
    在这里插入图片描述

回到目录…


总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是JavaWeb的学习,在我们学会了session会话机制的条件下,我们可以做一个登录的小程序。之后的学习内容将持续更新!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一只咸鱼。。

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

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

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

打赏作者

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

抵扣说明:

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

余额充值