【JavaEE】使Cookie与Session失效-Servlet上传文件操作-优化表白墙

【JavaEE】使Cookie与Session失效-表白墙退出登录操作-Servlet上传文件操作-表白墙注册上传头像+登录显示头像功能

1. Cookie与Session的删除

Cookie与Session基础博客【JavaEE】Cookie与Session的前后端交互-表白墙登录设计_s:103的博客-CSDN博客

  • 虽然Cookie和Session都是暂时存在的不久就会被删掉但是我们要退出登录的时候就不能等待其自然消除了~
    • 因为点击退出登录之后到达登录页面如果这个时候浏览器和服务器保留了Cookie和Session就会自动登录了~
    • 用户自己手动删Cookie不现实

这里就是一个固定的做法了

  • 一些东西是固定的目前看不懂也没事不是本文章重点

在这里插入图片描述

  • 创建一个新的Servlet程序Remove(/remove)
    • 注解的斜杠一定不要忘不仅仅是这个程序会出错而是整个项目全部出错
  1. 获取Session调用invalidate => 使session这个小哈希表无效

  2. 获取CookieCookie对象不是哈希表而是一个键值对对象而报文的Cookie里包含很多键值对甚至key可以重复

    • getCookies方法获取请求的Cookie所有键值对返回Cookie数组
    • 遍历数组找到key为loginpwdid的键值对将cookie的寿命改为0并通过响应发回浏览器调用addCookie方法
  3. 重定向

当其实只要打断其中的一条路就可以打破登录状态了使Cookie失效/使Session失效

简单了解

Cookie不仅仅有名字和值两个属性还有域domain、路径path等属性。其中不同的域、不同的路径下可以存在同样名字的cookie。一般我们设置cookie的方法是用一个同样名字、一个值。这时就一定要搞清楚你要设置的cookie的域和路径否则就会产生问题中的情况。

Cookie机制其实还可以存储很多其他的信息但在本文章不做研究暂时用不到

1.1 表白墙页面增加登录出口

在这里插入图片描述

在wall.html表白墙html添加导航栏和登录出口

在这里插入图片描述

  • 没错用到的css修饰一样是照抄博客系统的common.css中

在这里插入图片描述

  • 头像是默认的头像这里为什么是用户的头像后文提到

在这里插入图片描述

在这里插入图片描述

1.2 点击链接退出登录

  1. 跳转到登录页面
  2. 调用remove函数发送请求给服务器使Session/Cookie失效

在这里插入图片描述

1.3 测试

在这里插入图片描述

2. 上传文件

  • 这里只讲解一种通过form表单的file类型input按钮上传submit按钮提交

先看成品预计效果

在这里插入图片描述
在这里插入图片描述

设计稿
在这里插入图片描述

数据库表的设计

  • 表名为image
    1. 用户名
    2. 文件名

在这里插入图片描述

2.1 后端对上传文件的处理

2.1.1 HttpServletRequest 类方法

方法描述
Part getPart(String name)获取请求中给定 name 的文件
Collection getParts()获取所有的文件

2.1.2 Part 类方法

方法描述
String getSubmittedFileName()获取提交的文件名
String getContentType()获取提交的文件类型
long getSize()获取文件的大小
void write(String path)把提交的文件数据写入磁盘文件

高亮的为本文的重点方法~

2.1.3 操作

在这里插入图片描述

对于确认按钮点击它就是触发了form表单的提交将用户名和头像一同提交给服务器

  • 细节由于form的编码是特定的编码如果在后端以utf8去理解会报错所以只有在用户名不为中文或者什么特殊字符的时候才能正常的与头像进行绑定~
    • 中文虽然不会导致文件上传失败但是这个中文用户名不会绑定到头像也就是说此后这个账号将只显示默认的头像而不是自己的头像

而form在这里提交的应该是post请求其中的正文用户名可以用getParameter去获取

@MultipartConfig
@WebServlet("/reg")//form表单提交~
public class Register extends HttpServlet {
    //Part为一个Servlet提供
    //在这里确定这张照片是否应该存入数据库

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Part part = req.getPart("file");
        String fileName = part.getSubmittedFileName();
        part.write("D:\\马库\\mara-circle-june-2023\\showLove\\src\\main\\webapp\\" + fileName);
        String username = req.getParameter("name");
        resp.setContentType("text/html; charset=utf8");
        if(Save.isExistence("users", username) || Save.isExistence("image", username)) {
            resp.getWriter().write("<h1>已存在</h1>");
        }else {
            Save.insert("image", username, fileName);
            resp.getWriter().write("<h1>提交成功</h1>");
        }
    }
}

解析

在这里插入图片描述

write方法是直接写道硬盘上建议不要使用相对路径因为其默认的当前目录不是我们的项目目录~

  • 后面的文件名可以写自己的但是尽量不要该文件的类型

2.1.5 Image类

点击密码输入框发送请求获取头像的操作

@WebServlet("/image")
public class Image extends HttpServlet {

    ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf8");
        User img = objectMapper.readValue(req.getInputStream(), User.class);
        //不能处理一个只有一个成员的类
        String username = img.name;
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/Loves?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("mmsszsd666");//这是俺的微信号欢迎添加相互学习
        try {
            Connection connection = dataSource.getConnection();
            String sql = "select * from image where name = '" + username + "';";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            //这里的Set并不是对象为Love的Set集合而是一个迭代器
            ResultSet set = preparedStatement.executeQuery();
            //迭代他是next方法而不是hasNext
            if(set.next()) {
                resp.getWriter().write(set.getString("fileName"));
            }else {
                resp.getWriter().write("No");
            }
            set.close();
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}
  • 若数据库中并没有这个头像返回No~

2.1.4 Save类

  • 这个类是我自己包装的类包装了
    1. 在数据库中查询用户名是否注册过
    2. 在数据库中查询用户名是否与头像绑定国
    3. 给数据库的一张表中插入键值对
    4. 通过用户名获取图片

其中第一和第二为此方法

//传入表的名字和username
public static boolean isExistence(String tableName, String username) {
    DataSource dataSource = new MysqlDataSource();
    ((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/Loves?characterEncoding=utf8&useSSL=false");
    ((MysqlDataSource) dataSource).setUser("root");
    ((MysqlDataSource) dataSource).setPassword("mmsszsd666");//这是俺的微信号欢迎添加相互学习
    boolean ret = false;
    try {
        Connection connection = dataSource.getConnection();
        String sql = "select * from " + tableName + " where name = '" + username + "';";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //这里的Set并不是对象为Love的Set集合而是一个迭代器
        ResultSet set = preparedStatement.executeQuery();
        //迭代他是next方法而不是hasNext
        ret = set.next();
        set.close();
        preparedStatement.close();
        connection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return ret;//true 存在false不存在

}

在这里插入图片描述

第三为此方法

public static void insert(String tableName, String key, String value) {
    DataSource dataSource = new MysqlDataSource();
    ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/Loves?characterEncoding=utf8&useSSL=false");
    ((MysqlDataSource)dataSource).setUser("root");
    ((MysqlDataSource)dataSource).setPassword("mmsszsd666");//这是俺的微信号欢迎添加相互学习
    Connection connection = null;
    try {
        connection = dataSource.getConnection();
        String sql = "insert into " + tableName + " values(?, ?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1, key);
        preparedStatement.setString(2, value);
        preparedStatement.executeUpdate();
        preparedStatement.close();
        connection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }

}

在这里插入图片描述

第四为此方法

public static String getImage(String username) {
    DataSource dataSource = new MysqlDataSource();
    ((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/Loves?characterEncoding=utf8&useSSL=false");
    ((MysqlDataSource) dataSource).setUser("root");
    ((MysqlDataSource) dataSource).setPassword("mmsszsd666");//这是俺的微信号欢迎添加相互学习
    String ret = null;
    try {
        Connection connection = dataSource.getConnection();
        String sql = "select * from image where name = '" + username + "';";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //这里的Set并不是对象为Love的Set集合而是一个迭代器
        ResultSet set = preparedStatement.executeQuery();
        //迭代他是next方法而不是hasNext
        if(set.next()) {
            ret = set.getString("fileName");
        }else {
            ret = "https://img1.baidu.com/it/u=4205447136,2730860147&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=300";
        }
        set.close();
        preparedStatement.close();
        connection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return ret;
}
  • 与isExistence不同的是此方法返回一个文件名
    1. 找得到返回文件名
    2. 找不到返回默认头像

注意由于我直接将头像保存到了webapp目录下所以直接用用户名就可以访问到

所以刚才的 form表单请求处理操作中的这一段的解释为

  • 在这里千万不能改编码为utf8会报500

在这里插入图片描述

2.1.5 注册按钮

在这里插入图片描述

Save类本身也是个Servlet程序~

ObjectMapper objectMapper = new ObjectMapper();

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    User user = objectMapper.readValue(req.getInputStream(), User.class);
    resp.setContentType("text/html; charset=utf8");
    String username = user.name;//获取key对应值
    String password = user.password;
    if(isExistence("users", username)) {
        resp.getWriter().write("No");//存在此用户了
    }else {
        insert("users", username, password);
    }
}
  1. 存在此用户返回No
  2. 不存在则注册成功在users中插入用户信息

2.2 前端设计

  • 这个页面几乎照搬登录页面只是增加了一些元素罢了~
  • 用的css也直接用logIn.css和common.css

不包含js代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>注册页</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <link rel="stylesheet" href="common.css" />
    <link rel="stylesheet" href="logIn.css" />

    <style>
      #i {
        transition: all 0.618s;
        opacity: 61.8%;
      }
      #i:hover {
        opacity: 100%;
      }
    </style>
  </head>
  <body>
    <div class="navigation">
      <!-- 头像 -->
      <img
        src="https://img1.baidu.com/it/u=4205447136,2730860147&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=300"
        alt="未登录"
      />
      <div class="title">未登录</div>
      <div class="space"></div>

      <a href="login.html" onclick="remove()">登录</a>
    </div>
    <!-- 登录页面 -->

    <div class="login-Container">
      <div class="dialog">
        <h3>注册</h3>

        <form
          target="_blank"
          action="reg"
          method="POST"
          enctype="multipart/form-data"
        >
          <div id="fileImage">
            <input id="i" type="button" value="请上传头像" onclick="judge();" />
            <input type="file" name="file" style="display: none" />
            <div id="conf">
              <input
                type="submit"
                value="确认"
                id="co"
                onclick="alert(
                '如果你需要上传头像则需要注意以下几点\n' +
                  '1. 点击右侧的确认按钮后此用户名将无法更改头像\n' +
                  '2. 用户名应为英文字符否则虽然注册成功但是头像无法与您进行匹配\n' +
                  '3. 若用户名已被注册过或者已绑定头像则无法正常注册\n' + 
                  '4. 只有填写用户名后才能上传图片只有上传了图片才能点击确认否则会出错\n'
              );"
              />
            </div>
          </div>

          <div class="row">
            <label for="username">用户名</label>
            <input type="text" id="username" name="name" />
          </div>
        </form>

        <div class="row">
          <label for="password">密码</label>
          <input type="password" id="password" onclick="getImage()" />
        </div>
        <div class="r">
          <input type="submit" id="submit" value="注册" onclick="reg()" />
        </div>
      </div>
    </div>
  </body>
</html>

改动1头像触摸变化

在这里插入图片描述

改动2头像和按钮

  • form包住了头像和用户名输入框
  • 在确认的时候做一些提示~
  • 登录 -> 注册

在这里插入图片描述

改动3对新增元素进行css修饰

#fileImage {
    display: flex;
    justify-content: center;
    align-items: center;
    justify-content: space-around;
}
#conf {
    display: flex;
    justify-content: center;
    align-items: center;
}
#co {
    width: 100px;
    height: 50px;
    color: rgba(255, 255, 255, 0.618);
    font-weight: 900;
    background-color: rgb(251, 114, 153);
    line-height: 50px;
    text-align: center;
    border-radius: 30px;
    border: none;
    transition: all 0.618s;
}
#co:hover {
    background-color: rgb(101, 94, 252);
    color: rgba(0, 0, 0, 0.618);
}

#i {
    width: 200px;
    height: 200px;
    border-radius: 100px;
    background-image: url(https://img1.baidu.com/it/u=4205447136,2730860147&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=300);
    background-repeat: no-repeat;
    background-position: center center;
    background-size: cover;
    border: rgba(251, 114, 153, 0.5) 2px solid;
}

改动4对其他元素进行微调不演示

2.2.1 form提交文件

  • 由于上传文件按钮的样式难以更改所以我们这里改为一下这种方式
    • 用点击button代替点击上传文件按钮并且让上传文件按钮消失

在这里插入图片描述

后面搭配一段代码即可

提交form的post请求按钮

在这里插入图片描述

在这里插入图片描述

2.2.2 js代码

  1. 上传头像要在输入用户名后才能进行judge函数的非空校验

在这里插入图片描述

function judge() {
    var name = jQuery("#username");
    var password = jQuery("#password");

    if (name.val().trim() == "") {
        alert("请输入名字");
        name.focus();
        return;
    } else {
        javascript: $("input[name='file']").click();
        jQuery("#i").val("");
    }
}
  1. 确认按钮为form的方式去提交请求的所以跟js无关~
  2. 点击密码框显示头像
function getImage() {
    var name = jQuery("#username");
    var password = jQuery("#password");

    if (name.val().trim() == "") {
        alert("请输入名字");
        name.focus();
        return;
    }
    var keyValue = {
        name: name.val(),
        password: password.val(),
    };
    jQuery.ajax({
        type: "post",
        url: "image",
        contentType: "application/json; charset=utf8",
        data: JSON.stringify(keyValue),
        success: function (body) {
            if (body != "No") {
                jQuery("#i").css("background-image", "url(" + body + ")");
                jQuery("#i").val("");
            } else {
                jQuery("#i").css(
                    "background-image",
                    "url(https://img1.baidu.com/it/u=4205447136,2730860147&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=300)"
                );
                jQuery("#i").val("头像");
            }
        },
    });
}

在这里插入图片描述

  1. 提交注册

在这里插入图片描述

function reg() {
    var name = jQuery("#username");
    var password = jQuery("#password");
    if (name.val().trim() == "") {
        alert("清输入名字");
        name.focus();
        return;
    }
    if (password.val().trim() == "") {
        alert("清输入密码");
        password.focus();
        return;
    }
    var keyValue = {
        name: name.val(),
        password: password.val(),
    };

    jQuery.ajax({
        type: "post",
        url: "save",
        contentType: "application/json; charset=utf8",
        data: JSON.stringify(keyValue),
        success: function (body) {
            if (body == "No") {
                alert("用户存在");
                name.val("");
                password.val("");
                name.focus();
                jQuery("#i").css(
                    "background-image",
                    "url(https://img1.baidu.com/it/u=4205447136,2730860147&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=300)"
                );
            } else {
                alert("注册成功");
                window.location.href = "login.html";
            }
        },
    });
}

2.2.3 补充登录页头像显示

  • 原理一致~

在这里插入图片描述

3. 登录页面提供注册与忘记密码按钮

在这里插入图片描述

  • 源码直接在码云看就行了~

3.1 注册按钮

简单的跳转~

在这里插入图片描述

3.2 忘记密码

  • 忘记密码特别简单就是直接在数据库里拿到密码然后返回给输入框~
function toGetPassword() {
    var name = jQuery("#username");
    var password = jQuery("#password");
    if (name.val().trim() == "") {
        alert("请输入是谁");
        name.focus();
        return;
    }
    var keyValue = {
        name: name.val(),
        password: password.val(),
    };
    jQuery.ajax({
        type: "POST",
        url: "remind",
        contentType: "application/json; charset=utf8",
        data: JSON.stringify(keyValue),
        success: function (body) {
            if (body != "No") {
                jQuery("#password").val(body);
            } else {
                alert("不存在这个用户");
            }
        },
    });
}

后端中(新的servlet类 Remind)

@WebServlet("/remind")
public class Remind extends HttpServlet {

    ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = objectMapper.readValue(req.getInputStream(), User.class);
        resp.setContentType("text/html; charset=utf8");
        String name = user.name;
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/Loves?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("mmsszsd666");//这是俺的微信号欢迎添加相互学习
        try {
            Connection connection = dataSource.getConnection();
            String sql = "select * from users where name = '" + name + "';";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSet set = preparedStatement.executeQuery();
            if(set.next()) {
                resp.getWriter().write(set.getString("password"));
            }else {
                resp.getWriter().write("No");
            }
            set.close();
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

4. 测试

登录与退出登录测试

在这里插入图片描述

注册测试

在这里插入图片描述

重复注册测试

在这里插入图片描述


文章到此结束谢谢观看
可以叫我 小马我可能写的不好或者有错误但是一起加油鸭

表白墙即将到达尾声最后一步就是优化“甜言蜜语”的显示了

码云链接代码

敬请期待()V


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java