当前位置: 首页 > news >正文

思途JSP学习 0730

本期继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);@Overridepublic 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);//设置总记录数//分页查询sqlString 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 对象的集合。

 

http://www.dtcms.com/a/306683.html

相关文章:

  • DP-v2.1-mem-clean学习(3.6.7)
  • 片上变化(OCV)
  • 7.Origin2021如何绘制拟合数据图?
  • Python 之抽象方法 @abstractmethod 的理解
  • Day06_C++编程
  • 9《MySQL 教程》MySQL 的数据类型(2)
  • 云原生环境里的显示变革:Docker虚拟浏览器与cpolar穿透技术实战
  • 赵义弘-----补题报告
  • 【python】Python爬虫入门教程:使用requests库
  • 【git】在 GitLab 上如何把 A 分支(如 feature/xxx)合并到 B 分支(如 trunk)
  • Scala实现常用排序算法
  • 深入理解 Kotlin Flow:异步数据流处理的艺术
  • MidJourney精选图集与提示词生成器:AI创意灵感与高效提示词工具
  • composer 常用命令
  • 高防CDN与高防IP的选择
  • docker可视化管理工具lazydocker
  • 【百卷编程】Go语言大厂高级面试题集
  • 3GPP TS 38.331 V18.6.0 (2025-06)中文版
  • 工业5G路由器赋能高速公路实时监控
  • 【问题未解决-寻求帮助】VS Code 中使用 Conda 环境,运行 Python 后 PowerShell 终端输出内容立即消失
  • 《Java 程序设计》第 12 章 - 异常处理
  • T113-i Linux系统完整构建指南:从SDK开箱到内核镜像量产烧录全流程
  • 2025年湖北中级注册安全工程师报考那些事
  • docker 用于将镜像打包为 tar 文件
  • 【MySQL学习|黑马笔记|Day3】多表查询(多表关系、内连接、外连接、自连接、联合查询、子查询),事务(简介、操作、四大体系、并发事务问题、事务隔离级别)
  • 【公有云部署模型】yolo模型公有云部署
  • 用聊天方式聊聊msvcr100.dll丢失的解决方法有哪些?msvcr100.dll是什么
  • 7.pcl滤波(一)
  • Python在Web开发领域的崛起与生态探索:从脚本语言到全栈利器
  • Unity Standard Shader 解析(四)之ForwardAdd(简化版)