JavaWeb实战(1)(重点:分页查询、jstl标签与jsp、EL表达式、Bootstrap组件搭建页面、jdbc)

目录

一、jstl标签。

(1)基本概念。

(2)使用前提。

(3)"<%...%>"与"<%=%>"。

(4)使用jstl标签的步骤。

1、导入对应jar包。

2、引入核心标签库。(core)

3、在jsp页面中使用jstl标签(常见标签)。

二、分页查询。

(1)使用循环拿对象,利用EL表达式显示属性。

(2)通过Bootstrap获取分页栏组件快速渲染页面(jsp)。

(3)分页查询思路分析。

1、页面(前端)需要传什么参数?

2、页面需要接收什么参数。

3、Page类。

4、sql语句的书写。

三、正式代码书写。

(1)链接到对应Servlet。

(2)queryUsersByPageServlet类。

(3)service层接口。

(4)serviceImpl实现类。

(5)dao层接口。(数据访问层接口)

(6)dao层实现类。

(7)初步测试其功能是否正常。

(8)完善设计要求。

1、当前所在页为:1。

2、当前所在页为:最后一页。

3、位于当前页时。

4、显示页数(如:1、2...)。

5、测试结果。


一、jstl标签。

(1)基本概念。
  • JSTL(JavaServer Pages Standard Tag Library)是一个为JavaServerPages (JSP) 技术提供的标签库。
  • 它允许开发者在JSP页面中使用标签来执行常见的功能。如条件判断、循环等。
(2)使用前提。
  • 导入两个jar包。

  • 或使用Maven添加对应的依赖也能够使用。
(3)"<%...%>"与"<%=%>"。
  • 简单说:jsp页面就是让Java代码能够在html页面书写。
java 复制代码
<%
   //java方法能写的代码, 都可以在这里写
%>
<%=表达式 %>  把表达式的结果在客户端页面显示  使用EL表达式替换
(4)使用jstl标签的步骤。
1、导入对应jar包。
2、引入核心标签库。(core)
  • 注意:"uri"一定要选择对应的正确核心库标签。
  • 它也叫"c标签"。
  • @tag:目标,lib:库。
java 复制代码
<%--引入JSTL核心标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3、在jsp页面中使用jstl标签(常见标签)。
  • 循环:<c:forEach>。
  • if判断:<c:if>。
  • if...else:<choose>。类似于MySQL中的case一样。

二、分页查询。

(1)使用<c:forEach>循环拿对象,利用EL表达式显示属性。
  • 使用"<%%>"、"<%=%>"嵌套代码看着很混乱。
  • 则可以使用jstl标签完成操作!。
java 复制代码
<%
            //从request域拿到数据
            List<UserInfo> users = (List<UserInfo>) request.getAttribute("users");
            for (UserInfo user : users) {

        %>
        <tr>
            <td><%=user.getId()%></td>
            <td><%=user.getName()%></td>
            <td><%=user.getGender()%></td>
            <td><%=user.getAge()%></td>
            <td><%=user.getAddress()%></td>
            <td><%=user.getEmail()%></td>
            <td><%=user.getQq()%></td>
            <td>
                <a class="btn btn-default btn-sm" href="/users/update?id=<%=user.getId()%>">修改</a>&nbsp;
                <a class="btn btn-default btn-sm" href="/users/delete?id=<%=user.getId()%>">删除</a></td>
        </tr>
        <%
            }
        %>
  • 使用<c:forEach>标签。

  • 从所有域中搜索键名"users"值。拿到应该List<UserInfo>集合。

java 复制代码
<c:forEach items="${users}" var="user" varStatus="s">
  • items相当于Javaforeach循环中的"for(String str:str(数组/集合))"的数据集合。

  • var相当于某个体。

  • varStatus代表当前状态(如:位于第几行?)

java 复制代码
<table border="1" class="table table-bordered table-hover">
        <tr class="success">
            <th>编号</th>
            <th>姓名</th>
            <th>性别</th>
            <th>年龄</th>
            <th>籍贯</th>
            <th>QQ</th>
            <th>邮箱</th>
            <th>操作</th>
        </tr>
        <c:forEach items="${users}" var="user" varStatus="s">
            <tr>
                <td>${s.count}</td>
                <td>${user.name}</td>
                <td>${user.gender}</td>
                <td>${user.age}</td>
                <td>${user.address}</td>
                <td>${user.email}</td>
                <td>${user.qq}</td>
                <td>
                    <a class="btn btn-default btn-sm" href="/users/update?id=${user.id}">修改</a>&nbsp;
                    <a class="btn btn-default btn-sm" href="/users/delete?id=${user.id}">删除</a></td>
            </tr>
        </c:forEach>
    </table>

(2)通过Bootstrap获取分页栏组件快速渲染页面(jsp)。

  • 渲染后。

(3)分页查询思路分析。
1、页面(前端)需要传什么参数?
  • 页码。(当前位于第几页)
  • 页容量。(每页显示的数据条数)
  • 带条件的分页查询。
2、页面需要接收什么参数。
  • 记录。(根据分页或条件查询的数据记录)
  • 总记录。(查询的所有数据有多少条?)
  • 总页数(最终分页)。(根据总记录与页容量计算!)
  • 页码。
  • 页容量。
  • 将上面5个数据封装到Page类对象中,并存在域中!

  • 将上面的5个数据封装成一个类Page。简单且实用。(面向对象)
3、Page类。

  • totalPage(总页数)不能提供setter()方法。因为这个是根据总记录数和页容量进行计算。

  • 如果有40条数据。每一页显示5条。则总页数 =8页。
  • 如果有41条数据。每一页显示5条。则总页数 = 9页。
  • 总页数 = 总记录数 % 页容量 == 0? 总记录数/页容量: 总记录数/页容量 +1。
java 复制代码
public Long getTotalPage() {
        //总页数 = 总记录数 % 页容量 == 0? 总记录数/页容量:  总记录数/页容量 +1
        return count%pageSize==0?count/pageSize:(count/pageSize+1);
    }
java 复制代码
package com.fs.entity;

import java.util.List;

/**
 * @Title: Page
 * @Author HeYouLong
 * @Package com.fs.entity
 * @Date 2024/11/29 下午4:48
 * @description: 分页实体类
 */
public class Page<T> {
    private Long count ; //总记录数
    private Long totalPage; //总页数
    private Integer pageIndex; //当前页码
    private Integer pageSize;  //每页显示记录数(页容量)
    private List<T> records;  //

    public Long getCount() {
        return count;
    }

    public void setCount(Long count) {
        this.count = count;
    }

    public Long getTotalPage() {
        return count % pageSize == 0 ? count / pageSize : (count / pageSize) + 1;
    }

    /*public void setTotalPage(Long totalPage) {
        this.totalPage = totalPage;
    }*/

    public Integer getPageIndex() {
        return pageIndex;
    }

    public void setPageIndex(Integer pageIndex) {
        this.pageIndex = pageIndex;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public List<T> getRecords() {
        return records;
    }

    public void setRecords(List<T> records) {
        this.records = records;
    }
}
4、sql语句的书写。
  • sql语句需要写两条。调用两个方法。
  • 记录(根据分页得到的查询结果)。
  • 求当前页记录: select * from .... limit 开始序号,页容量。

  • 总记录(count)。
  • 求总记录数: select count(1) from...

  • limit的开始序号与页容量。
  • 开始序号 = (页码-1)*页容量。
  • 如40条数据。每页5条。
  • 页码 开始序号
  • 1 0
  • 2 5
  • 3 10

三、正式代码书写。

(1)链接到对应Servlet。


(2)queryUsersByPageServlet类。
  • 具体代码。具体解释在注释中。
java 复制代码
package com.fs.web;

import com.fs.entity.Page;
import com.fs.entity.UserInfo;
import com.fs.service.UserInfoService;
import com.fs.service.impl.UserInfoServiceImpl;

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;
import java.util.List;

/**
 * @Title: queryUsersByPageServlet
 * @Author HeYouLong
 * @Package com.fs.web
 * @Date 2024/11/29 下午5:01
 * @description: 分页查询用户信息
 */
@WebServlet("/users/queryUsersByPage")
public class queryUsersByPageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.设置编码
        resp.setContentType("text/html;charset=utf-8");
        //获取请求参数
        //页码
        String pageIndexStr = req.getParameter("pageIndex");
        int pageIndex = Integer.parseInt(pageIndexStr);
        //默认设置页容量=2
        int pageSize = 2;
        //2.调用业务层
        UserInfoService userInfoService = new UserInfoServiceImpl();
        //调用分页查询方法
        //注意返回的是一个封装了5个数据的Page对象
        Page<UserInfo> page = userInfoService.queryByPage(pageIndex,pageSize);

        //将分页查询的所有用户信息保存到request域中
        req.setAttribute("page",page);
        //请求转发
        req.getRequestDispatcher("/users/list.jsp").forward(req,resp);
    }

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

    }
}
  • 注意修改:将循环的EL表达式改成"page(对象)",并且是它的属性查询后的记录数(records)。

(3)service层接口。
java 复制代码
/**
     * 分页查询
     * @param pageIndex
     * @param pageSize
     * @return
     */
    Page<UserInfo> queryByPage(int pageIndex, int pageSize);
(4)serviceImpl实现类。
  • 注意这里需要写两个dao层方法。
  • 1.查询总记录数。2.查询当前分页条件下的记录。(数据)
java 复制代码
@Override
    public Page<UserInfo> queryByPage(int pageIndex, int pageSize) {
        UserInfoDao userInfoDao = new UserInfoDaoImpl();
        //1.查询总记录数
        long count = userInfoDao.count();
        // 2.查询当前分页的记录(数据)
        List<UserInfo> records =userInfoDao.selectByPage(pageIndex,pageSize);
        //包装成page对象
        Page<UserInfo> page = new Page<>();
        page.setPageIndex(pageIndex);
        page.setPageSize(pageSize);
        page.setCount(count);
        page.setRecords(records);
        return page;
    }
}
(5)dao层接口。(数据访问层接口)
java 复制代码
/**
     * 查询总记录数
     * @return
     */
    long count();

    /**
     * 分页查询
     * @param pageIndex
     * @param pageSize
     * @return
     */
    List<UserInfo> selectByPage(int pageIndex, int pageSize);
  • 因为查询的结果是返回是一个基本数据类型的数据。
  • 所以使用ScalarHandler类接收参数。
(6)dao层实现类。
java 复制代码
@Override
    public long count() {
        Connection conn = null;
        try {
            conn = JdbcUtil.getConnection();
            QueryRunner queryRunner = new QueryRunner();
            String sql = "select count(1) from tb_userinfo";
            //查询单个值,resultSet处理器 ScalarHandler
            return queryRunner.query(conn,sql,new ScalarHandler<Long>());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtil.close(conn);
        }
    }

    @Override
    public List<UserInfo> selectByPage(int pageIndex, int pageSize) {
        Connection conn = null;
        try {
            conn = JdbcUtil.getConnection();
            QueryRunner queryRunner = new QueryRunner();
            String sql = "select * from tb_userinfo limit ?,?";
            return queryRunner.query(conn,sql,new BeanListHandler<>(UserInfo.class),(pageIndex-1)*pageSize,pageSize);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtil.close(conn);
        }
    }
(7)初步测试其功能是否正常。
  • 先登录。
  • 进入首页。点击查询用户信息按钮。
  • 功能正常。
  • 现在对下面的分页栏进行修改。增加总记录数、总页数显示。

(8)完善设计要求。

(注意本代码中使用bootstrap组件快速开发)

1、当前所在页为:1。
  • 不显示上一页按钮。点击下一页跳到下一页数据。
  • 通过<c:if>标签进行判断。
2、当前所在页为:最后一页。
  • 不显示下一页按钮。点击上一页跳到上一页数据。
3、位于当前页时。
  • 从超链接变成不能点击的。以单纯文本显示。
  • 所在按钮背景变"蓝"。
4、显示页数(如:1、2...)。
  • 根据当前的分页总数计算。
  • 根据<c:forEach>进行普通循环。

java 复制代码
<%@ page import="com.fs.entity.UserInfo" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入JSTL核心标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
    <!-- 指定字符集 -->
    <meta charset="utf-8">
    <!-- 使用Edge最新的浏览器的渲染方式 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
    width: 默认宽度与设备的宽度相同
    initial-scale: 初始的缩放比,为1:1 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>用户信息管理系统</title>

    <!-- 1. 导入CSS的全局样式 -->
    <link href="../css/bootstrap.min.css" rel="stylesheet">
    <!-- 2. jQuery导入,建议使用1.9以上的版本 -->
    <script src="../js/jquery-2.1.0.min.js"></script>
    <!-- 3. 导入bootstrap的js文件 -->
    <script src="../js/bootstrap.min.js"></script>
    <style type="text/css">
        td, th {
            text-align: center;
        }
    </style>
</head>
<body>

<div class="container">
    <h3 style="text-align: center">用户信息列表</h3>
    <div style="float: left;">

        <form class="form-inline">
            <div class="form-group">
                <label for="exampleInputName2">姓名</label>
                <input type="text" class="form-control" id="exampleInputName2">
            </div>
            <div class="form-group">
                <label for="exampleInputName3">籍贯</label>
                <input type="text" class="form-control" id="exampleInputName3">
            </div>

            <div class="form-group">
                <label for="exampleInputEmail2">邮箱</label>
                <input type="email" class="form-control" id="exampleInputEmail2">
            </div>
            <button type="submit" class="btn btn-default">查询</button>
        </form>

    </div>

    <div style="float: right;margin: 5px;">

        <a class="btn btn-primary" href="add.html">添加新用户</a>
        <a class="btn btn-primary" href="add.html">删除选中用户</a>
    </div>

    <table border="1" class="table table-bordered table-hover">
        <tr class="success">
            <th><input type="checkbox"></th>
            <th>编号</th>
            <th>姓名</th>
            <th>性别</th>
            <th>年龄</th>
            <th>籍贯</th>
            <th>QQ</th>
            <th>邮箱</th>
            <th>操作</th>
        </tr>
        <c:forEach items="${page.records}" var="user" varStatus="s">
            <tr>
                <td><input type="checkbox"></td>
                <td>${s.count}</td>
                <td>${user.name}</td>
                <td>${user.gender}</td>
                <td>${user.age}</td>
                <td>${user.address}</td>
                <td>${user.email}</td>
                <td>${user.qq}</td>
                <td>
                    <a class="btn btn-default btn-sm" href="/users/update?id=${user.id}">修改</a>&nbsp;
                    <a class="btn btn-default btn-sm" href="/users/delete?id=${user.id}">删除</a></td>
            </tr>
        </c:forEach>
    </table>
    <nav aria-label="Page navigation">
        <ul class="pagination">
            <li>
                <c:if test="${page.pageIndex>1}">
                    <a href="/users/queryUsersByPage?pageIndex=${page.pageIndex-1}" aria-label="Previous">
                        <span aria-hidden="true"><<</span>
                    </a>
                </c:if>
            </li>
            <%--var相当于i begin 开始 end 结束  step 步长(每次加1)--%>
            <c:forEach var="i" begin="1" end="${page.totalPage}" step="1">
                <c:choose>
                    <c:when test="${page.pageIndex==i}">
                        <li class="active"><span>${i}</span></li>
                    </c:when>
                    <c:otherwise>
                        <li><a href="/users/queryUsersByPage?pageIndex=${i}">${i}</a></li>
                    </c:otherwise>
                </c:choose>
            </c:forEach>
            <li>
                <c:if test="${page.pageIndex <page.totalPage}">
                    <a href="/users/queryUsersByPage?pageIndex=${page.pageIndex+1}" aria-label="Next">
                        <span aria-hidden="true">>></span>
                    </a>
                </c:if>
            </li>
            <span style="font-size: 25px;margin-left: 5px;">
                    共条${page.count}记录,共${page.totalPage}页
                </span>
        </ul>
    </nav>
</div>
</body>
</html>
5、测试结果。
  • 初步测试1。

  • 位于第一页时,没有上一页按钮。

  • 位于最后一页时,没有下一页按钮。

  • 最终效果。
相关推荐
三氧化真7 分钟前
使用FastExcel时的单个和批量插入的问题
java·数据库·mybatis
蜡笔小祎在线学习24 分钟前
小林coding-12道Spring面试题
java·后端·spring
杨凯凡1 小时前
Mockito 全面指南:从单元测试基础到高级模拟技术
java·单元测试·mockito
厌世小晨宇yu.1 小时前
对Gpt关于泛型、Stream的提问
java·开发语言·gpt·ai
lllsure1 小时前
SpringMVC 拦截器(Interceptor)
java·开发语言·mysql
Adellle1 小时前
Java进阶
java·后端·面试
MicoZone2 小时前
Tomcat
java
陈陈爱java2 小时前
Java算法模板
java·开发语言·算法
慵懒学者3 小时前
16 Junit单元测试框架、反射、注解、动态代理(黑马Java视频笔记)
java·笔记·junit·单元测试
开开心心就好3 小时前
自定义屏幕显示方向的实用软件
java·服务器·python·eclipse·pdf·word·excel