因为HTTP是无状态的协议,无法根据之前的状态进行本次的请求处理
为了保留无状态协议这个特征,于是引入了 Cookie 信息来控制客户端的状态.
Cookie会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie.当下次再给该服务器发送请求的时候,客户端会自动在请求报文中加入Cookie值后发送出去.
服务器端发现客户端发送来的 Cookie 后,会去检查是哪一个客户端发来的连接请求,对比服务器上的记录,最后得到之前的状态信息.
此时在服务器这边就需要记录Cookie信息, 这个就是 Session 机制所做的工作
Session 译为 会话 .Session是存储在服务端的,当客户端第一次访问服务端的时候,服务端会把客户端的信息存储在服务器上,当客户端再次访问的时候,就可以通过 Session中查找该客户端的状态就可以了.存储的方式类似于 哈希表.
- Cookie 是保存在 客户端, Session 是保存在 服务端
- Cookie 不安全
- 单个Cookie保存的数据不能超过 4k
- Cookie 和 Session 经常会在一起配合使用. 但是不是必须配合
方法 | 描述 |
---|---|
HttpSession getSession() | 在服务器中获取会话. 参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null |
Cookie[] getCookies() | 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对. |
方法 | 描述 |
---|---|
void addCookie(Cookie cookie) | 把指定的 cookie 添加到响应中. |
方法 | 描述 |
---|---|
Object getAttribute(String name) | 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null. |
void setAttribute(String name, Object value) | 该方法使用指定的名称绑定一个对象到该 session 会话 |
boolean isNew() | 判定当前是否是新创建出的会话 |
方法 | 描述 |
---|---|
String getName() | 该方法返回 cookie 的名称。名称在创建后不能改变。(这个值是 SetCooke 字段设置给浏览器的) |
String getValue() | 该方法获取与 cookie 关联的值 |
void setValue(String newValue) | 该方法设置与 cookie 关联的值。 |
HttpServletRequest.getCookies()
获取到请求中的一系列 Cookie 键值对.需要带有参数true
的时候, 如果 session 不存在,就会创建,如果存在,就获取session然后返回false
的时候,如果 session 不存在,就会返回null,如果存在,就获取session然后返回key
和 value
两个属性创建 webapp/WEB-INF/web.xml
web.xml
DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
web-app>
客户端给服务器第一次交互, 登录请求
登录账号,之后重定向到第二次交互
此时重定向到第二次交互,访问主页
login.html
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>Documenttitle>
<link rel="stylesheet" href="css/common.css">
<link rel="stylesheet" href="css/login.css">
head>
<body>
<div id="leader">
<div class="login">
<form action="login" method="POST">
<div class="title">某某管理系统div>
<div class="one"><input type="text" name="username" class="user"><input type="password" name="password" class="password">div>
<div class="submit"><button>登 录button>div>
form>
div>
div>
body>
html>
common.css
* {
padding: 0;
margin: 0;
}
html,body {
width: 100%;
height: 100%;
}
login.css
#leader{
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.login {
background-color: pink;
width: 400px;
height: 290px;
padding: 25px;
border-radius: 10px;
}
.login .title{
font-size: 30px;
font-weight: 600;
text-align: center;
margin: 5px;
}
.login .one{
display: flex;
flex-direction: column;
align-items: center;
}
.login .user,.login .password {
width: 380px;
height: 35px;
margin: 10px;
border-radius: 8px;
padding: 5px;
border: none;
}
.login .submit{
margin: 10px;
}
.login .submit button{
display: block;
margin: 0 auto;
width: 100px;
height: 50px;
background-color: orange;
color: white;
border-radius: 5px;
border: 0;
}
.login .submit button:active{
background-color: red;
}
这里是账号密码是直接固定好了
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 {
resp.setContentType("text/html;charset=utf-8");
// 1. 先从请求的body中读取 用户名 和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2. 判定 用户名密码 是否正确(这里直接固定)
if(!"wz".equals(username) || !"123456".equals(password)){
// 用户名和密码有错误的
resp.getWriter().write("登录失败!");
return;
}
// 3. 登录成功,则创建一个会话出来.
HttpSession httpSession = req.getSession(true);
httpSession.setAttribute("username","wz");
httpSession.setAttribute("loginCount",0);
// 4. 让页面跳转到主页,使用重定向
resp.sendRedirect("index");
}
}
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 {
// 根据当前用户请求中的 sessionId, 获取到用户信息,并显示到页面上
resp.setContentType("text/html;charset=utf-8");
// 1. 判定当前用户是否已经登录了.
HttpSession httpSession = req.getSession(false);//这里如果不存在就不需要创建.
if(httpSession == null){
resp.sendRedirect("login.html");
return;
}
// 2. 如果已经登录,就可以从 HttpSession 中拿到用户信息了
String username = (String) (httpSession.getAttribute("username"));
Integer loginCount = (Integer) (httpSession.getAttribute("loginCount"));
loginCount = loginCount + 1;
httpSession.setAttribute("loginCount",loginCount);
// 3. 返回一个 HTML 页面
StringBuilder html = new StringBuilder();
html.append("用户: "+username+"");
html.append("访问次数: "+loginCount+"");
resp.getWriter().write(html.toString());
}
}
首先浏览器输入 http://127.0.0.1:8080/ForLogin/login.html
输入 "wz" "123456"
在刷新页面的时候,会增加访问次数