当前位置: 首页 > 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.lryc.cn/news/605303.html

相关文章:

  • LeetCode 刷题【22. 括号生成】
  • Winform 渐变色 调色板
  • 代码随想录算法训练营第五十六天|动态规划part6
  • C语言基础11——结构体1
  • AutoSAR(MCAL) --- ADC
  • VoIP技术全面深度学习指南:从原理到实践的认知进化
  • 【GEO从入门到精通】生成式引擎与其他 AI 技术的关系
  • Linux ARM 平台 C 语言操作 Excel 文件的常用库与工具汇总(支持 xls 和 xlsx)
  • Linux基本指令,对路径的认识
  • SringBoot入门
  • uvm-tlm-sockets
  • 关于MyBatis 的懒加载(Lazy Loading)机制
  • 腾讯云市场排名
  • linux进程概念(三)进程状态
  • COZE 开源,新一代 AI Agent 本地部署一条龙
  • 借助 Wisdom SSH 的 AI 助手构建 Linux 开发环境
  • 2. Agent与 React流程
  • 智能Agent场景实战指南 Day 26:Agent评估与性能优化
  • 【面试场景题】随机立减金额计算
  • 三十四、【Linux常用工具】rsync+inotify实时同步演示
  • 游卡,快手26届秋招内推
  • Cortex-M处理器的优势?
  • 解决Nginx的HTTPS跨域内容显示问题
  • Linux日志管理和时钟同步配置指南
  • DFT设计中的不同阶段介绍
  • 【C语言类型转换坑】乘法溢出隐患发现与正确写法
  • 嵌入式系统分层开发:架构模式与工程实践(二)(创建任务篇(二))
  • CSS-in-JS 动态主题切换与首屏渲染优化
  • 人类语言驱动物理机制建模的AIVC
  • Zynq SoC 中断控制系统设计与实现:基于 GPIO 的中断驱动开发