cookie

目录

一、会话技术

二、Cookie

1.创建Cookie

2.使用response响应Cookie给客户端(浏览器)

[3. 获取Cookie](#3. 获取Cookie)

三、Cookie的原理解析

[1. 基本实现原理](#1. 基本实现原理)

(1)响应头:set---cookie

(2)请求头:cookie

(3)Cookie过期时间

四、cookie细节

五、session

六、session使用

[1. 服务器端会话跟踪技术:](#1. 服务器端会话跟踪技术:)

[2. 常用的API:](#2. 常用的API:)

[3. session原理](#3. session原理)

[4. session细节](#4. session细节)

七、session与cookie区别

[八、 用户登录注册案例](#八、 用户登录注册案例)

用户登录

记住密码

用户注册

图形验证码


一、会话技术

1. 会话:一次会话中包含多次请求和响应。
	* 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
2. 功能:在一次会话的范围内的多次请求间,共享数据
3. 方式:
	1. 客户端会话技术:Cookie
	2. 服务器端会话技术:Session

1.用户打开同一个浏览器,访问到我们的web服务器的资源建立会话,对方断开连接该会话才会结束,在一次会话中可以包含多次请求和响应。通俗易懂的理解:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于一个浏览器,以便于在同一次会话的多次请求间共享数据。

2.这是因为http协议是无状态的,每次浏览器向服务器请求时,没有绑定会话信息服务器都会认为该请求是为新请求,没有任何记忆功能,所以我们需要会话跟踪技术实现会话内数据共享。

  1. 会话技术实现方式

(1)客户端会话跟踪技术:Cookie

(2)服务端会话跟踪技术:Session

(3)token或者jwt----新的

二、Cookie

Cookie:客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问

Cookie 数据存放在浏览器端(客户端)

Cookie的特点:
    1. cookie存储数据在客户端浏览器
    2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)

      * 作用:
        1. cookie一般用于存出少量的不太敏感的数据
        2. 在不登录的情况下,完成服务器对客户端的身份识别

1.创建Cookie

Cookie cookie = new Cookie("key","value");

2.使用response响应Cookie给客户端(浏览器)

response.addCookie(cookie);

3. 获取Cookie

获取客户端携带的所有Cookie,使用request对象

java 复制代码
Cookie[] cookies = request.getCookies();
cookie.getName();
cookie.getValue();
java 复制代码
@WebServlet("/addCookieServlet")
public class AddCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("mayikt", "yushengjun");
        resp.addCookie(cookie);
    }
}
java 复制代码
@WebServlet("/getCookieServlet")
public class GetCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie[] cookies = req.getCookies();
        for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            System.out.println("key:" + cookie.getName() + "," +cookie.getValue());
        }
    }
}

注意:在没有清理浏览器缓存的情况下,重启tomcat服务器,cookie数据不会丢失

三、Cookie的原理解析

1. 基本实现原理

Cookie实现是基于HTTP协议的

客户端(浏览器端)发送请求达到服务器端,服务器端会创建cookie,会将该cookie数据

返回给客户端,在响应头中设置 set---cookie value cookie数据。

(2)请求头:cookie

同一个浏览器发送请求时,在请求中设置该cookie数据 存放在请求头中。

cookie value

(3)Cookie过期时间

setMaxAge(int seconds):设置Cookie存活时间

a.正数:将Cookie写入浏览器所在的电脑硬盘,持久化存储,到期自动删除

b.负数:默认值,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁。

c.零:删除对应Cookie

四、cookie细节

  1. 一次可不可以发送多个cookie?

* 可以

* 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。

  1. cookie在浏览器中保存多长时间?

(1) 默认情况下,当浏览器关闭后,Cookie数据被销毁

(2) 持久化存储:

* setMaxAge(int seconds)

a. 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效

b. 负数:默认值

c. 零:删除cookie信息

  1. cookie能不能存中文?

* 在tomcat 8 之前 cookie中不能直接存储中文数据。

* 需要将中文数据转码---一般采用URL编码(%E3)

* 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析

  1. cookie共享问题?

假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?

* 默认情况下cookie不能共享

* setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录

* 如果要共享,则可以将path设置为"/"

五、session

  1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession

  2. 快速入门:

(1)获取HttpSession对象:

HttpSession session = request.getSession();

(2)使用HttpSession对象:

Object getAttribute(String name)

void setAttribute(String name, Object value)

void removeAttribute(String name)

  1. 原理

* Session的实现是依赖于Cookie的。

六、session使用

java 复制代码
1.session用于存储一次会话的多次请求的数据,存在服务器端;

2.session可以存储任意类型,任意大小的数据。

1. 服务器端会话跟踪技术:

将数据保存在服务器端,底层基于cookie实现封装

2. 常用的API:

(1)void session.setAttribute(k,v) session存入值 key=name,value 'yushengjun'

(2)Object session.getAttribute(k) 获取到session中的值

(3)void removeAttribute(k) 删除我们的session

3. session原理

(1)当我们客户端发送请求达到服务器端时创建session,会得到一个sessionid,在将该

sessionid 响应在响应头<sessionid >

(2)客户端(浏览器)接受响应头中的sessionid ,会将该sessionid的值 存放在浏览器中。

session本质上就是基于cookie实现封装的。

(3)使用同一个浏览器发送请求时,访问通一个服务器端,会在请求头中设定该sessionid 的值,服务器端就会从请求头中获取到该sessionid 查找对应session。

session 数据存放在服务器端 cookie将数据存放在本地。

4. session细节

(1)当客户端关闭后,服务器不关闭的话,再次打开客户端访问服务器端两次获取Session是否为同一个?

在默认情况下,不是同一个。因为客户端关闭后,cookie对象被销毁,客户端请求服务器会创建新的session。

如果需要两个Session相同,则可以创建一个Cookie对象,key为:JSESSIONID,设置一下最大存活时间,让Cookie持久化保存Session的ID,就可以实现客户端关闭,两次获取Session就是同一个。

Cookie c = new Cookie("JSESSIONID",session.getId());
	    c.setMaxAge(60*60); //1个小时有效期
	    response.addCookie(c);

(2)客户端不关闭,服务器关闭后的话,两次获取的Session是否是同一个?

不是,因为同样服务器关闭后session对象会被销毁。

如果想确保数据不丢失,可以使session钝化,即在服务器正常关闭之前,将session对象序列化到硬盘上。下次在服务器启动后,将session文件反序列化转化为内存中的session对象即可。

0D202066E021E4F4FB978F1647C0D742

java 复制代码
tomcat自动完成以下工作:

1.session的钝化:在服务器正常关闭之前,将session对象系列化到硬盘上。

2.session的活化: 在服务器启动后,将session文件转化为内存中的session对象即可。
java 复制代码
session什么时候被销毁?

1.服务器关闭;

2.session对象调用invalidate() ;

3.session默认失效时间 30分钟。

七、session与cookie区别

session与Cookie的区别:

1.session存储数据在服务器端,Cookie在客户端;

2.session没有数据大小限制,Cookie有数据大小限制;

3.session数据安全,Cookie相对不安全。

八、 用户登录注册案例

用户登录

使用session保存用户会话信息。

数据库访问层

java 复制代码
public class MayikUsertDao {
    
    /**
    * 用户登录成功之后 该方法返回 用户登录成功之后对象
    */
    public MayiktUserEntity login(String userName, String userPwd) {
        try {
            Connection connection = MayiktJdbcUtils.getConnection();
            String loginSql = "select  * from  mayikt_users where userName=? and userPwd=?;";
            PreparedStatement preparedStatement = connection.prepareStatement(loginSql);
            preparedStatement.setString(1, userName);
            preparedStatement.setString(2, userPwd);
            ResultSet resultSet = preparedStatement.executeQuery();
            if (!resultSet.next()) {  // 查询不到用户数据
                return null;
            }
            // 将db中数据 返回给客户端 查询到数据
            Integer id = resultSet.getInt(1);
            String dbUserName = resultSet.getString(2);
            String dbUserPwd = resultSet.getString(3);
            MayiktUserEntity mayiktUserEntity = new MayiktUserEntity(id, dbUserName, dbUserPwd);
            return mayiktUserEntity;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        
    }
}

业务逻辑层

java 复制代码
public class MayikUsertService {
    private MayikUsertDao mayikUsertDao = new MayikUsertDao();

    public MayiktUserEntity login(String userName, String userPwd) {
        return mayikUsertDao.login(userName, userPwd);
    }
}

视图层

java 复制代码
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private MayikUsertService mayikUsertService = new MayikUsertService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 转发login页面
        req.getRequestDispatcher("login.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 点击登录的时候 获取到用户的参数
        String userName = req.getParameter("userName");
        if (StringUtils.isEmpty(userName)) {
            //转发到错误页面
            req.setAttribute("errorMsg", "用户名称不能够是为空!");
            req.getRequestDispatcher("error.jsp").forward(req, resp);
            return;
        }
        String userPwd = req.getParameter("userPwd");
        // 参数验证
        if (StringUtils.isEmpty(userPwd)) {
            //转发到错误页面
            req.setAttribute("errorMsg", "userPwd不能够是为空!");
            req.getRequestDispatcher("error.jsp").forward(req, resp);
            return;
        }
        // 在调用业务逻辑层
        MayiktUserEntity mayiktUserEntity = mayikUsertService.login(userName, userPwd);
        if (mayiktUserEntity == null) {
            // 用户名称或者密码错误!
            req.setAttribute("errorMsg", "用户名称或者是密码错误!");
            req.getRequestDispatcher("login.jsp").forward(req, resp);
            return;
        }
        // 能够db中查询到对象 登录成功了  将用户数据存放在session中
        HttpSession session = req.getSession();
        session.setAttribute("user", mayiktUserEntity);
        // 在转发到首页(重定向到首页)
//        req.getRequestDispatcher("index.jsp").forward(req, resp);
        resp.sendRedirect("index.jsp");
    }
}
html 复制代码
<%--
  Created by IntelliJ IDEA.
  User: mayikt
  Date: 2022/6/6
  Time: 17:12
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <title>登录测试页面</title>
    <form action="/mayikt_session_war_exploded/login" method="post">
        <label>用户名: </label><input type="text" name="userName"/><br>
        <label>密&nbsp码&nbsp: </label><input type="password" name="userPwd"/><br>
        ${errorMsg}
        <input type="submit" value="登录 "/>
    </form>

</head>
</html>

相关配置文件

driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mayikt?serverTimezone=GMT%2B8
user=root
password=root

记住密码

思路:

用户登录成功之后,会将用户的名称和密码 写入在cookie中,

当我们用户下次登录时,会直接从cookie中获取到数据 回显到

login.jsp中 这样的话就不需要用户重复的数据用户名称和密码。

改造servlet

java 复制代码
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private MayikUsertService mayikUsertService = new MayikUsertService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 转发login页面
        req.getRequestDispatcher("login.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 点击登录的时候 获取到用户的参数
        String userName = req.getParameter("userName");
        if (StringUtils.isEmpty(userName)) {
            //转发到错误页面
            req.setAttribute("errorMsg", "用户名称不能够是为空!");
            req.getRequestDispatcher("error.jsp").forward(req, resp);
            return;
        }
        String userPwd = req.getParameter("userPwd");
        // 参数验证
        if (StringUtils.isEmpty(userPwd)) {
            //转发到错误页面
            req.setAttribute("errorMsg", "userPwd不能够是为空!");
            req.getRequestDispatcher("error.jsp").forward(req, resp);
            return;
        }
        // 在调用业务逻辑层
        MayiktUserEntity mayiktUserEntity = mayikUsertService.login(userName, userPwd);
        if (mayiktUserEntity == null) {
            // 用户名称或者密码错误!
            req.setAttribute("errorMsg", "用户名称或者是密码错误!");
            req.getRequestDispatcher("login.jsp").forward(req, resp);
            return;
        }
        // 判断用户是否记住密码
        String rememberPassword = req.getParameter("rememberPassword");
        if ("on".equals(rememberPassword)) {
            // 如果有记住密码则 将密码保存在cookie中
            Cookie userNameCookie = new Cookie("userName", userName);
            Cookie userPwdCookie = new Cookie("userPwd", userPwd);
            resp.addCookie(userNameCookie);
            resp.addCookie(userPwdCookie);
        }
        // 能够db中查询到对象 登录成功了  将用户数据存放在session中
        HttpSession session = req.getSession();
        session.setAttribute("user", mayiktUserEntity);
        // 在转发到首页(重定向到首页)
//        req.getRequestDispatcher("index.jsp").forward(req, resp);
        resp.sendRedirect("index.jsp");
    }
}

改造jsp

html 复制代码
<%--
  Created by IntelliJ IDEA.
  User: mayikt
  Date: 2022/6/6
  Time: 17:12
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <title>登录测试页面</title>
    <form action="/mayikt_session_war_exploded/login" method="post">
        <label>用户名: </label><input type="text" name="userName" value="${cookie.userName.value}"/><br>
        <label>密&nbsp码&nbsp: </label><input type="password" name="userPwd" value="${cookie.userPwd.value}"/><br>
        <label>记住密码: </label><input type="checkbox" name="rememberPassword"/><br>
        ${errorMsg}
        <input type="submit" value="登录 "/>
    </form>

</head>
</html>

用户注册

数据库访问层

java 复制代码
public class MayikUsertDao {
    
    /**
    * 用户登录成功之后 该方法返回 用户登录成功之后对象
    */
    public MayiktUserEntity login(String userName, String userPwd) {
        ResultSet resultSet = null;
        PreparedStatement preparedStatement = null;
        Connection connection = null;
        try {
            connection = MayiktJdbcUtils.getConnection();
            String loginSql = "select  * from  mayikt_users where userName=? and userPwd=?;";
            preparedStatement = connection.prepareStatement(loginSql);
            preparedStatement.setString(1, userName);
            preparedStatement.setString(2, userPwd);
            resultSet = preparedStatement.executeQuery();
            if (!resultSet.next()) {  // 查询不到用户数据
                return null;
            }
            // 将db中数据 返回给客户端 查询到数据
            Integer id = resultSet.getInt(1);
            String dbUserName = resultSet.getString(2);
            String dbUserPwd = resultSet.getString(3);
            MayiktUserEntity mayiktUserEntity = new MayiktUserEntity(id, dbUserName, dbUserPwd);
            return mayiktUserEntity;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            MayiktJdbcUtils.closeConnection(resultSet, preparedStatement, connection);
        }
    }
    
    public MayiktUserEntity findByUserName(String userName) {
        ResultSet resultSet = null;
        PreparedStatement preparedStatement = null;
        Connection connection = null;
        try {
            connection = MayiktJdbcUtils.getConnection();
            String loginSql = "select  * from  mayikt_users where userName=?";
            preparedStatement = connection.prepareStatement(loginSql);
            preparedStatement.setString(1, userName);
            resultSet = preparedStatement.executeQuery();
            if (!resultSet.next()) {  // 查询不到用户数据
                return null;
            }
            // 将db中数据 返回给客户端 查询到数据
            Integer id = resultSet.getInt(1);
            String dbUserName = resultSet.getString(2);
            String dbUserPwd = resultSet.getString(3);
            MayiktUserEntity mayiktUserEntity = new MayiktUserEntity(id, dbUserName, dbUserPwd);
            return mayiktUserEntity;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            MayiktJdbcUtils.closeConnection(resultSet, preparedStatement, connection);
        }
    }
    
    public int register(String userName, String userPwd) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = MayiktJdbcUtils.getConnection();
            // sql语句写的操作 ----加上事务
            MayiktJdbcUtils.beginTransaction(connection); // 开启事务
            String insertSql = "INSERT INTO `mayikt`.`mayikt_users` (`id`, `userName`, `userPwd`) VALUES (null, ?, ?);";
            preparedStatement = connection.prepareStatement(insertSql);
            preparedStatement.setString(1, userName);
            preparedStatement.setString(2, userPwd);
            int result = preparedStatement.executeUpdate();
            // 代码执行没有问题的情况下 则会提交数据
            MayiktJdbcUtils.commitTransaction(connection); // 提交事务
            return result;
        } catch (Exception e) {
            // 程序代码报错之后 是需要回滚事务
            e.printStackTrace();
            MayiktJdbcUtils.rollBackTransaction(connection);// 回滚事务
            return 0;
        } finally {
            MayiktJdbcUtils.closeConnection(preparedStatement, connection);
        }
        
    }
}

业务逻辑层

    public int register(String userName, String userPwd) {
        return mayikUsertDao.register(userName, userPwd);
    }

    public MayiktUserEntity findByUserName(String userName) {
        return mayikUsertDao.findByUserName(userName);
    }

视图层

java 复制代码
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    private MayikUsertService mayikUsertService = new MayikUsertService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 转发到register.jsp
        req.getRequestDispatcher("register.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 转发到注册插入数据
        // 点击注册的时候 获取到用户的参数
        String userName = req.getParameter("userName");
        if (StringUtils.isEmpty(userName)) {
            //转发到错误页面
            req.setAttribute("errorMsg", "用户名称不能够是为空!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        String userPwd = req.getParameter("userPwd");
        // 参数验证
        if (StringUtils.isEmpty(userPwd)) {
            //转发到错误页面
            req.setAttribute("errorMsg", "userPwd不能够是为空!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        // 用户注册之前根据用户名称查询该用户是否存在如果不存在的情况下才可以注册 如果存在的话就无法注册
        MayiktUserEntity dbMayiktUserEntity = mayikUsertService.findByUserName(userName);
        if (dbMayiktUserEntity != null) {
            req.setAttribute("errorMsg", "该用户" + userName + ",在数据库中存在无法重复注册!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        //用户数据注册
        int register = mayikUsertService.register(userName, userPwd);
        if (register <= 0) {
            // 注册失败了   //转发到错误页面
            req.setAttribute("errorMsg", "注册失败!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        // 注册成功之后就直接重定向到登录请求
        resp.sendRedirect("login");
    }
}
html 复制代码
<%--
  Created by IntelliJ IDEA.
  User: mayikt
  Date: 2022/6/6
  Time: 17:12
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <title>注册页面</title>
    <form action="/mayikt_session_war_exploded/register" method="post">
        <label>用户名: </label><input type="text" name="userName"/><br>
        <label>密&nbsp&nbsp&nbsp码: </label><input type="password" name="userPwd"/><br>
        <span style="color: red">${errorMsg}</span>
        <input type="submit" value="注册"/>
    </form>

</head>
</html>

图形验证码

图形底层实现原理

java支持根据内容生成图片

abcd 企业实际开发中图形验证码工具类 底层细节我们自己去开发的

1.生成图形验证码内容 abch

2.调用java的api 将我们的该内容 生成一张图片abch

3.将该形验证码内容 abch 存放在session中

用户点击注册时:获取用户输入的图形验证码和session中验证码比对 如果一致的情况下

则开始做注册流程。

图形验证码工具类

java 复制代码
/**
 * 工具类,生成随机验证码
 */
public class RandomValidateCode {
    public static final String MAYIKT_RANDOMVALIDATECODE = "RandomValidateCode";// 放到session中的key
    private Random random = new Random();
    private String randString = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生的字符串
    private int width = 100;// 图片宽度
    private int height = 26;// 图片高度
    private int lineSize = 40;// 干扰线数量
    private int stringNum = 4;// 随机产生的字符数量

    /*
     * 获得字体
     */
    private Font getFont() {
        return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
    }

    /*
     * 获得颜色
     */
    private Color getRandColor(int fc, int bc) {
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc - 16);
        int g = fc + random.nextInt(bc - fc - 14);
        int b = fc + random.nextInt(bc - fc - 18);
        return new Color(r, g, b);
    }

    /**
     * 生成随机图片
     */
    public void getRandcode(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,该对象可以在图像上进行各种绘制操作
        g.fillRect(0, 0, width, height);
        g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));
        g.setColor(getRandColor(110, 133));
        // 绘制干扰线
        for (int i = 0; i <= lineSize; i++) {
            drowLine(g);
        }
        // 绘制随机字符
        String randomString = "";
        for (int i = 1; i <= stringNum; i++) {
            randomString = drowString(g, randomString, i);
        }
        session.removeAttribute(MAYIKT_RANDOMVALIDATECODE);
        session.setAttribute(MAYIKT_RANDOMVALIDATECODE, randomString);
        g.dispose();
        try {
            ImageIO.write(image, "JPEG", response.getOutputStream());// 将内存中的图片通过流动形式输出到客户端
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * 绘制字符串
     */
    private String drowString(Graphics g, String randomString, int i) {
        g.setFont(getFont());
        g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));
        String rand = getRandomString(random.nextInt(randString.length()));
        randomString += rand;
        g.translate(random.nextInt(3), random.nextInt(3));
        g.drawString(rand, 13 * i, 16);
        return randomString;
    }

    /*
     * 绘制干扰线
     */
    private void drowLine(Graphics g) {
        int x = random.nextInt(width);
        int y = random.nextInt(height);
        int xl = random.nextInt(13);
        int yl = random.nextInt(15);
        g.drawLine(x, y, x + xl, y + yl);
    }

    /*
     * 获取随机的字符
     */
    public String getRandomString(int num) {
        return String.valueOf(randString.charAt(num));
    }
}
java 复制代码
/**
 * 前台验证码处点击刷新,发送到该servlet的请求,
 * 该servlet调用生成验证码的工具类返回一个图像验证码
 */
@WebServlet(name = "VerifycodeServlet", urlPatterns = "/VerifycodeServlet")
public class VerifycodeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片
        response.setHeader("Pragma", "No-cache");//设置响应头信息,告诉浏览器不要缓存此内容
        //做浏览器兼容
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", 0);
        RandomValidateCode randomValidateCode = new RandomValidateCode();
        try {
            randomValidateCode.getRandcode(request, response);//输出图片方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

注册jsp加上图形验证码

html 复制代码
<%--
  Created by IntelliJ IDEA.
  User: mayikt
  Date: 2022/6/6
  Time: 17:12
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <title>注册页面</title>
    <form action="/mayikt_session_war_exploded/register" method="post">
        <label>用户名: </label><input type="text" name="userName"/><br>
        <label>密&nbsp&nbsp&nbsp码: </label><input type="password" name="userPwd"/><br>
        <label>验证码: </label><input type="text" name="code"/>
        <img id="exchangecode" src="VerifycodeServlet">
        <a id="ecode" href="#">看不清?换一张图片</a><br>
        <span style="color: red">${errorMsg}</span>
        <input type="submit" value="注册"/>
    </form>
    <script type="text/javascript">
        window.onload = function () {
            //获取img标签的对象
            img = document.getElementById("exchangecode");
            img.onclick = function () {
                //加时间戳,避免浏览器缓存
                var date = new Date().getTime()
                img.src = "VerifycodeServlet?" + date;
            }
            //获取a标签的对象
            ec = document.getElementById("ecode");
            ec.onclick = function () {
                //加时间戳
                var date = new Date().getTime()
                img.src = "VerifycodeServlet?" + date;
            }
        }

    </script>
</head>
</html>

注册验证图形验证码

java 复制代码
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    private MayikUsertService mayikUsertService = new MayikUsertService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 转发到register.jsp
        req.getRequestDispatcher("register.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 转发到注册插入数据
        // 点击注册的时候 获取到用户的参数
        String userName = req.getParameter("userName");
        if (StringUtils.isEmpty(userName)) {
            //转发到错误页面
            req.setAttribute("errorMsg", "用户名称不能够是为空!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        String userPwd = req.getParameter("userPwd");
        // 参数验证
        if (StringUtils.isEmpty(userPwd)) {
            //转发到错误页面
            req.setAttribute("errorMsg", "userPwd不能够是为空!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        // 图形验证码  比较 是在 注册之前
        // 比较图形验证码
        String userCode = req.getParameter("code"); // 用户输入的图形验证码
        // 从session中获取图形验证码
        HttpSession session = req.getSession();
        String sessionCode = (String) session.getAttribute(RandomValidateCode.MAYIKT_RANDOMVALIDATECODE);
        if (!sessionCode.equalsIgnoreCase(userCode)) {
            req.setAttribute("errorMsg", "图形验证码不正确,请重新输入!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        // 用户注册之前根据用户名称查询该用户是否存在如果不存在的情况下才可以注册 如果存在的话就无法注册
        MayiktUserEntity dbMayiktUserEntity = mayikUsertService.findByUserName(userName);
        if (dbMayiktUserEntity != null) {
            req.setAttribute("errorMsg", "该用户" + userName + ",在数据库中存在无法重复注册!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        //用户数据注册
        int register = mayikUsertService.register(userName, userPwd);
        if (register <= 0) {
            // 注册失败了   //转发到错误页面
            req.setAttribute("errorMsg", "注册失败!");
            req.getRequestDispatcher("register.jsp").forward(req, resp);
            return;
        }
        // 注册成功之后就直接重定向到登录请求
        resp.sendRedirect("login");
    }
}
相关推荐
weixin_462428474 分钟前
使用 Caffeine 缓存并在业务方法上通过注解实现每3到5秒更新缓存
java·缓存
程序媛小果5 分钟前
基于java+SpringBoot+Vue的桂林旅游景点导游平台设计与实现
java·vue.js·spring boot
骑鱼过海的猫1237 分钟前
【java】java通过s3访问ceph报错
java·ceph·iphone
杨充13 分钟前
13.观察者模式设计思想
java·redis·观察者模式
Lizhihao_15 分钟前
JAVA-队列
java·开发语言
喵叔哟24 分钟前
重构代码之移动字段
java·数据库·重构
喵叔哟24 分钟前
重构代码之取消临时字段
java·前端·重构
fa_lsyk27 分钟前
maven环境搭建
java·maven
Daniel 大东1 小时前
idea 解决缓存损坏问题
java·缓存·intellij-idea
wind瑞1 小时前
IntelliJ IDEA插件开发-代码补全插件入门开发
java·ide·intellij-idea