JavaWeb核心技术之会话技术SessionAndCookie

@WebServlet(“/aServlet”)

public class AServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//发送Cookie

String value = “张三”;

//对中文进行URL编码

value = URLEncoder.encode(value, “UTF-8”);

System.out.println(“存储数据:”+value);

//将编码后的值存入Cookie中

Cookie cookie = new Cookie(“username”,value);

//设置存活时间 ,1周 7天

cookie.setMaxAge(606024*7);

//2. 发送Cookie,response

response.addCookie(cookie);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(2)在BServlet中获取值,并对值进行解码

@WebServlet(“/bServlet”)

public class BServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//获取Cookie

//1. 获取Cookie数组

Cookie[] cookies = request.getCookies();

//2. 遍历数组

for (Cookie cookie : cookies) {

//3. 获取数据

String name = cookie.getName();

if(“username”.equals(name)){

String value = cookie.getValue();//获取的是URL编码后的值 %E5%BC%A0%E4%B8%89

//URL解码

value = URLDecoder.decode(value,“UTF-8”);

System.out.println(name+“:”+value);//value解码后为 张三

break;

}

}

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

至此,我们就可以将中文存入Cookie中进行使用。

小结

Cookie的使用细节中,我们讲了Cookie的存活时间存储中文:

  • 存活时间,需要掌握setMaxAage()API的使用

  • 存储中文,需要掌握URL编码和解码的使用

3,Session


Cookie已经能完成一次会话多次请求之间的数据共享,之前我们还提到过Session也可以实现,那么:

  • 什么是Session?

  • Session如何来使用?

  • Session是如何实现的?

  • Session的使用注意事项有哪些?

3.1 Session的基本使用

1.概念

Session:服务端会话跟踪技术:将数据保存到服务端。

  • Session是存储在服务端而Cookie是存储在客户端

  • 存储在客户端的数据容易被窃取和截获,存在很多不安全的因素

  • 存储在服务端的数据相比于客户端来说就更安全

2.Session的工作流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fyZsY3ox-1642765422108)(assets/1629427173389.png)]

  • 在服务端的AServlet获取一个Session对象,把数据存入其中

  • 在服务端的BServlet获取到相同的Session对象,从中取出数据

  • 就可以实现一次会话中多次请求之间的数据共享了

  • 现在最大的问题是如何保证AServlet和BServlet使用的是同一个Session对象(在原理分析会讲解)?

3.Session的基本使用

在JavaEE中提供了HttpSession接口,来实现一次会话的多次请求之间数据共享功能。

具体的使用步骤为:

  • 获取Session对象,使用的是request对象

HttpSession session = request.getSession();

  • Session对象提供的功能:

  • 存储数据到 session 域中

void setAttribute(String name, Object o)

  • 根据 key,获取值

Object getAttribute(String name)

  • 根据 key,删除该键值对

void removeAttribute(String name)

介绍完Session相关的API后,接下来通过一个案例来完成对Session的使用,具体实现步骤为:

需求:在一个Servlet中往Session中存入数据,在另一个Servlet中获取Session中存入的数据

1.创建名为SessionDemo1的Servlet类

2.创建名为SessionDemo2的Servlet类

3.在SessionDemo1的方法中:获取Session对象、存储数据

4.在SessionDemo2的方法中:获取Session对象、获取数据

5.启动测试

(1)创建名为SessionDemo1的Servlet类

@WebServlet(“/demo1”)

public class SessionDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(2)创建名为SessionDemo2的Servlet类

@WebServlet(“/demo2”)

public class SessionDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(3)SessionDemo1:获取Session对象、存储数据

@WebServlet(“/demo1”)

public class SessionDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//存储到Session中

//1. 获取Session对象

HttpSession session = request.getSession();

//2. 存储数据

session.setAttribute(“username”,“zs”);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(4)SessionDemo2:获取Session对象、获取数据

@WebServlet(“/demo2”)

public class SessionDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//获取数据,从session中

//1. 获取Session对象

HttpSession session = request.getSession();

//2. 获取数据

Object username = session.getAttribute(“username”);

System.out.println(username);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(5)启动测试,

  • 先访问http://localhost:8080/cookie-demo/demo1,将数据存入Session

  • 在访问http://localhost:8080/cookie-demo/demo2,从Session中获取数据

  • 查看控制台

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Fhxq3fD-1642765422108)(assets/1629428292373.png)]

通过案例的效果,能看到Session是能够在一次会话中两次请求之间共享数据。

小结

至此Session的基本使用就已经完成了,重点要掌握的是:

  • Session的获取

HttpSession session = request.getSession();

  • Session常用方法的使用

void setAttribute(String name, Object o)

Object getAttribute(String name)

**注意:**Session中可以存储的是一个Object类型的数据,也就是说Session中可以存储任意数据类型。

介绍完Session的基本使用之后,那么Session的底层到底是如何实现一次会话两次请求之间的数据共享呢?

3.2 Session的原理分析

  • Session是基于Cookie实现的

这句话其实不太能详细的说明Session的底层实现,接下来,咱们一步步来分析下Session的具体实现原理:

(1)前提条件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-evNAy5aA-1642765422108)(assets/1629429063101.png)]

Session要想实现一次会话多次请求之间的数据共享,就必须要保证多次请求获取Session的对象是同一个。

那么它们是一个对象么?要验证这个结论也很简单,只需要在上面案例中的两个Servlet中分别打印下Session对象

SessionDemo1

@WebServlet(“/demo1”)

public class SessionDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//存储到Session中

//1. 获取Session对象

HttpSession session = request.getSession();

System.out.println(session);

//2. 存储数据

session.setAttribute(“username”,“zs”);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

SessionDemo2

@WebServlet(“/demo2”)

public class SessionDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//获取数据,从session中

//1. 获取Session对象

HttpSession session = request.getSession();

System.out.println(session);

//2. 获取数据

Object username = session.getAttribute(“username”);

System.out.println(username);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

启动测试,分别访问

http://localhost:8080/cookie-demo/demo1

http://localhost:8080/cookie-demo/demo2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IUmNcCwU-1642765422109)(assets/1629429239409.png)]

通过打印可以得到如下结论:

  • 两个Servlet类中获取的Session对象是同一个

  • 把demo1和demo2请求刷新多次,控制台最终打印的结果都是同一个

那么问题又来了,如果新开一个浏览器,访问demo1或者demo2,打印在控制台的Session还是同一个对象么?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-llPVacGN-1642765422109)(assets/1629429788264.png)]

注意:在一台电脑上演示的时候,如果是相同的浏览器必须要把浏览器全部关掉重新打开,才算新开的一个浏览器。

当然也可以使用不同的浏览器进行测试,就不需要把之前的浏览器全部关闭。

测试的结果:如果是不同浏览器或者重新打开浏览器后,打印的Session就不一样了。

所以Session实现的也是一次会话中的多次请求之间的数据共享。

那么最主要的问题就来了,Session是如何保证在一次会话中获取的Session对象是同一个呢?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e6cNqxf2-1642765422109)(assets/1629430754825.png)]

(1)demo1在第一次获取session对象的时候,session对象会有一个唯一的标识,假如是id:10

(2)demo1在session中存入其他数据并处理完成所有业务后,需要通过Tomcat服务器响应结果给浏览器

(3)Tomcat服务器发现业务处理中使用了session对象,就会把session的唯一标识id:10当做一个cookie,添加Set-Cookie:JESSIONID=10到响应头中,并响应给浏览器

(4)浏览器接收到响应结果后,会把响应头中的coookie数据存储到浏览器的内存中

(5)浏览器在同一会话中访问demo2的时候,会把cookie中的数据按照cookie: JESSIONID=10的格式添加到请求头中并发送给服务器Tomcat

(6)demo2获取到请求后,从请求头中就读取cookie中的JSESSIONID值为10,然后就会到服务器内存中寻找id:10的session对象,如果找到了,就直接返回该对象,如果没有则新创建一个session对象

(7)关闭打开浏览器后,因为浏览器的cookie已被销毁,所以就没有JESSIONID的数据,服务端获取到的session就是一个全新的session对象

至此,Session是基于Cookie来实现的这就话,我们就解释完了,接下来通过实例来演示下:

(1)使用chrome浏览器访问http://localhost:8080/cookie-demo/demo1,打开开发者模式(F12或Ctrl+Shift+I),查看==响应头(Response Headers)==数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gPbAIJGP-1642765422109)(assets/1629430891071.png)]

(2)使用chrome浏览器再次访问http://localhost:8080/cookie-demo/demo2,查看==请求头(Request Headers)==数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pws7iSn-1642765422110)(assets/1629431299195.png)]

小结

介绍完Session的原理,我们只需要记住

  • Session是基于Cookie来实现的

3.3 Session的使用细节

这节我们会主要讲解两个知识,第一个是Session的钝化和活化,第二个是Session的销毁,首先来学习什么是Session的钝化和活化?

3.3.1 Session钝化与活化

首先需要大家思考的问题是:

  • 服务器重启后,Session中的数据是否还在?

要想回答这个问题,我们可以先看下下面这幅图,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v5rYcmMl-1642765422110)(assets/1629438984314.png)]

(1)服务器端AServlet和BServlet共用的session对象应该是存储在服务器的内存中

(2)服务器重新启动后,内存中的数据应该是已经被释放,对象也应该都销毁了

所以session数据应该也已经不存在了。但是如果session不存在会引发什么问题呢?

举个例子说明下,

(1)用户把需要购买的商品添加到购物车,因为要实现同一个会话多次请求数据共享,所以假设把数据存入Session对象中

(2)用户正要付钱的时候接到一个电话,付钱的动作就搁浅了

(3)正在用户打电话的时候,购物网站因为某些原因需要重启

(4)重启后session数据被销毁,购物车中的商品信息也就会随之而消失

(5)用户想再次发起支付,就会出为问题

所以说对于session的数据,我们应该做到就算服务器重启了,也应该能把数据保存下来才对。

分析了这么多,那么Tomcat服务器在重启的时候,session数据到底会不会保存以及是如何保存的,我们可以通过实际案例来演示下:

注意:这里所说的关闭和启动应该要确保是正常的关闭和启动。

那如何才是正常关闭Tomcat服务器呢?

需要使用命令行的方式来启动和停止Tomcat服务器:

启动:进入到项目pom.xml所在目录,执行tomcat7:run

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bbRtkOVG-1642765422110)(assets/1629439800328.png)]

停止:在启动的命令行界面,输入ctrl+c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dYAex4wH-1642765422111)(assets/1629439879596.png)]

有了上述两个正常启动和关闭的方式后,接下来的测试流程是:

(1)先启动Tomcat服务器

(2)访问http://localhost:8080/cookie-demo/demo1将数据存入session中

(3)正确停止Tomcat服务器

(4)再次重新启动Tomcat服务器

(5)访问http://localhost:8080/cookie-demo/demo2 查看是否能获取到session中的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nvLJSfjT-1642765422111)(assets/1629440018238.png)]

经过测试,会发现只要服务器是正常关闭和启动,session中的数据是可以被保存下来的。

那么Tomcat服务器到底是如何做到的呢?

具体的原因就是:Session的钝化和活化:

  • 钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中

  • 钝化的数据路径为:项目目录\target\tomcat\work\Tomcat\localhost\项目名称\SESSIONS.ser

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wHdEoiMM-1642765422111)(assets/1629440576828.png)]

  • 活化:再次启动服务器后,从文件中加载数据到Session中

  • 数据加载到Session中后,路径中的SESSIONS.ser文件会被删除掉

对于上述的整个过程,大家只需要了解下即可。因为所有的过程都是Tomcat自己完成的,不需要我们参与。

小结

Session的钝化和活化介绍完后,需要我们注意的是:

  • session数据存储在服务端,服务器重启后,session数据会被保存

  • 浏览器被关闭启动后,重新建立的连接就已经是一个全新的会话,获取的session数据也是一个新的对象

  • session的数据要想共享,浏览器不能关闭,所以session数据不能长期保存数据

  • cookie是存储在客户端,是可以长期保存

3.3.2 Session销毁

session的销毁会有两种方式:

  • 默认情况下,无操作,30分钟自动销毁

  • 对于这个失效时间,是可以通过配置进行修改的

  • 在项目的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”>

100

  • 如果没有配置,默认是30分钟,默认值是在Tomcat的web.xml配置文件中写死的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gPTkV1W-1642765422111)(assets/1629441687613.png)]

  • 调用Session对象的invalidate()进行销毁

  • 在SessionDemo2类中添加session销毁的方法

@WebServlet(“/demo2”)

public class SessionDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//获取数据,从session中

//1. 获取Session对象

HttpSession session = request.getSession();

System.out.println(session);

// 销毁

session.invalidate();

//2. 获取数据

Object username = session.getAttribute(“username”);

System.out.println(username);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

  • 启动访问测试,先访问demo1将数据存入到session,再次访问demo2从session中获取数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eipjn8yU-1642765422112)(assets/1629441900843.png)]

  • 该销毁方法一般会在用户退出的时候,需要将session销毁掉。

Cookie和Session小结

  • Cookie 和 Session 都是来完成一次会话内多次请求间数据共享的。

所需两个对象放在一块,就需要思考:

Cookie和Session的区别是什么?

Cookie和Session的应用场景分别是什么?

  • 区别:

  • 存储位置:Cookie 是将数据存储在客户端,Session 将数据存储在服务端

  • 安全性:Cookie不安全,Session安全

  • 数据大小:Cookie最大3KB,Session无大小限制

  • 存储时间:Cookie可以通过setMaxAge()长期存储,Session默认30分钟

  • 服务器性能:Cookie不占服务器资源,Session占用服务器资源

  • 应用场景:

  • 购物车:使用Cookie来存储

  • 以登录用户的名称展示:使用Session来存储

  • 记住我功能:使用Cookie来存储

  • 验证码:使用session来存储

  • 结论

  • Cookie是用来保证用户在未登录情况下的身份识别

  • Session是用来保存用户登录后的数据

介绍完Cookie和Session以后,具体用哪个还是需要根据具体的业务进行具体分析。

4,用户登录注册案例


4.1 需求分析

需求说明:

  1. 完成用户登录功能,如果用户勾选“记住用户” ,则下次访问登录页面自动填充用户名密码

  2. 完成注册功能,并实现验证码功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0WM82AxR-1642765422112)(assets/1629442826981.png)]

4.2 用户登录功能

  1. 需求:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ysIIC1k8-1642765422112)(assets/1629443152010.png)]

  • 用户登录成功后,跳转到列表页面,并在页面上展示当前登录的用户名称

  • 用户登录失败后,跳转回登录页面,并在页面上展示对应的错误信息

  1. 实现流程分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4jbD6p1y-1642765422112)(assets/1629443379531.png)]

(1)前端通过表单发送请求和数据给Web层的LoginServlet

(2)在LoginServlet中接收请求和数据[用户名和密码]

(3)LoginServlet接收到请求和数据后,调用Service层完成根据用户名和密码查询用户对象

(4)在Service层需要编写UserService类,在类中实现login方法,方法中调用Dao层的UserMapper

(5)在UserMapper接口中,声明一个根据用户名和密码查询用户信息的方法

(6)Dao层把数据查询出来以后,将返回数据封装到User对象,将对象交给Service层

(7)Service层将数据返回给Web层

(8)Web层获取到User对象后,判断User对象,如果为Null,则将错误信息响应给登录页面,如果不为Null,则跳转到列表页面,并把当前登录用户的信息存入Session携带到列表页面。

  1. 具体实现

(1)完成Dao层的代码编写

(1.1)将04-资料\1. 登录注册案例\2. MyBatis环境\UserMapper.java放到com.itheima.mapper`包下:

public interface UserMapper {

/**

  • 根据用户名和密码查询用户对象

  • @param username

  • @param password

  • @return

*/

@Select(“select * from tb_user where username = #{username} and password = #{password}”)

User select(@Param(“username”) String username,@Param(“password”) String password);

/**

  • 根据用户名查询用户对象

  • @param username

  • @return

*/

@Select(“select * from tb_user where username = #{username}”)

User selectByUsername(String username);

/**

  • 添加用户

  • @param user

*/

@Insert(“insert into tb_user values(null,#{username},#{password})”)

void add(User user);

}

(1.2)将04-资料\1. 登录注册案例\2. MyBatis环境\User.java放到com.itheima.pojo包下:

public class User {

private Integer id;

private String username;

private String password;

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

@Override

public String toString() {

return “User{” +

“id=” + id +

“, username='” + username + ‘’’ +

“, password='” + password + ‘’’ +

‘}’;

}

}

(1.3)将04-资料\1. 登录注册案例\2. MyBatis环境\UserMapper.xml放入到resources/com/itheima/mapper`目录下:

<?xml version="1.0" encoding="UTF-8" ?>

(2)完成Service层的代码编写

(2.1)在com.itheima.service包下,创建UserService类

public class UserService {

//1.使用工具类获取SqlSessionFactory

SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();

/**

  • 登录方法

  • @param username

  • @param password

  • @return

*/

public User login(String username,String password){

//2. 获取SqlSession

SqlSession sqlSession = factory.openSession();

//3. 获取UserMapper

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

//4. 调用方法

User user = mapper.select(username, password);

//释放资源

sqlSession.close();

return user;

}

}

(3)完成页面和Web层的代码编写

(3.1)将04-资料\1. 登录注册案例\1. 静态页面拷贝到项目的webapp目录下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgrRxxh6-1642765422113)(assets/1629444649629.png)]

(3.2)将login.html内容修改成login.jsp

<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

login

LOGIN IN

用户名或密码不正确

Username:

Password:

Remember:

   

没有账号?

(3.3)创建LoginServlet类

@WebServlet(“/loginServlet”)

public class LoginServlet extends HttpServlet {

private UserService service = new UserService();

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

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

String username = request.getParameter(“username”);

String password = request.getParameter(“password”);

//2. 调用service查询

User user = service.login(username, password);

//3. 判断

if(user != null){

//登录成功,跳转到查询所有的BrandServlet

//将登陆成功后的user对象,存储到session

HttpSession session = request.getSession();

session.setAttribute(“user”,user);

String contextPath = request.getContextPath();

response.sendRedirect(contextPath+“/selectAllServlet”);

}else {

// 登录失败,

// 存储错误信息到request

request.setAttribute(“login_msg”,“用户名或密码错误”);

// 跳转到login.jsp

request.getRequestDispatcher(“/login.jsp”).forward(request,response);

}

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(3.4)在brand.jsp中标签下添加欢迎当前用户的提示信息:

${user.username},欢迎您

(3.5) 修改login.jsp,将错误信息使用EL表达式来获取

修改前内容:

用户名或密码不正确

修改后内容:

${login_msg}

(4)启动,访问测试

(4.1) 进入登录页面,输入错误的用户名或密码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qkvlwkRu-1642765422113)(assets/1629445376407.png)]

(4.2)输入正确的用户和密码信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vgT7ZUqb-1642765422113)(assets/1629445415216.png)]

小结

  • 在LoginServlet中,将登录成功的用户数据存入session中,方法在列表页面中获取当前登录用户信息进行展示

  • 在LoginServlet中,将登录失败的错误信息存入到request中,如果存入到session中就会出现这次会话的所有请求都有登录失败的错误信息,这个是不需要的,所以不用存入到session中

4.3 记住我-设置Cookie

  1. 需求:

如果用户勾选“记住用户” ,则下次访问登陆页面自动填充用户名密码。这样可以提升用户的体验。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AnSHK3fd-1642765422113)(assets/1629445835281.png)]

对应上面这个需求,最大的问题就是: 如何自动填充用户名和密码?

  1. 实现流程分析

因为记住我功能要实现的效果是,就算用户把浏览器关闭过几天再来访问也能自动填充,所以需要将登陆信息存入一个可以长久保存,并且能够在浏览器关闭重新启动后依然有效的地方,就是我们前面讲的Cookie,所以:

  • 将用户名和密码写入Cookie中,并且持久化存储Cookie,下次访问浏览器会自动携带Cookie

  • 在页面获取Cookie数据后,设置到用户名和密码框中

  • 何时写入Cookie?

  • 用户必须登陆成功后才需要写

  • 用户必须在登录页面勾选了记住我的复选框

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2qbl7W3o-1642765422114)(assets/1629446248511.png)]

(1)前端需要在发送请求和数据的时候,多携带一个用户是否勾选Remember的数据

(2)LoginServlet获取到数据后,调用Service完成用户名和密码的判定

(3)登录成功,并且用户在前端勾选了记住我,需要往Cookie中写入用户名和密码的数据,并设置Cookie存活时间

(4)设置成功后,将数据响应给前端

  1. 具体实现

(1)在login.jsp为复选框设置值

<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

login

LOGIN IN

${login_msg}

Username:

Password:

Remember:

   

没有账号?

(2)在LoginServlet获取复选框的值并在登录成功后进行设置Cookie

@WebServlet(“/loginServlet”)

public class LoginServlet extends HttpServlet {

private UserService service = new UserService();

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

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

String username = request.getParameter(“username”);

String password = request.getParameter(“password”);

//获取复选框数据

String remember = request.getParameter(“remember”);

//2. 调用service查询

User user = service.login(username, password);

//3. 判断

if(user != null){

//登录成功,跳转到查询所有的BrandServlet

//判断用户是否勾选记住我,字符串写前面是为了避免出现空指针异常

if(“1”.equals(remember)){

//勾选了,发送Cookie

//1. 创建Cookie对象

Cookie c_username = new Cookie(“username”,username);

Cookie c_password = new Cookie(“password”,password);

// 设置Cookie的存活时间

c_username.setMaxAge( 60 * 60 * 24 * 7);

c_password.setMaxAge( 60 * 60 * 24 * 7);

//2. 发送

response.addCookie(c_username);

response.addCookie(c_password);

}

//将登陆成功后的user对象,存储到session

HttpSession session = request.getSession();

session.setAttribute(“user”,user);

String contextPath = request.getContextPath();

response.sendRedirect(contextPath+“/selectAllServlet”);

}else {

// 登录失败,

// 存储错误信息到request

request.setAttribute(“login_msg”,“用户名或密码错误”);

// 跳转到login.jsp

request.getRequestDispatcher(“/login.jsp”).forward(request,response);

}

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(3)启动访问测试,

只有当前用户名和密码输入正确,并且勾选了Remeber的复选框,在响应头中才可以看得cookie的相关数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qENpxCwh-1642765422114)(assets/1629447232217.png)]

4.4 记住我-获取Cookie

  1. 需求

登录成功并勾选了Remeber后,后端返回给前端的Cookie数据就已经存储好了,接下来就需要在页面获取Cookie中的数据,并把数据设置到登录页面的用户名和密码框中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-766th7XJ-1642765422115)(assets/1629449100282.png)]

如何在页面直接获取Cookie中的值呢?

  1. 实现流程分析

在页面可以使用EL表达式,${cookie.key.value}

key:指的是存储在cookie中的键名称

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v6Lt3MkX-1642765422115)(assets/1629449234735.png)]

(1)在login.jsp用户名的表单输入框使用value值给表单元素添加默认值,value可以使用${cookie.username.value}

(2)在login.jsp密码的表单输入框使用value值给表单元素添加默认值,value可以使用${cookie.password.value}

  1. 具体实现

(1)修改login.jsp页面

<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

login

LOGIN IN

${login_msg}

Username:

Password:

Remember:

   

没有账号?

  1. 访问测试,重新访问登录页面,就可以看得用户和密码已经被填充。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qOhIs4TA-1642765422115)(assets/1629449530886.png)]

4.5 用户注册功能

  1. 需求
  • 注册功能:保存用户信息到数据库

  • 验证码功能

  • 展示验证码:展示验证码图片,并可以点击切换

  • 校验验证码:验证码填写不正确,则注册失败

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y9qFMGqB-1642765422115)(assets/1629449648793.png)]

  1. 实现流程分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xhm3q5ya-1642765422116)(assets/1629449720005.png)]

(1)前端通过表单发送请求和数据给Web层的RegisterServlet

(2)在RegisterServlet中接收请求和数据[用户名和密码]

(3)RegisterServlet接收到请求和数据后,调用Service层完成用户信息的保存

(4)在Service层需要编写UserService类,在类中实现register方法,需要判断用户是否已经存在,如果不存在,则完成用户数据的保存

(5)在UserMapper接口中,声明两个方法,一个是根据用户名查询用户信息方法,另一个是保存用户信息方法

(6)在UserService类中保存成功则返回true,失败则返回false,将数据返回给Web层

(7)Web层获取到结果后,如果返回的是true,则提示注册成功,并转发到登录页面,如果返回false则提示用户名已存在并转发到注册页面

  1. 具体实现

(1)Dao层代码参考资料中的内容完成

(2)编写Service层代码

public class UserService {

//1.使用工具类获取SqlSessionFactory

SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();

/**

  • 注册方法

  • @return

*/

public boolean register(User user){

//2. 获取SqlSession

SqlSession sqlSession = factory.openSession();

//3. 获取UserMapper

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

//4. 判断用户名是否存在

User u = mapper.selectByUsername(user.getUsername());

if(u == null){

// 用户名不存在,注册

mapper.add(user);

sqlSession.commit();

}

sqlSession.close();

return u == null;

}

}

(3)完成页面和Web层的代码编写

(3.1)将register.html内容修改成register.jsp

<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

欢迎注册

欢迎注册

已有帐号? 登录

用户名

用户名不太受欢迎

密码

密码格式有误

验证码

看不清?


(3.2)编写RegisterServlet

@WebServlet(“/registerServlet”)

public class RegisterServlet extends HttpServlet {

private UserService service = new UserService();

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//1. 获取用户名和密码数据

String username = request.getParameter(“username”);

String password = request.getParameter(“password”);

User user = new User();

user.setUsername(username);

user.setPassword(password);

//2. 调用service 注册

boolean flag = service.register(user);

《MySql面试专题》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySql性能优化的21个最佳实践》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySQL高级知识笔记》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

文中展示的资料包括:**《MySql思维导图》《MySql核心笔记》《MySql调优笔记》《MySql面试专题》《MySql性能优化的21个最佳实践》《MySq高级知识笔记》**如下图

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

关注我,点赞本文给更多有需要的人

加入社区:https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0
and-demo/registerServlet" method=“post”>

用户名

用户名不太受欢迎

密码

密码格式有误

验证码

看不清?


(3.2)编写RegisterServlet

@WebServlet(“/registerServlet”)

public class RegisterServlet extends HttpServlet {

private UserService service = new UserService();

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//1. 获取用户名和密码数据

String username = request.getParameter(“username”);

String password = request.getParameter(“password”);

User user = new User();

user.setUsername(username);

user.setPassword(password);

//2. 调用service 注册

boolean flag = service.register(user);

《MySql面试专题》

[外链图片转存中…(img-ZV0NrBVi-1725649891072)]

[外链图片转存中…(img-gd5vZv4s-1725649891073)]

《MySql性能优化的21个最佳实践》

[外链图片转存中…(img-L0IxcxJG-1725649891073)]

[外链图片转存中…(img-qjO7DIuD-1725649891073)]

[外链图片转存中…(img-U6F1I8ck-1725649891074)]

[外链图片转存中…(img-PTE9t7q4-1725649891074)]

《MySQL高级知识笔记》

[外链图片转存中…(img-xAp8dJq4-1725649891075)]

[外链图片转存中…(img-FL4F08oM-1725649891075)]

[外链图片转存中…(img-WboSLDdb-1725649891075)]

[外链图片转存中…(img-JClLmVsS-1725649891076)]

[外链图片转存中…(img-6ahYONiz-1725649891076)]

[外链图片转存中…(img-Wz4XfJIL-1725649891076)]

[外链图片转存中…(img-6T7nRmSK-1725649891077)]

[外链图片转存中…(img-AJ5Nob7q-1725649891077)]

[外链图片转存中…(img-eGz9LlEK-1725649891077)]

[外链图片转存中…(img-JOkzm2yd-1725649891078)]

文中展示的资料包括:**《MySql思维导图》《MySql核心笔记》《MySql调优笔记》《MySql面试专题》《MySql性能优化的21个最佳实践》《MySq高级知识笔记》**如下图

[外链图片转存中…(img-IhAvA9Wp-1725649891078)]

关注我,点赞本文给更多有需要的人

加入社区:https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0

  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值