JavaEE 暑期课笔记 Ⅳ JSP HttpSession ① 简易购物车 + ② 避免表单重复提交 + ③ 实现验证码

笔记来源于 2013 年尚硅谷的视频教程

1. 简易 session 版购物车

在这里插入图片描述
操作流程

在这里插入图片描述

1.1 在 web 下新建文件夹 cart

新建 step-1.jsp

<%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2020/7/23
  Time: 21:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>step-1</title>
</head>
<body>
<h4>Step1: 选择要购买的图书</h4>
<p>开发的时候只能使用绝对路径,不可以用相对路径</p>
<p>name 必须一样</p>
<form action="<%= request.getContextPath() %>/processStep1Servlet" method="post">
    <table border="1" cellpadding="10" cellspacing="0">
        <tr>
            <td>书名</td>
            <td>购买</td>
        </tr>
        <tr>
            <td>Java</td>
            <td> <input type="checkbox" name="book" value="Java"> </td>
        </tr>

        <tr>
            <td>Oracle</td>
            <td><input type="checkbox" name="book" value="Oracle"></td>
        </tr>

        <tr>
            <td>Structs</td>
            <td><input type="checkbox" name="book" value="Structs"></td>
        </tr>

        <tr>
            <td colspan="2">
                <input type="submit" value="Submit" />
            </td>
        </tr>
    </table>
</form>

</body>
</html>

新建 step-2.jsp

<%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2020/7/23
  Time: 22:30
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>step-2</title>
</head>
<body>
<h4>step2: 请输入寄送地址和信用卡信息</h4>
<form action="<%= request.getContextPath() %>/processStep2Servlet" method="post">
    <table border="1" cellpadding="10" cellspacing="0">
        <tr>
            <td colspan="2">寄送信息</td>
        </tr>
        <tr>
            <td>姓名:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>寄送地址:</td>
            <td><input type="text" name="address"></td>
        </tr>

        <tr>
            <td colspan="2">信用卡信息</td>
        </tr>
        <tr>
            <td>种类:</td>
            <td>
                <input type="radio" name="cardType" value="Visa">Visa
                <input type="radio" name="cardType" value="Master">Master
            </td>
        </tr>
        <tr>
            <td>卡号:</td>
            <td><input type="text" name="card"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Submit">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

新建 confirm.jsp

<%@ page import="com.learn.session.cart.Customer" %><%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2020/7/24
  Time: 0:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>confirm</title>
</head>
<body>
<form>
    <%
        Customer customer = (Customer) session.getAttribute("customer");
        String[] books = (String[]) session.getAttribute("books");
    %>
    <table border="1" cellpadding="10" cellspacing="0">
        <tr>
            <td>name: </td>
            <td><%= customer.getName() %></td>
        </tr>
        <tr>
            <td>address: </td>
            <td><%= customer.getAddress() %></td>
        </tr>
        <tr>
            <td>cardType: </td>
            <td><%= customer.getCardType() %></td>
        </tr>
        <tr>
            <td>card: </td>
            <td><%= customer.getCard() %></td>
        </tr>

        <tr>
            <td>Books: </td>
            <td>
                <%
                    for (String book: books) {
                        out.print(book);
                        out.print("<br>");
                    }
                %>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

1.2 在 src 下新建文件夹 cart

新建 ProcessStep1Servlet.java

package com.learn.session.cart;

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 java.io.IOException;

/**
 * User: Admin
 * Date: 2020/7/23
 * Time: 22:21
 * Author: 
 * Note:
 */
@WebServlet(name = "processStep1Servlet", urlPatterns = "/processStep1Servlet")
public class ProcessStep1Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取选中的图书的信息
        String[] books = request.getParameterValues ( "book");
        //2.把图书信息放入到HttpSession中
        request.getSession(). setAttribute( "books", books);
        //3.重定向页面到 cart/step-2.jsp
        System.out.println(request.getContextPath() + "/learn.session.cart/step-2.jsp");
        response.sendRedirect(request.getContextPath() + "/learn.session.cart/step-2.jsp");

    }
}

新建 ProcessStep2Servlet.java

package com.learn.session.cart;

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;

/**
 * User: Admin
 * Date: 2020/7/23
 * Time: 22:21
 * Author: 
 * Note:
 */
@WebServlet(name = "processStep2Servlet", urlPatterns = "/processStep2Servlet")
public class ProcessStep2Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求参数: name, address, cardType, card
        String name = request.getParameter( "name") ;
        String address = request.getParameter( "address");
        String cardType = request.getParameter("cardType");
        String card = request.getParameter("card");

        Customer customer = new Customer(name, address, cardType, card);

        //2.把请求信息存入到HttpSession中
        HttpSession session = request.getSession();
        session.setAttribute("customer", customer);

        //3.重定向页面到confirm.jsp
        response.sendRedirect(request.getContextPath() + "/learn.session.cart/confirm.jsp");

    }
}

新建 Customer.java

package com.learn.session.cart;

/**
 * User: Admin
 * Date: 2020/7/23
 * Time: 23:59
 * Note:
 */
public class Customer {
    private String name;
    private String address;
    private String cardType;
    private String card;

    public Customer() { }

    public Customer(String name, String address, String cardType, String card) {
        this.name = name;
        this.address = address;
        this.cardType = cardType;
        this.card = card;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getCardType() {
        return cardType;
    }

    public void setCardType(String cardType) {
        this.cardType = cardType;
    }

    public String getCard() {
        return card;
    }

    public void setCard(String card) {
        this.card = card;
    }
}

1.3 运行结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. token 避免表单重复提交

首先创建一个提交表单 index.jsp, 成功表单 success.jsp 和一个响应的 servlet

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>index</title>
</head>
<body>
<form action="<%= request.getContextPath() %>/tokenServlet" method="post">
    name: <input type="text" name="name" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>success</title>
</head>
<body>
<h4>Success Page</h4>
</body>
</html>

TokenServlet.java

package com.learn.session.token;

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 java.io.IOException;

/**
 * User: Admin
 * Date: 2020/7/24
 * Time: 10:03
 * Note:
 */
@WebServlet(name = "tokenServlet", urlPatterns = "/tokenServlet")
public class TokenServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        System.out.println("name: " + name);

        // 请求转发
//        req.getRequestDispatcher("/learn.session.token/success.jsp").forward(req, resp);

        // 重定向
        resp.sendRedirect(req.getContextPath() + "/learn.session.token/success.jsp");
    }
}

2.1 重复提交的情况

① 在表单提交到一个Servlet, 而Servlet又通过请求转发的方式响应了一个JSP(HTML)页面, 此时地址栏还保留着Servlet的那个路径, 在响应页面点击"刷新".
② 在响应页面没有到达时重复点击"提交按钮"
③ 点击“返回",再点击"提交"

2.2 不是重复提交的情况

点击"返回",“刷新"原表单页面, 再"提交"

2.3 如何避免表单的重复提交

在表单中做一个标记,提交到Servlet时,检查标记是否存在且是否和预定义的标记致,
① 若一致,则受理请求,并销毁标记;
② 若不一致或没有标记,则直接响应提示信息: “重复提交”

2.3.1 Error:仅提供一个隐藏域

// index.jsp 的 form 中添加
<input type="hidden" name="token" value="RongRong" />
// TokenServlet.java 中添加
String token = req.getParameter("token");
if ("RongRong".equals(token)) {
    // 清除标记: 没有办法清除固定的请求参数
}

此方法行不通的理由:没有办法清除固定的请求参数

2.3.2 Error:把标记放在 request 中

// index.jsp 的 form 中添加
<%
    request.setAttribute("token", "tokenValue");
%>
// TokenServlet.java 中添加
Object token = req.getAttribute("token");
if (token != null) {
    req.removeAttribute("token");
} else {
    resp.sendRedirect(req.getContextPath() +
    	 "/learn.session.token/token.jsp");
    return;
}

token.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>token</title>
</head>
<body>
<h4>对不起,已经提交过了</h4>
</body>
</html>

此方法行不通的理由:因为表单页面制新后,request已经被销毁,再提交表单是一个新的request 。

2.3.3 Success:把标记放在 session 中

// index.jsp 的 form 中添加
<%
    session.setAttribute("token", "tokenValue");
%>
// TokenServlet.java 中添加
HttpSession session = req.getSession();
Object token = session.getAttribute("token");
if (token != null) {
    session.removeAttribute("token");
} else {
    resp.sendRedirect(req.getContextPath() + "/learn.session.token/token.jsp");
    return;
}

此方法虽然可以但是不完美,缺陷很多。比如我们希望 token 的值是一个随机的值。

2.3.4 Perfect:把随机值标记放在 session 中

在原表单页面,生成一个随机值token
在原表单页面,把token值放入session属性中
在原表单页面,把token值放入到隐藏城中。
在目标的Servlet中:获取session和隐藏城中的token值
比较两个值是否致:若致,受理请求,且把session域中的token羼性清除
若不一致,则直接响应提示页面: “重复提交”

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>index</title>
</head>
<body>

<%
    String tokenValue = new Date() + "";
    session.setAttribute("token", tokenValue);
%>

<form action="<%= request.getContextPath() %>/tokenServlet" method="post">
    name: <input type="text" name="name" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>
// TokenServlet.java 中添加
HttpSession session = req.getSession();
Object token = session.getAttribute("token");
String tokenValue = req.getParameter("token");

if (token != null && token.equals(tokenValue)) {
    session.removeAttribute("token");
} else {
    resp.sendRedirect(req.getContextPath() + "/learn.session.token/token.jsp");
    return;
}

2.4 代码最终模样

index.jsp

<%@ page import="java.util.Date" %>
<%@ page import="com.learn.session.token.TokenProcessor" %><%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2020/7/24
  Time: 10:01
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>index</title>
</head>
<body>

<%
    String tokenValue = new Date().getTime() + "";
    session.setAttribute("token", tokenValue);
%>

<form action="<%= request.getContextPath() %>/tokenServlet" method="post">
    <input type="hidden" name="TOKEN_KEY"
           value="<%= TokenProcessor.getInstance().saveToken(request) %>">
    name: <input type="text" name="name" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>success</title>
</head>
<body>
<h4>Success Page</h4>
</body>
</html>

token.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>token</title>
</head>
<body>
<h4>对不起,已经提交过了</h4>
</body>
</html>

TokenProcessor.java

package com.learn.session.token;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class TokenProcessor {
    private static final String TOKEN_KEY = "TOKEN_KEY";

    private static final String TRANSACTION_TOKEN_KEY = "TRANSACTION_TOKEN_KEY";

    /**
     * The singleton instance of this class.
     */
    private static TokenProcessor instance = new TokenProcessor();

    /**
     * The timestamp used most recently to generate a token value.
     */
    private long previous;

    /**
     * Protected constructor for TokenProcessor.  Use TokenProcessor.getInstance()
     * to obtain a reference to the processor.
     */
    protected TokenProcessor() {
        super();
    }

    /**
     * Retrieves the singleton instance of this class.
     */
    public static TokenProcessor getInstance() {
        return instance;
    }

    public synchronized boolean isTokenValid(HttpServletRequest request) {
        return this.isTokenValid(request, false);
    }

    /** 
     * @param request The servlet request we are processing
     * @param reset   Should we reset the token after checking it?
     */
    public synchronized boolean isTokenValid(HttpServletRequest request,
                                             boolean reset) {
        // Retrieve the current session for this request
        HttpSession session = request.getSession(false);

        if (session == null) {
            return false;
        }

        // Retrieve the transaction token from this session, and
        // reset it if requested
        String saved =
                (String) session.getAttribute(TRANSACTION_TOKEN_KEY);

        if (saved == null) {
            return false;
        }

        if (reset) {
            this.resetToken(request);
        }

        // Retrieve the transaction token included in this request
        String token = request.getParameter(TOKEN_KEY);

        if (token == null) {
            return false;
        }

        return saved.equals(token);
    }

    /**
     * Reset the saved transaction token in the user's session.  This
     * indicates that transactional token checking will not be needed on the
     * next request that is submitted.
     *
     * @param request The servlet request we are processing
     */
    public synchronized void resetToken(HttpServletRequest request) {
        HttpSession session = request.getSession(false);

        if (session == null) {
            return;
        }

        session.removeAttribute(TRANSACTION_TOKEN_KEY);
    }

    /**
     * Save a new transaction token in the user's current session, creating a
     * new session if necessary.
     *
     * @param request The servlet request we are processing
     */
    public synchronized String saveToken(HttpServletRequest request) {
        HttpSession session = request.getSession();
        String token = generateToken(request);

        if (token != null) {
            session.setAttribute(TRANSACTION_TOKEN_KEY, token);
        }

        return token;
    }

    /**
     * Generate a new transaction token, to be used for enforcing a single
     * request for a particular transaction.
     *
     * @param request The request we are processing
     */
    public synchronized String generateToken(HttpServletRequest request) {
        HttpSession session = request.getSession();

        return generateToken(session.getId());
    }

    /**
     * Generate a new transaction token, to be used for enforcing a single
     * request for a particular transaction.
     *
     * @param id a unique Identifier for the session or other context in which
     *           this token is to be used.
     */
    public synchronized String generateToken(String id) {
        try {
            long current = System.currentTimeMillis();

            if (current == previous) {
                current++;
            }

            previous = current;

            byte[] now = new Long(current).toString().getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(id.getBytes());
            md.update(now);

            return toHex(md.digest());
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    /**
     * Convert a byte array to a String of hexadecimal digits and return it.
     *
     * @param buffer The byte array to be converted
     */
    private String toHex(byte[] buffer) {
        StringBuffer sb = new StringBuffer(buffer.length * 2);

        for (int i = 0; i < buffer.length; i++) {
            sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
            sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
        }

        return sb.toString();
    }

}

TokenServlet.java

package com.learn.session.token;

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;

/**
 * User: Admin
 * Date: 2020/7/24
 * Time: 10:03
 * Author: 
 * Note:
 */
@WebServlet(name = "tokenServlet", urlPatterns = "/tokenServlet")
public class TokenServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        String token = req.getParameter("token");
//        if ("RongRong".equals(token)) {
//            // 清除标记: 没有办法清除固定的请求参数
//        }

//        HttpSession session = req.getSession();
//        Object token = session.getAttribute("token");
//        String tokenValue = req.getParameter("token");
//
//        if (token != null && token.equals(tokenValue)) {
//            session.removeAttribute("token");
//        } else {
//            resp.sendRedirect(req.getContextPath() + "/learn.session.token/token.jsp");
//            return;
//        }

        boolean valid = TokenProcessor.getInstance().isTokenValid(req);
        if (valid) {
            TokenProcessor.getInstance().resetToken(req);
        } else {
            resp.sendRedirect(req.getContextPath() + "/learn.session.token/token.jsp");
            return;
        }

        String name = req.getParameter("name");
        System.out.println("name: " + name);

        // 请求转发
//        req.getRequestDispatcher("/learn.session.token/success.jsp").forward(req, resp);

        // 重定向
        resp.sendRedirect(req.getContextPath() + "/learn.session.token/success.jsp");
    }
}

3. 利用Session实现一次性验证码

在原表单页面,生成一个验证码的图片,生成图片的同时,需要把该图片中的字符串放入到session中.
在原表单页面,定义一个文本域,用于输入验证码。
在目标的Servlet中:获取session和表单域中的验证码的值
比较两个值是否一致:若一致,受理请求,且把session域中的验证码属性清除
若不一 致,则直接通过重定向的方式返回原表单页面,并提示用户"验证码错误“

3.1 代码

index.jsp

<%@ page import="java.util.Date" %>
<%@ page import="com.learn.session.token.TokenProcessor" %><%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2020/7/24
  Time: 12:01
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>index</title>
</head>
<body>

<form color="red">
    <%= session.getAttribute("message") == null ? "": session.getAttribute("message") %>
</form>

<form action="<%= request.getContextPath() %>/checkCodeServlet" method="post">
    name: <input type="text" name="name" />
    验证码: <input type="text" name="CHECK_CODE_PARAM_KEY">
    <img alt="code" src="<%= request.getContextPath() %>/validateColorServlet">
    <input type="submit" value="Submit" />
</form>
</body>
</html>

CheckCodeServlet.java

package com.learn.session.check;

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 java.io.IOException;

/**
 * User: Admin
 * Date: 2020/7/24
 * Time: 14:59
 * Note:
 */
@WebServlet(name = "checkCodeServlet", urlPatterns = "/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取请求参数: CHECK_CODE_PARAM_KEY
        String paramCode = req.getParameter("CHECK_CODE_PARAM_KEY");

        //2.获取session中的CHECK_CODE_KEY属性值
        String sessionCode = (String)req.getSession().getAttribute("CHECK_CODE_KEY");
        System.out.println("sessionCode = " + sessionCode + ", paramCode = " + paramCode);

        //3.比对。看是否一致,若一致说明验证码正确,若不一致,说明验证码错误
        if (paramCode != null && paramCode.equals(sessionCode)) {
            // 必须使用 session
            req.getSession().setAttribute("message", "YES: 验证码一致");
            resp.sendRedirect(req.getContextPath() + "/learn.session.check/index.jsp");
            return;
        }

        System.out.println("No: 验证码不一致!");

    }
}

ValidateColorServlet.java

package com.learn.session.check;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
 * User: Admin
 * Date: 2020/7/24
 * Time: 11:59
 * Note:
 */
@WebServlet(name = "validateColorServlet", urlPatterns = "/validateColorServlet")
public class ValidateColorServlet extends HttpServlet {
    public static final String CHECK_CODE_KEY = "CHECK_CODE_KEY";

    private static final long serialVersionUID = 1L;

    //设置验证图片的宽度, 高度, 验证码的个数
    private int width = 152;
    private int height = 40;
    private int codeCount = 6;

    //验证码字体的高度
    private int fontHeight = 4;

    //验证码中的单个字符基线. 即:验证码中的单个字符位于验证码图形左上角的 (codeX, codeY) 位置处
    private int codeX = 0;
    private int codeY = 0;

    //验证码由哪些字符组成
    char [] codeSequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz23456789".toCharArray();
//    char[] codeSequence = "^[A-Za-z2-9]".toCharArray();

    //初始化验证码图形属性
    public void init(){
        fontHeight = height - 2;
        codeX = width / (codeCount + 2);
        codeY = height - 4;
    }

    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //定义一个类型为 BufferedImage.TYPE_INT_BGR 类型的图像缓存
        BufferedImage buffImg = null;
        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);

        //在 buffImg 中创建一个 Graphics2D 图像
        Graphics2D graphics = null;
        graphics = buffImg.createGraphics();

        //设置一个颜色, 使 Graphics2D 对象的后续图形使用这个颜色
        graphics.setColor(Color.WHITE);

        //填充一个指定的矩形: x - 要填充矩形的 x 坐标; y - 要填充矩形的 y 坐标; width - 要填充矩形的宽度; height - 要填充矩形的高度
        graphics.fillRect(0, 0, width, height);

        //创建一个 Font 对象: name - 字体名称; style - Font 的样式常量; size - Font 的点大小
        Font font = null;
        font = new Font("", Font.BOLD, fontHeight);
        //使 Graphics2D 对象的后续图形使用此字体
        graphics.setFont(font);

        graphics.setColor(Color.BLACK);

        //绘制指定矩形的边框, 绘制出的矩形将比构件宽一个也高一个像素
        graphics.drawRect(0, 0, width - 1, height - 1);

        //随机产生 15 条干扰线, 使图像中的认证码不易被其它程序探测到
        Random random = null;
        random = new Random();
        graphics.setColor(Color.GREEN);
        for(int i = 0; i < 55; i++){
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x1 = random.nextInt(20);
            int y1 = random.nextInt(20);
            graphics.drawLine(x, y, x + x1, y + y1);
        }

        //创建 randomCode 对象, 用于保存随机产生的验证码, 以便用户登录后进行验证
        StringBuffer randomCode;
        randomCode = new StringBuffer();

        for(int i = 0; i < codeCount; i++){
            //得到随机产生的验证码数字
            String strRand = null;
            strRand = String.valueOf(codeSequence[random.nextInt(36)]);

            //把正在产生的随机字符放入到 StringBuffer 中
            randomCode.append(strRand);

            //用随机产生的颜色将验证码绘制到图像中
            graphics.setColor(Color.BLUE);
            graphics.drawString(strRand, (i + 1)* codeX, codeY);
        }

        //再把存放有所有随机字符的 StringBuffer 对应的字符串放入到 HttpSession 中
        request.getSession().setAttribute(CHECK_CODE_KEY, randomCode.toString());

        System.out.println("随机验证码 = " + randomCode.toString());

        //禁止图像缓存
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        //将图像输出到输出流中
        ServletOutputStream sos = null;
        sos = response.getOutputStream();
        ImageIO.write(buffImg, "jpeg", sos);
        sos.close();
    }
}

3.2 运行结果

代码中间可能有一些页面跳转的逻辑错误。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值