简易购物车——验证码,防止多次提交表单

创建工程

创建dynamic Web Project 取名 shoppingcart
建立工程目录如下:
这里写图片描述

工具类

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * 生成一个随机的验证码图片
 * @author footprint
 *
 */
public final class DrawPicUtils {
    /**
     * 图片宽度
     */
    private int width;
    /**
     * 图片高度
     */
    private int height;
    /**
     * 验证码长度
     */
    private int num;
    /**
     * 验证码的字典
     */
    private String code;
    /**
     * 取随机数的对象
     */
    private static final Random RANDOM = new Random();
    /**
     * 单例模式
     */
    private static DrawPicUtils drawPicUtils;
    /**
     * 私有化构造
     */
    private DrawPicUtils() {
        code = "123456789abcdefghijklmnopqrstvwxyz";
        num = 4;
    }
    /**
     * 单例模式获取对象
     * @return
     */
    public static DrawPicUtils getDrawPicUtils() {
        if(null == DrawPicUtils.drawPicUtils) {
            DrawPicUtils.drawPicUtils = new DrawPicUtils();
        }
        return DrawPicUtils.drawPicUtils;
    }
    /**
     * 设置属性
     * @param width
     * @param height
     * @param num
     * @param code
     */
    public void set(int width, int height, int num, String code) {
        this.width = width;
        this.height = height;
        this.num = num;
        this.code = code;
    }
    /**
     * 设置属性
     * @param width
     * @param height
     */
    public void set(int width, int height) {
        this.width = width;
        this.height = height;
    }


    public int getWidth() {
        return width;
    }
    public void setWidth(int width) {
        this.width = width;
    }
    public int getHeight() {
        return height;
    }
    public void setHeight(int height) {
        this.height = height;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    /**
     * 生成随机验证码
     * @return
     */
    public String generateCheckCode() {
        StringBuffer str = new StringBuffer();
        for(int i = 0; i < num; i++) {
            str.append(code.charAt(DrawPicUtils.RANDOM.nextInt(this.code.length())));
        }
        return str.toString();
    }
    /**
     * 画出需要的图片返回
     * @param checkCode
     * @return
     */
    public BufferedImage generateCheckImage(String checkCode) {
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //获取图片对象的画笔
        Graphics2D graphic = img.createGraphics();
        graphic.setColor(Color.WHITE);
        graphic.fillRect(0, 0, width, height);
        graphic.setColor(Color.BLACK);
        graphic.drawRect(0, 0, width-1, height-1);
        Font font = new Font("宋体", Font.BOLD+Font.ITALIC, (int)(height*0.8));
        graphic.setFont(font);
        for(int i = 0; i < num; i++) {
            graphic.setColor(new Color(RANDOM.nextInt(155), RANDOM.nextInt(155), RANDOM.nextInt(155)));
            graphic.drawString(String.valueOf(checkCode.charAt(i)), i * (width / 4) + 4, (int)(height * 0.8));
        }
        //加一些点
        for(int i = 0; i < (width+height)/2; i++) {
            graphic.setColor(new Color(RANDOM.nextInt(155), RANDOM.nextInt(155), RANDOM.nextInt(155)));
            graphic.drawOval(RANDOM.nextInt(width), RANDOM.nextInt(height), 1, 1);
        }
        //加一些线
        for(int i = 0; i < 2; i++) {
            graphic.setColor(new Color(RANDOM.nextInt(155), RANDOM.nextInt(155), RANDOM.nextInt(155)));
            graphic.drawOval(0, RANDOM.nextInt(height), width, RANDOM.nextInt(height));
        }
        return img;
    }
}

Servlet类



import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
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;

//另一种配置方法
@WebServlet(urlPatterns= {"*.pdo"})
public final class ShopController extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        String mn = req.getServletPath();
        mn = mn.substring(1);
        mn = mn.substring(0, mn.length()-4);
        //利用反射
        try {
            Method method = this.getClass().getDeclaredMethod(mn, HttpServletRequest.class, HttpServletResponse.class);
            method.invoke(this, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

    @SuppressWarnings("unused")
    private void shopping(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pname = req.getParameter("pname");
        req.setAttribute("pname", pname);
        req.getRequestDispatcher("/productdetails.jsp").forward(req, resp);//转发
    }

    @SuppressWarnings("unused")
    private void addcar(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //模拟网络延时 会造成重复提交
        /*
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        */
        String pname = req.getParameter("pname");
        String cc = req.getParameter("checkcode");
        String scc = (String) req.getSession().getAttribute("checkcode");
        if(!cc.equals(scc)) {
            req.setAttribute("pname", pname);
            req.getRequestDispatcher("/productdetails.jsp").forward(req, resp);//转发
            return;
        }
        //防止网页回滚不刷新提交,360浏览器多次提交
        String token = req.getParameter("token");//提交的令牌
        String sessionUuid = (String) req.getSession().getAttribute("uuid");//获取本地session的uuid(token)令牌
        req.getSession().removeAttribute("uuid");//要删除 只能使用一次
        if(token.equals(sessionUuid)) {//令牌有效 加入购物车
            HttpSession session = req.getSession();
            @SuppressWarnings("unchecked")
            List<String> list = (List<String>)session.getAttribute("car");
            if(null == list) {
                list = new ArrayList<>();
            }
            list.add(pname);
            session.setAttribute("car", list);
        }
        resp.sendRedirect(req.getContextPath() + "/productcars.jsp");
    }
    /**
     * 画一张图片验证码
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @SuppressWarnings("unused")
    private void drawCheckCode(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("img/jpg");
        DrawPicUtils pic = DrawPicUtils.getDrawPicUtils();
        pic.set(100, 30);
        String checkCode = pic.generateCheckCode();//获取随机验证码
        req.getSession().setAttribute("checkcode", checkCode);//session需要记录该验证码
        OutputStream os = resp.getOutputStream();//输出流
        ImageIO.write(pic.generateCheckImage(checkCode), "jpg", os);//写入浏览器
    }
}

productcars.jsp

<%@page import="javafx.scene.control.Alert"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>这里是购物车</title>
</head>
<body>
    <%
        @SuppressWarnings("unchecked")
        List<String> list = (List<String>)session.getAttribute("car");
        if(list != null && list.size() > 0) {
            for(String str : list) {
                out.print("<br><br>" + str);
            }
        }
    %>
</body>
</html>

productdetails.jsp ##

<%@page import="java.util.UUID"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>购物车防止重复提交</title>
<script type="text/javascript">
    window.onload = function() {
        var btn = documnet.getElementById("submitbtn");
        btn.onclick = function() {
            this.disabled = true;
            this.parentNode.submit();
        }
    }
</script>
</head>
<body>
    <%
        String uuid= UUID.randomUUID().toString();
        session.setAttribute("uuid", uuid);
    %>

    <br><br>
    该产品的详细信息。
    <br><br>

    <form action="<%=request.getContextPath()%>/addcar.pdo?psso=<%=request.getAttribute("pname")%>" ><!-- 提交一次 -->
        <!--  form中的?pname=<%=request.getAttribute("pname")%>被input的内容覆盖  -->
        <input type="hidden" name="pname" value="<%=request.getAttribute("pname")%>">
        <input type="hidden" name="token" value="<%=uuid %>">  <!-- 再次提交,覆盖之前的 因为都是pname -->

        <input type="text" name="checkcode">
        <br><br>
        <img alt="" src="<%=request.getContextPath()%>/drawCheckCode.pdo">

        <br><br>
        <input id="submitbtn" style="width: 120px; height: 30px; background: red; color: #fff;" type="submit" value="加入购物车" >
    </form>

    <br><br>

    <br><br>


</body>
</html>

productlist.jsp ##

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>简易购物车</title>
</head>
<body>
    <br><br>
    <a href="<%=request.getContextPath()%>/shopping.pdo?pname=联想笔记本">联想笔记本</a>
    <br><br>
    <a href="<%=request.getContextPath()%>/shopping.pdo?pname=华硕主板">华硕主板</a>
    <br><br>
    <a href="<%=request.getContextPath()%>/shopping.pdo?pname=金士顿优盘">金士顿优盘</a>
    <br><br>
    <a href="<%=request.getContextPath()%>/shopping.pdo?pname=飞行棋">飞行棋</a>
    <br><br>
    <a href="<%=request.getContextPath()%>/shopping.pdo?pname=TCL显示屏">TCL显示屏</a>
    <br><br>
    <a href="<%=request.getContextPath()%>/shopping.pdo?pname=火星土豆">火星土豆</a>
    <br><br>

</body>
</html>

代码下载地址

简易购物车

猜你喜欢

转载自blog.csdn.net/footprint01/article/details/82532191