系列链接:
✨JavaWeb项目实战亲自动手手敲上线小项目的第一天✨
✨JavaWeb项目实战亲自动手手敲上线小项目的第二天✨
✨JavaWeb项目实战亲自动手手敲上线小项目的第三天✨
✨JavaWeb项目:实战亲自动手手敲上线小项目部分功能的第四天优化✨
JavaWeb项目实战第二天进展
实现流程思想与过程
那今天就不多说流程了,直接去实现功能就是了。
1. 模糊查询功能实现
那在前面说过我们已经实现了对学生列表的全查,那接下来就进行一下优化对其进行查询条件的限定,之后根据对应条件去返回对的查询结果。
- 那我们首先就去修改我们的
list.jsp
中的关于模糊查询的条件:
结果如下:
<form action="/Educational/student/getStudentList" method="get">
学生名称:
<input type="text" name="stuname" value="${stuname}" />
学生学号:
<input type="text" name="stuno" value="${stuno}" />
性别:
<select name="sex">
<option value="-1">--请选择--</option>
<option value="1">男</option>
<option value="0">女</option>
</select>
<input type="submit" value="查询" />
</form>
- 那之后发送一个请求给form表单的action,那就又到了我们的
GetStudentServlet
,那之前不是没有参数的吗,现在我们就去获取参数,那传参了,下面的调取service的GetStudents的方法也要有参数。
//1. 获取参数
String stuname = req.getParameter("stuname");
String stuno = req.getParameter("stuno");
String sex = req.getParameter("sex");
//2. 调取service方法
StudentService service = new StudentServiceImpl();
List<Student> students = service.getStudents(stuname,stuno,Integer.parseInt(sex));
那我们依次都要对service,还有实现类都要加上参数。
那更新后的StudentService
接口方法为:
package com.lby.service;
import com.lby.bean.Student;
import java.util.List;
/**
* @Author: King-lby
* @Date Created in 2021-08-24 9:46
*/
public interface StudentService {
/**
* 获取学员的信息列表
*/
public List<Student> getStudents(String name,String stuno,int sex);
}
还有StudentSerivceImpl
类:还有调用过程中要返回的都要加上参数.
@Override
public List<Student> getStudents(String name,String stuno,int sex) {
return dao.getStudents(name,stuno,sex);
}
dao层的StudentDao
也要更新:
public List<Student> getStudents(String name,String stuno,int sex);
还有dao层的实现类StudentDaoImpl
:
@Override
public List<Student> getStudents(String name,String stuno,int sex) {
那把参数都传入了,就要根据相应的参数进行一个动态的筛选查询了,所以我们要去改我们的查询sql语句,那我们可以用一个StringBuffer
工具类,那为什么用StringBuffer
呢,而不选择用String呢,那是因为String是一个固定长度的字符串,而StringBuffer
是一个动态的进行内存的更新,也就是内存可以扩容,所以方便我们进行查询语句的一个动态的变化,(因为我们可根据上面的三个参数进行总共有
A
3
3
A_{3}^{3}
A33种选择筛选条件的变化)
@Override
public List<Student> getStudents(String name,String stuno,int sex) {
List list = new ArrayList<Student>();
List params = new ArrayList();
try {
StringBuffer sqlbuf=new StringBuffer(" select * from student where 1=1 ");//注意前后加空格,这是字符串的拼接
if(name!=null&&name.length()>0){
//拼接字符串
sqlbuf.append(" and stuname like ? ");//注意前后加空格,这是字符串的拼接
params.add("%"+name+"%");//模糊查要添加%别忘了
}
if(stuno!=null&&stuno.length()>0){
//拼接字符串
sqlbuf.append(" and stuname=? ");//注意前后加空格,这是字符串的拼接
params.add(stuno);
}
if(sex!=-1){
//拼接字符串
sqlbuf.append(" and sex=? ");//注意前后加空格,这是字符串的拼接
params.add(sex);
}
resultSet = query(sqlbuf.toString(), params);//没有参数,返回结果集,使用父类变量resultSet
那我们会发现我们的页面查询会报异常:数据类型转换格式出现了问题
29行出现了错误,那是哪里:
那就是这个问题我他丫的今天啥也没干,就陪着他折腾了一整天,我疯了,网上众说纷纭啊,那我这里最后在老师的帮助下解决了,解决完就是晚上八点了
我服了,我是废物,那具体的解决方法就是直接对其进行一个三目判断:
将第29行改为:
List<Student> students = service.getStudents(stuname,stuno,sex==null?-1:Integer.parseInt(sex));
那这个1是我设置的男性的值,0是女性,-1则是请选择,那还是不要去设置1或者0,因为我试过了,如果设置的是1,那不管你的sex如何改变都会是男学生,0则全是不管选择什么都是女学生。还是-1对应null比较好。
就这样解决了
就这样没了,心里空落落的,好难受。
好吧,解决后的效果如下:
当查询条件为男性时:
当学号查询条件为
stu1001
时:
当模糊查询
含有李
的学生姓名时:
那我们会发现我们在点击查询后,我们的查询条件是没有保存的,那我们就可以在GetStudentServlet
的跳转页面的操作后面添加:
//3. 跳转页面
//如果后台想给前台传数据,是一定要给给前台存值的
req.setAttribute("stulist",students);//将students对象的数据存到stulist中
//存储模糊查询条件
req.setAttribute("stuname",stuname);
req.setAttribute("stuno",stuno);
req.setAttribute("sex",sex);
/**
* 那我们跳转页面到Educational/student/list.jsp查看存储的数据
*/
//注意:这个路径是我们之前在left.jsp中已经有一个请求的路径了,所以只要接上之前的就好了,不用全部写完,当然直接用绝对路径的方式也是可行的,还是很好用的。
//注意2:不要加‘/’,加了就变成从根目录web查找路径了
req.getRequestDispatcher("list.jsp").forward(req,resp);
那之后我们的模糊查询就可以进行单击一个查询条件之后,再次根据选择添加条件去模糊查询了。
那优化后的模糊查询效果展示就不展示了,浪费空间,大家可自行猜想,那就直接下一环节。
2. 分页查询
那我们在完成了模糊查询后,再继续我们的分页查询。
惯例:
- 那我们首先在
list.jsp
中发送请求,然后就发送一个请求地址Educational/student/getStudentList
到GetStudentServlet
<tr>
<td colspan="20" style="text-align: center;">
<a style="text-decoration: none;" href="/Educational/student/getStudentList">首页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList">上一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList">下一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList">尾页</a>
共1234条
每页显示
10/23
</td>
</tr>
-
那我们的
GetStudentServlet
会干什么事呢?2.1 还是传参,但是是接收两部分参数:
//1.2 分页数据 limit 开始设置,显示条数
//页码值
String pageIndex = req.getParameter("pageIndex");//接收参数,然后传给service层
还是一样的流程,我们的StudentService
接口:
public interface StudentService {
/**
* 获取学员的信息列表
* pageIndex 页码值
* pageSize 每页显示条数
*/
public List<Student> getStudents(String name,String stuno,int sex,int pageIndex,int pageSize);
}
我们的StudentServiceImpl
实现类:
public class StudentServiceImpl implements StudentService {
private StudentDao dao = new StudentDaoImpl();
@Override
public List<Student> getStudents(String name,String stuno,int sex,int pageIndex,int pageSize) {
return dao.getStudents(name,stuno,sex,pageIndex,pageSize);
}
}
我们的StudentDao
接口:
public interface StudentDao {
/**
* 获取学员的信息列表
*/
public List<Student> getStudents(String name,String stuno,int sex,int pageIndex,int pageSize);
}
还有我们的StudentDaoImpl
实现类:
@Override
public List<Student> getStudents(String name,String stuno,int sex,int pageIndex,int pageSize) {
。。。
}
那就和模糊查询一样,我们也要去修改sql,所以我们在几个if的最外层加上:
//分页
sqlbuf.append(" limit ?,? ");// 1 5 limit 0 5
这里给大家说一下,那我们假设我们第一页,然后每页显示5条,那就要limit从下标:0开始,5条每页,对吧,那就有一个公式,大家可以记一下:
limit (pageIndex-1)*pageSize,pageSize;//起始位置,总页码数
所以我们的向集合中这样添加:
params.add((pageIndex-1)*pageSize);
params.add(pageSize);
那我们返回去看我们的GetStudentServlet
,我们这里有一个和模糊查询一下的问题:空值问题,哎,所以这次我们就提前定义一个index变量,判断空值:
//1.2 分页数据 limit 开始设置,显示条数
//页码值
String pageIndex = req.getParameter("pageIndex");//接收参数,然后传给service层
//如果页面没有传入pageIndex的值,则默认查询第一页
int index = pageIndex==null?1:Integer.parseInt(pageIndex);
//2. 调取service方法
StudentService service = new StudentServiceImpl();
List<Student> students = service.getStudents(stuname,stuno,sex==null?-1:Integer.parseInt(sex),index,5);
//3. 跳转页面
那这样,我们的首页空值问题和跳转以及每页显示列表条数问题就解决了,那我们的往后进行,
我们的上一页,下一页怎么办?
那我们的上一页或者下一页是怎么来的?是当前页码值-1,而当前页码值就是我们之前接收的pageIndex,那我们这个页码怎么从后台到前台进行一个获取呢?还是和模糊查询一样,所以我们在存储模糊查询条件后面加上:
//存储分页数据
req.setAttribute("index",pageIndex);
那我们存入了当前页码值之后去跳转list.jsp
,那我们的分页部分代码也就进行了优化:
<tr>
<td colspan="20" style="text-align: center;">
<a style="text-decoration: none;" href="/Educational/student/getStudentList">首页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${index-1}">上一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${index+1}">下一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList">尾页</a>
共1234条
每页显示
10/23
</td>
</tr>
我们测试一下:就是这样的一个效果
但是也有问题:当我们点击到了最后一页的时候,我们再次点击下一页,那就回显示:
同样的还有点击到首页时,我们还去点击上一页,那就会报错:
那又遇到了异常,我们要怎么解决呢?那先分析问题,我们在到最后一页时还点击下一页没有信息显示,而点击到首页还点击上一页,直接就是报了一个空指针异常,那我们就让他们在手尾的时候去进行一个空值判断就好了,我们采用EL表达式:
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${index-1<=1?1:index-1}">上一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${index+1}">下一页</a>
那我们的下一页是和总页数去作比较的,那总页数又是怎么来的。
那我们可以在GetStudentServlet
中定义:
//获取总页数=总条数%每页显示的条数>0?总条数/每页显示条数+1:总条数/每页显示条数;
//问题又来了,总条数从哪来,那我们可以在service层的StudnentService
接口定义一个方法:
/**
* 获得总条数(基于模糊查询)
*/
public int total(String name,String stuno,int sex);
那同样的,我们在dao层也去添加,还有他们的实实现类:
那我们的StudentServiceImpl
实现类:
那就直接Alt+Enter:然后我们改一下返回结果
public class StudentServiceImpl implements StudentService {
private StudentDao dao = new StudentDaoImpl();
@Override
public List<Student> getStudents(String name,String stuno,int sex,int pageIndex,int pageSize) {
return dao.getStudents(name,stuno,sex,pageIndex,pageSize);
}
@Override
public int total(String name, String stuno, int sex) {
return dao.total(name, stuno, sex);
}
}
我们的StudentDao
接口:
public interface StudentDao {
/**
* 获取学员的信息列表
*/
public List<Student> getStudents(String name,String stuno,int sex,int pageIndex,int pageSize);
/**
* 获得总条数(基于模糊查询)
*/
public int total(String name,String stuno,int sex);
}
还有StudentDaoImpl
实现类:
@Override
public int total(String name, String stuno, int sex) {
int total = 0;
try {
List params = new ArrayList();
StringBuffer sqlbuf=new StringBuffer(" select count(*) from student where 1=1 ");//注意前后加空格,这是字符串的拼接
if(name!=null&&name.length()>0){
//拼接字符串
sqlbuf.append(" and stuname like ? ");//注意前后加空格,这是字符串的拼接
params.add("%"+name+"%");//模糊查要添加%别忘了
}
if(stuno!=null&&stuno.length()>0){
//拼接字符串
sqlbuf.append(" and stuno=? ");//注意前后加空格,这是字符串的拼接
params.add(stuno);
}
if(sex!=-1){
//拼接字符串
sqlbuf.append(" and sex=? ");//注意前后加空格,这是字符串的拼接
params.add(sex);
}
resultSet = query(sqlbuf.toString(),params);
while(resultSet.next()){
total=resultSet.getInt(1);//第一列
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
closeAll();
}
return total;
}
那这里我们的resultSet其实就是一个值,那我们就在最外层设置total=0,之后我们while循环,获取第一列,最后closeAll()关闭资源,然后返回我们的total。
那我们再回到GetStudentServlet
去调用:
//获取总页数=总条数%每页显示的条数>0?总条数/每页显示条数+1:总条数/每页显示条数;
//问题又来了,总条数从哪来
int total = service.total(stuname,stuno,sex==null?-1:Integer.parseInt(sex));//总条数
int totalPages = total%5>0?total/5+1:total/5;//总页数
那调用后,我们去把之前的存储分页数据给填充起来:
//存储分页数据
req.setAttribute("index",index);
req.setAttribute("size",5);
req.setAttribute("total",total);
req.setAttribute("totalPages",totalPages);
那之后我们再去把之前的list,jsp
里的分页效果给迭代一下:
<td colspan="20" style="text-align: center;">
<a style="text-decoration: none;" href="/Educational/student/getStudentList">首页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${index-1<=1?1:index-1}">上一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${index+1>=totalPages?totalPages:index+1}">下一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${totalPages}">尾页</a>
共${total}条
每页显示
${index}/${totalPages}
</td>
那到这里,我们的份额查询就告一段落了,我们再去查看一下效果:
我们可以看到,当我们点击首尾页时,就没有再报错了,而且大家可以仔细看一下左下角的链接。
那我之后又去测试了模糊查询,发现有问题,按理来说应该是只有这一个条件筛选出来的信息,但是当我点击下一页时还是将所有数据都进行了查询,那我其实看到了,我们的左下角请求链接并没有变化,也就说我们的模糊查询的条件没有拼接上,那我们
再去list.jsp
的分页部分进行迭代:
<td colspan="20" style="text-align: center;">
<a style="text-decoration: none;" href="/Educational/student/getStudentList?stuname=${stuname}&stuno=${stuno}&sex=${sex}">首页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${index-1<=1?1:index-1}&stuname=${stuname}&stuno=${stuno}&sex=${sex}">上一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${index+1>=totalPages?totalPages:index+1}&stuname=${stuname}&stuno=${stuno}&sex=${sex}">下一页</a>
<a style="text-decoration: none;" href="/Educational/student/getStudentList?pageIndex=${totalPages}&stuname=${stuname}&stuno=${stuno}&sex=${sex}">尾页</a>
共${total}条
每页显示
${index}/${totalPages}
</td>
那我们再来看效果:
我们再看就会发现我们的stuname,stuno,sex数据都拼接成功了,而且也不会再出现返回全查的结果了。
好了,由于本人的时间今天都浪费在处理Bug上面去了,导致我们的时间很少,再加上我学完内容再写出来,现在都已经凌晨了,那y也是因为本人的接收能力不高,所以今天就学到这里,更新到这里。内容有点少,希望大家见谅。
当然若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。
别问,问就是
创作不易,白嫖很爽,但是求各位手下留情。
如果本篇博客有任何错误或者疏漏,请批评斧正,感激不尽 !