项目实战系列三: 家居购项目 第三部分

🍃后台分页

程序框架图
在这里插入图片描述

1.新建com.zzw.furns.entity.Page

//Page是一个Javabean, 是一个分页的数据模型(包含了分页的各种信息)
//T表示泛型, 因为将来分页模型对应的数据类型是不确定的
public class Page<T> {
    //因为每页显示多少条记录, 是其它地方也可以使用的
    public static final Integer PAGE_SIZE = 3;

    //pageNo 前端页面传来的
    private Integer pageNo;//表示显示当前页[即显示第几页]
    private Integer pageSize = PAGE_SIZE;//表示每页显示几条记录

    //pageTotal 计算得到的
    private Integer pageTotal;//表示共有多少页

    //totalRow 是可以从数据库来的, 由DAO来完成
    private Integer totalRow;//表示共有多少条记录

    //items 从数据库DB来的, 由DAO完成
    private List<T> items;//表示当前页,要显示的数据
    private String url;//分页导航的字符串

    public Page() {
    }

    public Page(Integer pageSize, Integer pageNo) {
        this.pageSize = pageSize;
        this.pageNo = pageNo;
    }
}

2.参考

在这里插入图片描述

3.修改FurnDao.java

//Page的哪些属性是可以从数据库中获取的, 就把获取这个属性的任务放在DAO层
public int getTotalRow();

/**
 * 获取当前页要显示的数据
 *
 * @param begin    表示当前数据从第几条记录开始获取, 从0开始计算
 * @param pageSize 表示取出多少条记录
 * @return
 */
public List<Furn> getPageItems(int begin, int pageSize);

4.修改FurnDaoImpl.java

@Override
public int getTotalRow() {
    String sql = "SELECT COUNT(*) FROM furn";
    //return (Integer) queryScalar(sql);//=>会报cast异常
    //java.lang.Long cannot be cast to java.lang.Integer
    return ((Number) queryScalar(sql)).intValue();
}

@Override
public List<Furn> getPageItems(int begin, int pageSize) {
    String sql = "select id, `name`,business,price,saleNum,inventory,image_path from furn limit ?,?";
    return queryMany(sql, Furn.class, begin, pageSize);
}

5.测试FurnDaoTest.java

@Test
public void getTotalRow() {
    int totalRow = furnDao.getTotalRow();
    System.out.println(totalRow);
}

@Test
public void getPageItems() {
    List<Furn> pageItems = furnDao.getPageItems(1, 5);
    for (Furn furn : pageItems) {
        System.out.println(furn);
    }
}

6.修改FurnService.java

/**
 * 根据传入的 pageNo和 pageSize, 返回对应的page对象
 * @param pageNo
 * @param pageSize
 * @return
 */
public Page<Furn> page(int pageNo, int pageSize);

7.修改FurnServiceImpl.java

@Override
public Page<Furn> page(int pageNo, int pageSize) {
    //先创建一个page对象, 然后根据实际情况, 填充属性
    Page<Furn> page = new Page<>();
    page.setPageNo(pageNo);//(1)表示显示当前页[即显示第几页]
    page.setPageSize(pageSize);//(2)表示每页显示几条记录
    int totalRow = furnDAO.getTotalRow();
    page.setTotalRow(totalRow);//(3)表示共有多少条记录
    //比如 6 2 => 6 / 2 = 3
    //比如 5 2 => 5 / 2 = 2
    //比如 7 2 => 7 / 2 = 3
    //比如 0 2 => 0 / 2 = 0
    int pageTotal = totalRow / pageSize;
    if (totalRow % pageSize > 0) {
        ++pageTotal;
    }
    page.setPageTotal(pageTotal);//(4)表示共有多少页
    //比如: pageNo=1, pageSize=3 => begin=1
    //比如: pageNo=2, pageSize=3 => begin=4
    //比如: pageNo=3, pageSize=2 => begin=4
    //注意: 这里隐藏了一个坑, 此刻还看不到, 之后会暴露
    int begin = (pageNo - 1) * pageSize;
    List<Furn> pageItems = furnDAO.getPageItems(begin, pageSize);
    page.setItems(pageItems);//(5)表示当前页,要显示的数据
    //还差一个url[分页导航], 后面需要
    return page;
}

8.测试FurnServiceTest.java

@Test
public void page() {
    //小技巧: 如果我们需要看一个对象, 这个对象比较复杂, 可以debug看对象
    Page<Furn> page = furnService.page(2, 2);
    System.out.println("page ===> " + page);
}

在这里插入图片描述

9.修改src/com/zzw/furns/web/FurnServlet.java, web层获取page对象

protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    int pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);
    int pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);

    //调用service, 获取page对象
    Page<Furn> page = furnService.page(pageNo, pageSize);

    //将page放入到request域
    req.setAttribute("page", page);
    //请求转发到家居管理页面
    req.getRequestDispatcher("/views/manage/furn_manage.jsp")
            .forward(req, resp);
}

10.修改manage_menu.jsp, 取缔list方法

<div class="header-bottom-set dropdown">
    <a href="manage/furnServlet?action=page">家居管理</a>
</div>

11.测试, 管理员登陆后, 点击家居管理
在这里插入图片描述

12.修改web/views/manage/furn_manage.jsp

<c:forEach items="${requestScope.page.items}" var="item">
<tr>
    <td class="product-thumbnail">
        <a href="#"><img class="img-responsive ml-3" src="${item.imagePath}"
                         alt=""/></a>
    </td>
    <td class="product-name"><a href="#">${item.name}</a></td>
    <td class="product-name"><a href="#">${item.business}</a></td>
    <td class="product-price-cart"><span class="amount">${item.price}</span></td>
    <td class="product-quantity">
        ${item.saleNum}
    </td>
    <td class="product-quantity">
        ${item.inventory}
    </td>
    <td class="product-remove">
        <a href="manage/furnServlet?action=display&id=${item.id}"><i class="icon-pencil"></i></a>
        <a furnName="${item.name}" href="manage/furnServlet?action=del&id=${item.id}">
            <i class="icon-close"></i>
        </a>
    </td>
</tr>
</c:forEach>

🍅后台分页导航

需求分析

  1. 管理员进入到家居管理后台页面
  2. 可以通过分页导航条来进行分页显示
  3. 完成上页, 下页, 显示共多少页
  4. 点击分页导航, 可以显示对应页的家居信息
  5. 在管理员进行修改, 删除, 添加后, 能够回显原来操作所在页面的数据

程序框架图

在这里插入图片描述

1.粘贴首页的分页导航代码

<!--  Pagination Area Start -->
<div class="pro-pagination-style text-center mb-md-30px mb-lm-30px mt-6" data-aos="fade-up">
    <ul>
        <li><a href="#">首页</a></li>
        <li><a href="#">上页</a></li>
        <li><a class="active" href="#">3</a></li>
        <li><a href="#">4</a></li>
        <li><a href="#">5</a></li>
        <li><a href="#">下页</a></li>
        <li><a href="#">末页</a></li>
        <li><a>共10页</a></li>
        <li><a>共90记录</a></li>
    </ul>
</div>
<!--  Pagination Area End -->

2.放到web/views/manage/furn_manage.jsp, 并做修改

<!--  Pagination Area Start -->
<div class="pro-pagination-style text-center mb-md-30px mb-lm-30px mt-6" data-aos="fade-up">
    <ul>
        <%--如果当前页 > 1, 就显示首页和上一页--%>
        <li><a style="${requestScope.page.pageNo == 1 ? 'pointer-events: none; color: lightgray' : ''}"
               href="manage/furnServlet?action=page&pageNo=1&pageSize=${requestScope.page.pageSize}">首页</a>
        </li>
        <li><a style="${requestScope.page.pageNo == 1 ? 'pointer-events: none; color: lightgray' : ''}"
               href="manage/furnServlet?action=page&pageNo=${requestScope.page.pageNo - 1}&pageSize=${requestScope.page.pageSize}">上一页</a>
        </li>

        <%--显示所有的分页数 先确定开始的页数 begin 1; 再确定结束的页数 end=>pageTotal--%>
        <%--最多显示10, 这里涉及算法--%>
        <c:set scope="page" var="begin" value="1"></c:set>
        <c:set scope="page" var="end" value="${requestScope.page.pageTotal}"></c:set>
        <%--循环显示--%>
        <c:forEach begin="${pageScope.begin}" end="${pageScope.end}" var="i"><%--总的页数--%>
            <%--如果i是当前页, 就使用class="active"来修饰--%>
            <li><a class="${i eq requestScope.page.pageNo ? "active" : ""}"
                   href="manage/furnServlet?action=page&pageNo=${i}&pageSize=${requestScope.page.pageSize}">${i}</a>
            </li>
        </c:forEach>

        <%--如果当前页 < 总的页数, 就显示末页和下一页--%>
        <li>
            <a style="${requestScope.page.pageNo == requestScope.page.pageTotal ? 'pointer-events: none; color: lightgray' : ''}"
               href="manage/furnServlet?action=page&pageNo=${requestScope.page.pageNo + 1}&pageSize=${requestScope.page.pageSize}">下一页</a>
        </li>
        <li>
            <a style="${requestScope.page.pageNo == requestScope.page.pageTotal ? 'pointer-events: none; color: lightgray' : ''}"
               href="manage/furnServlet?action=page&pageNo=${requestScope.page.pageTotal}&pageSize=${requestScope.page.pageSize}">末页</a>
        </li>

        <li><a>共${requestScope.page.pageTotal}</a></li>
        <li><a>共${requestScope.page.totalRow}记录</a></li>
    </ul>
</div>
<!--  Pagination Area End -->

3.修改后返回原页面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.删除后返回原页面

在这里插入图片描述
在这里插入图片描述

5.添加后返回原页面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

🍃首页分页

🍅首页分页导航

需求分析

  1. 顾客进入首页页面
  2. 分页显示家居
  3. 正确显示分页导航条, 即功能完善, 可以使用

程序框架图

在这里插入图片描述

1.新建src/com/zzw/furns/web/CustomerFurnServlet.java, 使用注解方式

@WebServlet(urlPatterns = "/customerFurnServlet")
public class CustomerFurnServlet extends BasicServlet {

    private FurnService furnService = new FurnServiceImpl();
    
    protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Integer pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);
        Integer pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);

        Page<Furn> page = furnService.page(pageNo, pageSize);
        //保存到request域
        req.setAttribute("page", page);
        //请求转发到/views/customer/index.jsp
        req.getRequestDispatcher("/views/customer/index.jsp").forward(req, resp);
    }
}

2.将项目页面移到web/views/customer目录下.

3.新建web/index.jsp, 负责请求转发.

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.直接请求CustomerFurnServlet, 获取网站首页要显示的分页数据. 类似我们网站的入口页面

在这里插入图片描述

5.分页显示数据

<c:forEach items="${requestScope.page.items}" var="item">
    <div class="col-lg-3 col-md-6 col-sm-6 col-xs-6 mb-6" data-aos="fade-up"
         data-aos-delay="200">
        <!-- Single Prodect -->
        <div class="product">
            <div class="thumb">
                <a href="shop-left-sidebar.jsp" class="image">
                    <img src="${item.imagePath}" alt="Product"/>
                    <img class="hover-image" src="assets/images/product-image/5.jpg"
                         alt="Product"/>
                </a>
                <span class="badges">
                    <span class="new">New</span>
                </span>
                <div class="actions">
                    <a href="#" class="action wishlist" data-link-action="quickview"
                       title="Quick view" data-bs-toggle="modal"
                       data-bs-target="#exampleModal"><i
                            class="icon-size-fullscreen"></i></a>
                </div>
                <button title="Add To Cart" class=" add-to-cart">Add
                    To Cart
                </button>
            </div>
            <div class="content">
                <h5 class="title">
                    <a href="shop-left-sidebar.jsp">Simple 北欧${item.name} </a></h5>
                <span class="price">
                    <span class="new">家居: ${item.name}</span>
                </span>
                <span class="price">
                    <span class="new">厂商: ${item.business}</span>
                </span>
                <span class="price">
                    <span class="new">价格: ¥${item.price}</span>
                </span>
                <span class="price">
                    <span class="new">销量: ${item.saleNum}</span>
                </span>
                <span class="price">
                    <span class="new">库存: ${item.inventory}</span>
                </span>
            </div>
        </div>
    </div>
</c:forEach>

6.首页分页导航

<c:set var="pageNo" value="${requestScope.page.pageNo}"></c:set>
<c:set var="pageTotal" value="${requestScope.page.pageTotal}"></c:set>
<c:set var="pageSize" value="${requestScope.page.pageSize}"></c:set>
<!--  Pagination Area Start -->
<div class="pro-pagination-style text-center mb-md-30px mb-lm-30px mt-6" data-aos="fade-up">
    <ul>
        <li><a href="customerFurnServlet?action=page&pageNo=1&pageSize=${pageSize}">首页</a></li>
        <li><a style="${pageNo <= 1 ? 'pointer-events: none; color: lightgray' : ''}" href="customerFurnServlet?action=page&pageNo=${pageNo - 1}&pageSize=${pageSize}">上页</a></li>
        <c:forEach begin="1" end="${pageTotal}" var="i">
            <li><a class="${pageNo == i ? 'active' : ''}" href="customerFurnServlet?action=page&pageNo=${i}&pageSize=${pageSize}">${i}</a></li>
        </c:forEach>
        <li><a style="${pageNo >= pageTotal ? 'pointer-events: none; color: lightgray;': ''}" href="customerFurnServlet?action=page&pageNo=${pageNo + 1}&pageSize=${pageSize}">下页</a></li>
        <li><a href="customerFurnServlet?action=page&pageNo=${pageTotal}&pageSize=${pageSize}">末页</a></li>
        <li><a>共${pageTotal}</a></li>
        <li><a>共${requestScope.page.totalRow}记录</a></li>
    </ul>
</div>
<!--  Pagination Area End -->

🍅首页搜索

需求分析
1.顾客进入首页页面
2.点击搜索按钮, 可以输入家居名
3.正确显示分页导航条, 并且要求在分页时, 保留上次搜索条件

程序框架图

在这里插入图片描述

代码实现
1.修改com.zzw.furns.FurnDAO, 模糊查询👉

//根据name查询furn对象的个数
public int getTotalQuantityByName(String name);

//根据begin,pageSize,name查询furn对象
public List<Furn> getPageItemsByName(int begin, int pageSize, String name);

2.修改com.zzw.furns.impl.FurnDaoImpl

@Override
public int getTotalQuantityByName(String name) {
    String sql = "SELECT COUNT(*) FROM furn WHERE `name` LIKE ?";
    return ((Number) queryScalar(sql, "%" + name + "%")).intValue();
}

@Override
public List<Furn> getPageItemsByName(int begin, int pageSize, String name) {
	//mysql中, limit默认从0开始
    String sql = "SELECT id, `name`, business, price, saleNum, " +
            "inventory, image_path as imagePath FROM furn WHERE `name` LIKE ? Limit ?, ?";
    return queryMany(sql, Furn.class, "%" + name + "%", begin, pageSize);
}

3.测试, 修改FurnDaoTest

@Test
public void getTotalQuantityByName() {
    System.out.println(furnDAO.getTotalQuantityByName("小台灯"));
}

@Test
public void getPageItemsByName() {
    List<Furn> furns = furnDAO.getPageItemsByName(3, 2, "小台灯");
    for (Furn furn : furns) {
        System.out.println(furn);
    }
}

4.修改com.zzw.furns.FurnService

//根据传入的pageNo,pageSize,name, 返回对应的page对象
public Page<Furn> pageByName(int pageNo, int pageSize, String name);

5.修改com.zzw.furns.impl.FurnServiceImpl

@Override
public Page<Furn> pageByName(int pageNo, int pageSize, String name) {
    //先创建一个page对象, 然后根据实际情况, 填充属性
    Page<Furn> page = new Page<>();
    page.setPageNo(pageNo);//(1)表示显示当前页[即显示第几页]
    page.setPageSize(pageSize);//(2)表示每页显示几条记录
    int countByName = furnDAO.getTotalQuantityByName(name);
    page.setTotalRow(countByName);//(3)根据家居名 返回总的记录数
    //比如 6 2 => 6 / 2 = 3
    //比如 5 2 => 5 / 2 = 2
    //比如 7 2 => 7 / 2 = 3
    //比如 0 2 => 0 / 2 = 0
    int pageTotal = countByName / pageSize;//计算得到总的页数
    if (countByName % pageSize > 0) {
        ++pageTotal;
    }
    page.setPageTotal(pageTotal);//(4)表示共有多少页
    //比如: pageNo=1, pageSize=3 => begin=1
    //比如: pageNo=3, pageSize=2 => begin=4
    //注意: 这里隐藏了一个坑, 此刻还看不到, 之后会暴露
    int begin = (pageNo - 1) * pageSize;
    List<Furn> pageItems = furnDAO.getPageItemsByName(begin, pageSize, name);
    page.setItems(pageItems);//(5)表示当前页,要显示的数据
    //还差一个url[分页导航], 后面需要
    return page;
}

6.测试,修改com.zzw.furns.impl.FurnServiceTest

@Test
public void pageByName() {
    Page<Furn> page = furnService.pageByName("蚂蚁", 1, 5);
    System.out.println(page);
}

6.web层 - 修改src/com/zzw/furns/web/CustomerFurnServlet.java, 增加pageByName方法

protected void pageByName(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //获取家居名
    //1.如果参数有name, 但是没有值, 这时接收到的是空串, 查询所有家居信息
    //2.如果参数name都没有, 接收到的是null
    String name = req.getParameter("name");
    name = (name == null) ? "" : name;
    int pageNo =
            DataUtils.parseInt(req.getParameter("pageNo"), 1);
    int pageSize =
            DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);
    //调用service方法, 获取page对象
    Page<Furn> page = furnService.pageByName(pageNo, pageSize, name);
    //将家居名[搜索条件]封装到page对象的url属性
    StringBuilder url = new StringBuilder("customerFurnServlet?action=pageByName");
    if (!"".equals(name)) {//如果name不为"", 则拼接name参数
        url.append("&name=").append(name);
    }
    page.setUrl(url.toString());
    //将page放入到request域
    req.setAttribute("page", page);
    //请求转发到index.jsp
    req.getRequestDispatcher("/views/customer/index.jsp").forward(req, resp);
}

7.修改web/views/customer/index.jsp

<div class="dropdown_search">
    <form class="action-form" action="customerFurnServlet">
        <input type="hidden" name="action" value="pageByName">
        <input type="hidden" name="pageSize" value="${param.pageSize}">
        <input class="form-control" name="name" placeholder="Enter your search key" type="text">
        <button class="submit" type="submit"><i class="icon-magnifier"></i></button>
    </form>
</div>

8.修改web/views/customer/index.jsp导航栏

<c:set var="pageNo" value="${requestScope.page.pageNo}"></c:set>
<c:set var="pageTotal" value="${requestScope.page.pageTotal}"></c:set>
<c:set var="pageSize" value="${requestScope.page.pageSize}"></c:set>
<c:set var="url" value="${requestScope.page.url}"></c:set>
<!--  Pagination Area Start -->
<div class="pro-pagination-style text-center mb-md-30px mb-lm-30px mt-6" data-aos="fade-up">
    <ul>
        <li><a href="${url}&pageNo=1&pageSize=${pageSize}">首页</a></li>
        <li><a style="${pageNo <= 1 ? 'pointer-events: none; color: lightgray' : ''}" href="${url}&pageNo=${pageNo - 1}&pageSize=${pageSize}">上页</a></li>
        <c:forEach begin="1" end="${pageTotal}" var="i">
            <li><a class="${pageNo == i ? 'active' : ''}" href="${url}&pageNo=${i}&pageSize=${pageSize}">${i}</a></li>
        </c:forEach>
        <li><a style="${pageNo >= pageTotal ? 'pointer-events: none; color: lightgray;': ''}" href="${url}&pageNo=${pageNo + 1}&pageSize=${pageSize}">下页</a></li>
        <li><a href="${url}&pageNo=${pageTotal}&pageSize=${pageSize}">末页</a></li>
        <li><a>共${pageTotal}页</a></li>
        <li><a>共${requestScope.page.totalRow}记录</a></li>
    </ul>
</div>
<!--  Pagination Area End -->

🍅两个奇怪的问题

1.点击家居管理, 发出两个请求

在这里插入图片描述
在这里插入图片描述

manage_menu.jspfurn_manage.jsp

在这里插入图片描述
抓包
在这里插入图片描述

原因: furn_manage.jsp有图片url

在这里插入图片描述

2.首页分页出现问题

在这里插入图片描述
在这里插入图片描述

原因

在这里插入图片描述

🍅会员显示登录名

需求分析
1.会员登陆成功
2.如果登陆成功后返回首页面, 显示订单管理和安全退出
3.如果用户没有登陆过, 首页就显示登录注册, 后台管理超链接

程序框架图

在这里插入图片描述

1.修改src/com/zzw/furns/web/MemberServlet.java

if (memberService.login(member)) {//登陆成功
    System.out.println("登陆成功");
    //将member存入到session域
    request.getSession().setAttribute("member", member);
    if ("admin".equals(member.getUsername())) {
        //管理员登录成功
        request.getRequestDispatcher("/views/manage/manage_menu.jsp")
                .forward(request, response);
    } else {
        //普通用户登陆成功
        request.getRequestDispatcher("/views/member/login_ok.jsp")
                .forward(request, response);
    }
}

2.修改web/views/customer/index.jsp

<!-- Single Wedge Start -->
<c:if test="${sessionScope.member != null}">
    <div class="header-bottom-set dropdown">
        欢迎: ${sessionScope.member.username}
    </div>
    <div class="header-bottom-set dropdown">
        <a href="#">订单管理</a>
    </div>
        <div class="header-bottom-set dropdown">
        <a href="#">安全退出</a>
    </div>
</c:if>
<c:if test="${sessionScope.member == null}">
    <div class="header-bottom-set dropdown">
        <a href="views/member/login.jsp">登录|注册</a>
    </div>
    <div class="header-bottom-set dropdown">
        <a href="views/manage/manage_login.jsp">后台管理</a>
    </div>
</c:if>
<!-- Single Wedge End -->

🍅注销登录

思路分析
1.用户登录成功后
2.login_ok.jsp, 点击安全退出, 注销登录
3.返回首页, 也可点击安全退出, 注销登录

程序框架图

在这里插入图片描述

代码实现
1.修改src/com/zzw/furns/web/MemberServlet.java,增加方法logout

//安全退出
protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("member 被调用...");
    HttpSession session = req.getSession();
    //让当前session立即无效
    session.invalidate();
    //默认访问index.jsp 首页面
    //req.getContextPath() http://localhost://jiaju_mall/
    resp.sendRedirect(req.getContextPath());
}

2.修改web/views/customer/index.jsp

<div class="header-bottom-set dropdown">
    <a href="memberServlet?action=logout">安全退出</a>
</div>

🍅验证码

表单重复提交情况

  1. 提交完表单. 服务器使用请求转发进行页面跳转. 用户刷新(F5), 会发起最后一次的请求, 造成表单重复提交问题. 解决:用重定向.
  2. 用户正常提交, 由于网络延迟等原因, 未收到服务器的响应. 这时, 用户着急多点了几次提交操作, 也会造成表单重复提交. 解决: 验证码
  3. 用户正常提交, 服务器也没有延迟, 但是提交完成后, 用户回退浏览器. 重新提交, 也会造成表单重复提交. 解决: 验证码
  4. 恶意注册, 使用可以批量发送Http的工具, 比如 Postman, Jemeter等, 使用验证码防护

程序框架图
在这里插入图片描述

代码实现
1.引入kaptcha-2.3.2.jar包

2.web层, 配置KaptchaServlet

<servlet>
    <servlet-name>KaptchaServlet</servlet-name>
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>KaptchaServlet</servlet-name>
    <url-pattern>/kaptchaServlet</url-pattern>
</servlet-mapping>

在这里插入图片描述
在这里插入图片描述

3.KAPTCHA_SESSION_KEY是一个常量, 使用前需要导入

import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;

在这里插入图片描述

4.修改前端页面web/views/member/login.jsp

<input type="text" id="captchaText" name="captcha" style="width: 50%"
       placeholder="验证码"/>  <img id="captcha" alt="" width="150px" src="kaptchaServlet">

5.测试

在这里插入图片描述

6.增加js代码, 点击图片更换验证码

$("#captcha").click(function () {
    $(this).attr("src", "kaptchaServlet?zzw=" + new Date());
});

7.增加校验 ⇒ 点击提交, 验证码不能为空

var captchaText = $("#captchaText").val().trim();
if (captchaText == "" || captchaText == null) {
    $("span.errorMsg").text("验证码不能为空!");
    return false;
}

8.修改MemberServlet

protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //todo 构建member
    
    //获取用户提交的验证码
    String captcha = request.getParameter("captcha");
    //从session中获取 生成的验证码
    HttpSession session = request.getSession();
    String token = (String) session.getAttribute(KAPTCHA_SESSION_KEY);
    //立即删除session中的验证码, 防止该验证码重复使用
    session.removeAttribute(KAPTCHA_SESSION_KEY);

    //如果token不为空, 并且和用户提交的验证码保持一致, 就继续
    if (token != null && token.equalsIgnoreCase(captcha)) {
    
        //todo 判断用户名是否可用 可用注册用户 不可用返回注册页面
        
    } else {
        request.setAttribute("msg", "验证码不正确");
        request.setAttribute("username", username);//回显用户名
        request.setAttribute("password", password);//回显密码
        request.setAttribute("email", email);//回显邮件
        request.setAttribute("active", "register_tab");
        request.getRequestDispatcher("/views/member/login.jsp")
                .forward(request, response);
    }
}
  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~ 小团子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值