思途JSP学习 0730

发布于:2025-07-31 ⋅ 阅读:(15) ⋅ 点赞:(0)

本期继0725继续对我们的学生列表进行升级

一.增加条件搜索框与各类按钮

在我们的jsp页面中进行编写

<div class="search">
  <form action="">
    <div>
      <label for="stuId">学号</label>
      <input type="text" id="stuId" name="stuId" placeholder="请输入学号" autocomplete="off">
    </div>
    <div>
      <label for="name">姓名</label>
      <input type="text" id="name" name="name" autocomplete="off">
    </div>
    <div>
      <label for="sex">性别</label>
      <select name="sex" id="sex">
        <option value="">请选择</option>
        <option value="男">男</option>
        <option value="女">女</option>
      </select>
    </div>
    <div class="layui-form-item">
      <label>出生日期:</label>
      <div class="layui-inline" id="birth-range">
        <div class="layui-input-inline">
          <input type="text" autocomplete="off" id="birth-start" class="layui-input"
                 placeholder="开始日期">
        </div>
        <div class="layui-form-mid">-</div>
        <div class="layui-input-inline">
          <input type="text" autocomplete="off" id="birth-end" class="layui-input"
                 placeholder="结束日期">
        </div>
      </div>
    </div>
    <div>
      <label for="phone">手机号</label>
      <input type="text" id="phone" name="phone" autocomplete="off">
    </div>
  </form>
</div>

<%--按钮区--%>
<div class="action">
  <button id="search">查询</button>
  <button id="add">新增</button>
  <button id="edit">修改</button>
  <button id="del">删除</button>
  <button id="reset">重置</button>
</div>

二.引入layui进行美化

如何下载layui我在这里就不作过多赘述了

在jsp前端中引入layui的css与js

  <link rel="stylesheet" href="assets/lib/layui/css/layui.css">
  <script src="assets/lib/layui/layui.js"></script>

在我们自己的js文件中编写js代码用于激活layui样式

    //渲染日期时间范围
    layui.use(() => {
        let laydate = layui.laydate;
        laydate.render({
            elem: "#birth-range",
            range: ["#birth-start", "#birth-end"]
        });
    });

三.给“重置”增加功能

重置按钮的作用应该是点击后使搜索框内的数据全部清除

在js中编写代码

//重置按钮事件
    $("#reset").click(function (){
        $("#stuId").val("");
        $("#name").val("");
        $("#sex").val("");
        $("#birth-start").val("");
        $("#birth-end").val("");
        $("#phone").val("");

        params={
            stuId:"",
            name:"",
            sex:"",
            birthStart:"",
            birthEnd:"",
            phone:""
        }
    });

或者用对DOM对象操作,使用reset函数重置表单,【0】找到#serch-form下的第一个元素,这里是form元素,我们就可以调用DOM中form的原生函数reset进行重置

$('#reset').click(function(){
    $('#serch-form')[0].reset();
})

四.增加搜索功能

1.完成js中搜索按钮的功能

//查询按钮事件
    $("#search").click(function (){
        let stuId = $("#stuId").val();
        let name = $("#name").val();
        let sex = $("#sex").val();
        let birthStart = $("#birth-start").val();
        let birthEnd = $("#birth-end").val();
        let phone = $("#phone").val();

        params = {
            stuId,
            name,
            sex,
            birthStart,
            birthEnd,
            phone
        };
        console.log(stuId, name, sex, birthStart, birthEnd, phone);
        findAll(1,limits,params);
    });

2.将搜索栏中输入的信息传给后端

为findAll函数新增加一个形参params用于接收条件,在ajax中使用

function findAll(page = 1, limit = 10, params = {}){
    $.ajax({
        url : ctx+ "/student/list",
        method:"post",
        data:{
          page,
          limit,
          ...params
        },

...params代表将params展开使用

findAll接受到参数后,再以post请求发送给servlet

servlet新建对象存储params

//前端提交的查询条件
            String stuId = req.getParameter("stuId");
            String name = req.getParameter("name");
            String sex = req.getParameter("sex");
            String birthStart = req.getParameter("birthStart");
            String birthEnd = req.getParameter("birthEnd");
            String phone = req.getParameter("phone");

在模型软件包model下新建搜索模型软件包search,创建StudentSearchBean类用于存放拓展模块,继承Student;

package com.situ.model.search;

import com.situ.model.Student;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDate;

@Setter
@Getter
public class StudentSearchBean extends Student {
    private LocalDate birthStart;
    private LocalDate birthEnd;
}

在servlet下创建搜索模型对象

如果搜索框内传入数据不为空,就将数据存入模型对象condition

StudentSearchBean condition = new StudentSearchBean();
            if(StringUtils.hasText(stuId)) condition.setStuId(stuId);
            if (StringUtils.hasText(name)) condition.setName(name);
            if (StringUtils.hasText(sex)) condition.setSex(sex);
            if (StringUtils.hasText(phone)) condition.setPhone(phone);
            if (StringUtils.hasText(birthStart)){
                LocalDate bs = LocalDate.parse(birthStart, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                condition.setBirthStart(bs);
            }
            if (StringUtils.hasText(birthEnd)){
                LocalDate be = LocalDate.parse(birthEnd, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                condition.setBirthEnd(be);
            }

五.向下传递,获取数据库中信息

让srevice,dao的findAll方法都接收新的形参StudentSearchBean

List<Student> findAll(Pagination pagination, StudentSearchBean ssb);

修改之前的sql语句,使用字符串拼接上where条件 

将得到的数据以数组的形式存到args中

package com.situ.dao.impl;

import com.situ.common.Global;
import com.situ.dao.StudentDao;
import com.situ.model.Student;
import com.situ.model.search.StudentSearchBean;
import com.situ.util.Pagination;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class StudentDaoImpl implements StudentDao {
    private final RowMapper<Student> rowMapper = new BeanPropertyRowMapper<Student>(Student.class);

    @Override
    public List<Student> findAll(Pagination pagination, StudentSearchBean ssb) {
        JdbcTemplate jdbcTemplate = Global.getTemplate();
        List<Object> args = new ArrayList<>();//查寻参数

        String select = "select id, stu_id, name, sex, birthday, pinyin, phone, email, qq, wechat from t_student";
        StringBuilder where = new StringBuilder();
        where.append(" where 1=1");
        if(StringUtils.hasText(ssb.getStuId())) {
            where.append(" and stu_id = ?");
            args.add(ssb.getStuId());
        }
        if(StringUtils.hasText(ssb.getName())) {
            where.append(" and name like ?");
            args.add("%"+ssb.getName()+"%");
        }
        if(StringUtils.hasText(ssb.getPinyin())) {
            where.append(" and pinyin like ?");
            args.add("%"+ssb.getPinyin()+"%");
        }
        if(StringUtils.hasText(ssb.getSex())) {
            where.append(" and sex = ?");
            args.add(ssb.getSex());
        }
        if(StringUtils.hasText(ssb.getPhone())) {
            where.append(" and phone like ?");
            args.add("%"+ssb.getPhone()+"%");
        }
        if(ssb.getBirthStart()!=null) {
            where.append(" and birthday >= ?");
            args.add(ssb.getBirthStart());
        }
        if(ssb.getBirthEnd()!=null) {
            where.append(" and birthday < ?");
            args.add(ssb.getBirthEnd());
        }

        //查询记录总数
        String coustsql = "select count(0) from ("+(select+where.toString())+") t";

        //记录总数
        Long count = jdbcTemplate.queryForObject(coustsql, Long.class, args.toArray());
        pagination.setTotal(count);//设置总记录数

        //分页查询sql
        String limitsql = select + where.toString() + " limit ?, ?";
        args.add(pagination.getOffset());
        args.add(pagination.getLimit());

        //执行查询操作
        List<Student> students =  jdbcTemplate.query(limitsql, rowMapper ,args.toArray());

        return students;
    }
}

六.数据返回给前端显示

七.显示当前页数,总页数,以及总条数,查询对象高亮

注意需要及时清除上一次创建的对象

//总页数和总条数
            $(".paginate>ul>li.jump-btn").after("<li>"+"共"+currentPage+"/"+pages+"页  "+pi.total+"条"+"</li>");

在信息插入之前使用.replace将目标对象替换即可

stu.name = stu.name.replace(params.name,"<span style='background-color: yellow'>"+params.name+"</span>")
$tr.append("<td>"+ stu.name +"</td>")
$tr.append("<td>"+ stu.pinyin +"</td>")
$tr.append("<td>"+ stu.sex +"</td>")
$tr.append("<td>"+ stu.birthday +"</td>")
stu.phone = stu.phone.replace(params.phone,"<span style='background-color: yellow'>"+params.phone+"</span>")
$tr.append("<td>"+ stu.phone +"</td>")

八.注意事项

1.RowMapper实例化

private final RowMapper<Student> rowMapper = new BeanPropertyRowMapper<>(Student.class);
  • RowMapper<Student>: 这是一个接口,定义了如何将数据库查询结果集(ResultSet)中的一行数据映射(转换)成一个特定的Java对象(在这里是Student对象)。<Student> 是泛型,指定了这个映射器将行数据转换成 Student 类型的对象。

  • BeanPropertyRowMapper<Student>(Student.class): 这是Spring JDBC提供的 RowMapper 接口的一个具体实现类

    • 作用: 它利用Java的反射机制(Reflection)来自动完成映射工作。
    • 映射规则:
      1. 列名匹配属性名: 它会检查 ResultSet 中每一列的列名(column name)。
      2. 转换为驼峰命名: 它会将数据库列名从 snake_case(如 student_idfirst_name)自动转换为 Java Bean 的 camelCase 属性名(如 studentIdfirstName)。这个转换是它智能的地方。
      3. 查找Setter方法: 它会查找 Student 类中与转换后的属性名匹配的 setter 方法(例如 setStudentId(...)setFirstName(...))。
      4. 设置属性值: 找到对应的 setter 方法后,它会调用该方法,将 ResultSet 中当前行对应列的值作为参数传入,从而设置 Student 对象的属性。
    • Student.class: 这个参数告诉 BeanPropertyRowMapper,它需要创建和填充的是 Student 类的实例。它会尝试调用 Student 类的无参构造函数来创建对象。
  • private final: 这表示 rowMapper 是一个私有的、不可变的(一旦初始化后就不能再指向其他对象)实例变量。通常在DAO类中这样定义,避免每次查询都创建新的映射器实例,提高效率。

2.获取记录总数

Long count = jdbcTemplate.queryForObject(coustsql, Long.class, args.toArray());
pagination.setTotal(count);//设置总记录数
  • jdbcTemplate: 这是 Spring Framework 提供的核心类,用于简化 JDBC 操作(如创建连接、执行SQL、处理异常、关闭资源等),让开发者专注于SQL本身。

  • queryForObject(String sql, Class<T> requiredType, Object... args): 这是 JdbcTemplate 的一个核心方法。

    • String sql (coustsql): 传入要执行的 SQL 查询语句。这里的 coustsql 应该是一个 SELECT COUNT(*) ... 语句,目的是获取满足条件的总记录数。例如:"SELECT COUNT(*) FROM students WHERE name LIKE ?"
    • Class<T> requiredType (Long.class): 指定查询期望返回的单一结果的数据类型。因为 COUNT(*) 返回的是一个整数,通常用 Long 来接收(避免 int 溢出),所以这里传入 Long.class。JdbcTemplate 会尝试将数据库返回的值转换成这个类型。
    • Object... args (args.toArray()): 这是一个可变参数列表,用于传递 SQL 语句中的占位符(通常是 ?)所对应的参数值。args 很可能是一个 List 或 Collection,存储了查询条件(比如搜索关键词、状态等)。toArray() 将其转换为 Object 数组,以便 JdbcTemplate 能正确地将这些值绑定到 SQL 语句的 ? 占位符上,有效防止SQL注入。
    • 返回值 Long count: 该方法执行 coustsql,并返回查询结果集中第一行第一列的值,且该值被转换为 Long 类型。对于 COUNT(*) 查询,这就是我们想要的总记录数。
  • pagination: 这通常是一个自定义的分页信息对象(例如 PageInfoPagePagination 等),用来封装分页所需的各种信息。
  • setTotal(count): 调用这个对象的 setTotal 方法,将上一步查询到的总记录数 count 设置进去。这个总数对于前端计算总页数、显示“共X条记录”等信息至关重要。

 3.执行分页查询并映射结果

List<Student> students = jdbcTemplate.query(limitsql, rowMapper, args.toArray());
  • jdbcTemplate.query(...): 这是 JdbcTemplate 另一个核心的查询方法,专门用于返回多行结果
  • String sql (limitsql): 传入要执行的 SQL 查询语句。这里的 limitsql 应该是一个包含分页逻辑的 SELECT 语句,通常使用 LIMIT (MySQL, PostgreSQL) 或 ROWNUM (Oracle) 或 OFFSET ... FETCH (SQL Server, PostgreSQL) 等子句来限制返回的行数和起始位置。例如:"SELECT * FROM students WHERE name LIKE ? LIMIT ? OFFSET ?"。它查询的是当前页需要显示的具体数据。
  • RowMapper<T> rowMapper (rowMapper): 传入之前定义好的 RowMapper 实例。JdbcTemplate 在遍历 ResultSet 的每一行时,都会调用这个 rowMapper 的 mapRow() 方法(BeanPropertyRowMapper 内部实现了此方法),将每一行数据转换成一个 Student 对象。
  • Object... args (args.toArray()): 和 queryForObject 一样,传入SQL占位符所需的参数值数组。注意,limitsql 中的占位符数量和顺序需要与 args 中的值匹配(可能比 coustsql 多两个,分别对应 LIMIT 和 OFFSET 的值)。
  • 返回值 List<Student> students: 该方法执行 limitsql,使用 rowMapper 将查询结果集中的每一行都转换成一个 Student 对象,然后将所有转换后的对象放入一个 List 中并返回。最终得到的就是当前分页页面上需要显示的所有 Student 对象的集合。

 


网站公告

今日签到

点亮在社区的每一天
去签到