表白墙完善(数据库,前端,后端Servlet),再谈Cookie和Session。以及一个关于Cookie的练习小程序

狗哥不是甜妹 2024-06-29 14:33:01 阅读 76

目录

表白墙引入数据库 

再谈Cookie和session

得到Cookie

​编辑

设置Cooie

使用Cookie编写一个登入的小界面


表白墙引入数据库 

1.先引入数据库的依赖(驱动包),5.1.49

pom.xml中,在之前的两个之前,再去添加一个

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.49</version>

</dependency>

2.创建本地的数据库

create table messageWall(`from` varchar(20),`to` varchar(20),message varchar(1024));

3.之前的代码中有一段可以删掉了

//此处把消息保存到内存中(一旦重启服务器,内存数据就会消失了。更科学的做法,应该是保存到数据库里面)

private List<Message> messageList=new ArrayList<>();

这个代码需要删除,因为我们已经决定使用数据库去存储了,就不需要本地去存了。

 完整代码

import com.fasterxml.jackson.databind.ObjectMapper;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.sql.DataSource;

import java.io.IOException;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

class Message{

public String from;

public String to;

public String message;

@Override

public String toString() {

return "Message{" +

"from='" + from + '\'' +

", to='" + to + '\'' +

", message='" + message + '\'' +

'}';

}

}

@WebServlet("/message")

public class MessageServlet extends HttpServlet {

//首先要把一个json转化为java对象

private ObjectMapper objectMapper=new ObjectMapper();

//此处把消息保存到内存中(一旦重启服务器,内存数据就会消失了。更科学的做法,应该是保存到数据库里面)

private List<Message> messageList=new ArrayList<>();

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//1.需要能够读取请求body,转换成java对象

Message message=objectMapper.readValue(req.getInputStream(),Message.class);

//2.得到message之后,需要把message保存到服务器中

try {

save(message);

} catch (SQLException e) {

e.printStackTrace();

}

System.out.println("服务器收到message:"+message.toString());

//3.返回响应,(其实没啥大必要,主要是返回一个200ok就行,body可以没有)

resp.setStatus(200); //设置成功状态码,会更加清晰

resp.getWriter().write("ok");

}

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

List<Message>messageList= null;

try {

messageList = load();

} catch (SQLException e) {

e.printStackTrace();

}

//1.把内存中的这些Message,组织成json格式,返回到响应中

String respJson=objectMapper.writeValueAsString(messageList);

//这个代码十分关键,告诉浏览器,返回的响应的body是json格式(utf8编码)

resp.setContentType("application/json; charset=utf8");

resp.getWriter().write(respJson);

// 2.针对List/数组这种,jackon会自动把数据整理成json数组,里面每个对象,又会被jsckon转换成{}json对象(json对象属性名字,也是和Message类的成员名字对应的)

}

private void save(Message message) throws SQLException {

//通过jdbc从数据库中存储数据。

DataSource dataSource=new MysqlDataSource();

//useSSL=false 此处的SSL就是HTTPS中的加密方案

((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/message?characterEncoding=utf8&&useSSL=false");

((MysqlDataSource)dataSource).setUser("root");

((MysqlDataSource)dataSource).setPassword("lcl15604007179");

//2.建立链接

Connection connection=dataSource.getConnection();

//3.构造SQL

String sql="insert into messageWall values(?,?,?)";

PreparedStatement statement=connection.prepareStatement(sql);

statement.setString(1, message.from);

statement.setString(2, message.from);

statement.setString(3, message.from);

//4.执行SQL

statement.executeUpdate();

//5.释放资源,关闭连接

statement.close();

connection.close();

}

private List<Message> load() throws SQLException {

//通过jdbc,从数据库读取数据

//1。创建数据源

DataSource dataSource=new MysqlDataSource();

((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/message?characterEncoding=utf8&&useSSL=false");

((MysqlDataSource) dataSource).setUser("root");

((MysqlDataSource)dataSource).setPassword("lcl15604007179");

//2.建立连接

Connection connection= dataSource.getConnection();

//3.构造SQL

String sql="select *from messageWall";

PreparedStatement statement=connection.prepareStatement(sql);

//4.执行SQL

ResultSet resultSet= statement.executeQuery();

//5.遍历结果集合

List <Message> messageList=new ArrayList<>();

while (resultSet.next()){

Message message=new Message();

message.from=resultSet.getString("from");

message.to=resultSet.getString("to");

message.message=resultSet.getString("message");

messageList.add(message);

}

//关闭连接,释放资源

resultSet.close();

statement.close();

connection.close();

return messageList;

}

}

我们可以知道,表白墙上的东西,即使你关闭服务器,我们的数据也是保存的,这也是游戏停服了但是你的数据不丢失的原因。

再谈Cookie和session

Cookie是浏览器在本地持久化存储数据的一种机制

1.Cookie的数据从哪里来?

服务器返回给浏览器的

2.Cookie的数据长什么样子?

Cookie中是键值对结构的数据,并且这里的键值对都是程序员自定义的。

3.Cookie有什么用

Cookie可以在浏览器这边存储一些临时性数据

其中最典型的一种使用方式,就是用来存储“身份标识”

sessionId->Cookie和Session之间的联动了

4.Cookie到哪里去

Cookie的内容会在下次访问该网站的时候,自动被带到HTTP请求中

5.Cookie怎么存储的

浏览器按照不同的域名分别存储Cookie域名和域名之间不能打扰。

Cookie存储在硬盘上的

Cookie存储往往会有一个超时时间(看浏览器不同而定,支付宝很短,安全)

得到Cookie

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/getcookie")

public class GetCookieServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

Cookie[] cookies = req.getCookies();

if (cookies != null) {

for (Cookie cookie : cookies) {

System.out.println(cookie.getName() + ":" + cookie.getValue());

}

} else {

resp.getWriter().write("当前请求中没有cookie");

}

resp.getWriter().write("ok");

}

}

设置Cooie

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/setcookie")

public class SetCookieServlet extends HttpServlet {

//期望通过doGet方法,把一个自定义的cookie数据返回到浏览器这边。

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

Cookie cookie=new Cookie("date","2023-09-23");

resp.addCookie(cookie);

Cookie cookie1=new Cookie("time","19:55");

resp.addCookie(cookie1);

resp.getWriter().write("setCookie ok");

}

}

我们需要是先设置Cookie之后,就可以此时拿到Cookie的内容,当然Cookie里面的数据,只是在浏览器休息休息,真正发挥作用,还是得在服务器这边的逻辑生效的。

Cookie结合Session实现登入效果,此时就能更清楚的看出来

sessionId是一个广义的概念,不同的库中具体实现过程会有一些细节的差异,在Servlet里,把这个属性具体叫做JSESSIONID

getSession背后做的事情(会话,就相当于账户,用户和服务器的交流,之前有没有这个账户)

1.读取请求中的Cookie,看Cookie里面是否有JESSIONID属性,以及值是什么,如果没有,就认为需要创建新的会话,如果有,就拿着这个ID去查询当前的session是否存在

要是session存在,就直接返回该session

要是session不存在,就准备创建新的会话。

2.如果当前确实需要创建会话,就会创建一个Session对象,同时生成唯一的一个JESSIONID,以JSESSIONID为key,SESSION对象为value,把这个键值对插入到服务器上述的哈希表中

3.刚才生成的JESSIONID又会通过addCookie方法,加入到响应中,此时响应里就会带有Set-Cookie字段,这里的值就是JSEEION=xxxxxxx通过响应,就把JSESSIOID返回到浏览器这边了。

这一行小小的,能量大大的🙉🙉🙉

HttpSession session=req.getSession(true);

问题1:什么情况会有sessionId但是没有session呢

服务器这边存的session对象也是在内存中进行的

比如把sessionId返回给浏览器了,sessionId和session对象是保存在服务器内存的,此时如果服务器重启了,内存中这些会话数据就没了,但是浏览器中的Cookie还是存在的

session存在内存中不太合理,实践中往往会把这种会话保存到其他介质上,来达到持久化存储目的(mysql,redis)

使用Cookie编写一个登入的小界面

简单的一个小的前端代码

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Document</title>

</head>

<form action="login" method="post">

<input type="text" name="username">

<input type="password" name="password">

<input type="submit" value="登入">

<!-- 当前页面是一个form表单-->

</form>

</body>

</html>

后端的登入代码编写

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import java.io.IOException;

@WebServlet("/index")

public class indexServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//先验证用户的登入状态,如果未登入,就要求用户要先登入一下

HttpSession session=req.getSession(false);

if(session==null){

//用户尚未登入

resp.setContentType("text/html;charset=utf8");

resp.getWriter().write("请先登入,再访问主页");

return;

}

//已经登入成功了

//就可以取出之前的attribute

String username=(String) session.getAttribute("username");

Long time=(Long) session.getAttribute("time");

System.out.println("username="+username+",time"+time);

//根据这样的内容构造页面

resp.setContentType("text/html;charset=utf8");

resp.getWriter().write("欢迎您,"+username+"!上次登入时间"+time);

}

}

重定向的内容编写 

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import java.io.IOException;

@WebServlet("/login")

public class LoginServlet extends HttpServlet {

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//1.获取到用户名和密码

String username = req.getParameter("username");

String password = req.getParameter("password");

if (username == null || password == null || username.equals("") || password.equals("")) {

resp.setContentType("text/html;charset=utf8");

resp.getWriter().write("请求的参数不完整");

return;

}

//2.验证用户密码是否正确

//正常的验证,是从数据库读取数据

//注册账号就会给数据库插入用户名和密码,登入的时候就是验证当前用户名是否存在,以及密码是否匹配

//当前为了简单,先不引入数据库,直接通过硬编码的方式来判定用户名和密码

//此处约定,合法的用户名是:zhangsan,密码:123

if (!username.equals("zhangsan")) {

resp.setContentType("text/html;charset=utf8");

resp.getWriter().write("用户名错误!");

return;

}

if (!password.equals("123")) {

resp.setContentType("text/html;charset=utf8");

resp.getWriter().write("密码错误");

return;

}

//3.登入成功了,此时可以给这个用户创建会话(就是这个人在不在账户上)

HttpSession session = req.getSession(true);

//会话总,可以顺便保存点自定义的数据,比如保存一个登入的时间戳

//setAttribute后面的value是个Object,想要存什么都可以!!

session.setAttribute("username", username);

session.setAttribute("time", System.currentTimeMillis());

//4.让页面自动跳转到网站主页

//此处约定的路径是index(使用Servlet生成一个动态页面)

resp.sendRedirect("index");

}

}

当前程序设计三个部分进行联动——以下是登入成功的效果

1.登入界面(静态的html,使用form构造http请求)

2.LoginServlet(doPost处理登入的逻辑流程 1234)

3.IndexServlet(doGet处理主页的生成)



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。