JavaWeb-阶段性项目1:最简单的后台库存管理系统
1 写项目前
前置准备
知识准备
已掌握JavaSE/MySQL/JDBC+HTML/CSS/JavaScript基础
并已完成了Javaweb前置知识的学习
04-JavaScript基础应用-鼠标悬浮/离开表格格式变化
05-JavaWeb-Tomcat8安装、Servlet初识
06-JavaWeb-Servlet方法/生命周期、HTTP/会话session
资源准备
尚硅谷丨2022版JavaWeb教程视频
教学资源
https://pan.baidu.com/s/1TS7QJ_a2vHHmXkggAs8RMQ
提取码:yyds
文件目录
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>
sample
</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="imgs/css/index.css">
<base href="http://localhost:8080/pro10/"/><!--当前页面上所有的路径都已href为基础-->
</head>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="../css/login.css" rel="stylesheet">
<link th:href ="@{}/css/login.css">
</head>
<body>
<p class="color">hello!</p>
</body>
</html>
以后都使用绝对路径 <link th:href ="@{}/css/login.css">的形式
后台管理系统页面
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>
sample
</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="imgs/css/index.css">
<base href="http://localhost:8080/pro10/"/><!--当前页面上所有的路径都已href为基础-->
</head>
<body>
<div id="div_containner">
<div id="div_fruit_list">
<p class="center f30">欢迎使用水果库存后台管理系统</p>
<table id="tb1_fruit">
<tr>
<th class="w20"><i>名称</i></th>
<th class="w20">单价</th>
<th class="w20">库存</th>
<th>操作</th>
</tr>
<tr th:if="${#lists.isEmpty(session.fruitList)}">
<td colspan="4">sorry, is empty</td>
</tr>
<tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}">
<td th:text="${fruit.fname}">苹果</td>
<td th:text="${fruit.price}">5</td>
<td th:text="${fruit.fcount}">20</td>
<td><img src="imgs/delete.png" class="delImg"/></td>
</tr>
</table>
</div>
</div>
</body>
</html>
2 开始项目
实现功能1的过程
功能1:在水果名称上点击,超链接跳转显示详情页面,可以在详情页面编辑。
①给名称加上超链接
使用HTML内容元素<a>苹果</a>
<a th:text="${fruit.fname}">苹果</a>
这里运用到了thymeleaf技术,
之前在会话域session中通过“fruitList”这个key
取到的value
是fruitList列表
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
FruitDAO fruitDAO = new FruitDAOImpl();
List<Fruit> fruitList = fruitDAO.getFruitList();
//保存到session作用域
HttpSession session = req.getSession();
session.setAttribute("fruitList",fruitList);
//此处的视图名称是index
//thymeleaf会将这个逻辑视图名称对应到物理视图名称上
//逻辑视图名称 index
//物理视图名称 view-prefix + 逻辑视图名称 + view-suffix
//真实的视图名称是 / index .html
super.processTemplate("index",req,resp);
}
}
th:each="fruit : ${session.fruitList},每迭代一次取一个fruit对象,作为临时变量赋给“fruit”
可以看到,fruit.
可以直接获取我们想要的fruit属性,
- 经过服务器解析,Thymeleaf引擎根据th:text属性指定的『标签体新值』去替换『标签体原始值』
将${fruit.fname}
值覆盖到超链接标签中,根据之前的循环代码,就给全部的名称都打上了超链接!如下图:
②点击超链接跳转edit.html
页面
增加一个edit.html页面,作为我们编辑信息的页面
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>
sample
</title>
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="css/edit.css">
<base href="http://localhost:8080/pro10/"/><!--当前页面上所有的路径都已href为基础-->
</head>
<body>
<div id="div_containner">
<div id="div_fruit_list">
<p class="center f30">编辑库存信息</p>
<table id="tb1_fruit">
<tr>
<th class="w20"><i>名称:</i></th>
<td><input type="text" name="fname" th:value="${fruit.fname}"/></td>
</tr>
<tr>
<th class="w20">单价:</th>
<td><input type="text" name="price" th:value="${fruit.price}"/></td>
</tr>
<tr>
<th class="w20">库存:</th>
<td><input type="text" name="fcount" th:value="${fruit.fcount}"/></td>
</tr>
<tr>
<th class="w20">备注:</th>
<td><input type="text" name="remark" th:value="${fruit.remark}"/></td>
</tr>
<tr>
<th th colspan="2">
<input type="submit" value="修改" />
</th>
</tr>
</table>
</div>
</div>
</body>
</html>
视频中的五次改写
超链接跳转到edit页面,edit.do
给servlet发请求(.do的要意思就是调用servlet里面的doxxxx方法)
<td> <a th:text="${fruit.fname}" th:href=edit.do>苹果</a></td>
加上之前介绍的绝对路径表示方法${}
<td> <a th:text="${fruit.fname}" th:href="@{/edit.do}">苹果</a></td>
不光需要增加超链接,还需给后台发送参数fid,以获得对应的信息,这样才能在edit页面中编辑
<td> <a th:text="${fruit.fname}" th:href="@{/edit.do?fruit.fid}">苹果</a></td>
有一部分是字符串不需要thymeleaf解析,另一部分需要,所以这样改写。
<td> <a th:text="${fruit.fname}" th:href="@{/'edit.do?fid='+fruit.fid}">苹果</a></td>
最终写法(普通表达式与字符串拼接,还可以使用双竖线):
<td> <a th:text="${fruit.fname}" th:href="@{/edit.do(fid=${fruit.fid})}">苹果</a></td>
③在edit.html页面显示相应信息
增加一个servlet组件
package com.fancy.fruit.servlets;
import com.fancy.fruit.dao.FruitDAO;
import com.fancy.fruit.dao.impl.FruitDAOImpl;
import com.fancy.fruit.pojo.Fruit;
import com.fancy.myssm.basedao.myspringmvc.ViewBaseServlet;
import com.fancy.myssm.basedao.util.StringUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/edit.do")
public class EditServlet extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String fidStr = req.getParameter("fid");
//HTML是模板,thymeleaf是引擎,我们在servlet中调用了引擎并且给了引擎需要的模板和参数
if(StringUtil.isNotEmpty(fidStr)){
int fid = Integer.parseInt(fidStr);
Fruit fruit = fruitDAO.getFruitByFid(fid);
//获取到fruit对象后将之放置在session作用域
req.setAttribute("fruit",fruit);
//thymeleaf的viewBaseServlet中的方法,处理模板数据
super.processTemplate("edit",req,resp);
}
}
}
HTML是模板,thymeleaf是引擎,我们在servlet中调用了引擎并且给了引擎需要的模板和参数
工具类
package com.fancy.myssm.basedao.util;
public class StringUtil {
//判断字符串是否为null或者“”
public static boolean isEmpty(String str){
return str == null || "".equals(str);
}
public static boolean isNotEmpty(String str){
return !isEmpty(str);
}
}
判断从请求包中根据fid获取到的fid参数是否为空(是否取到了)
如果取到了,servlet就转发给thymeleaf渲染,最终展现在edit.html页面上。
最终效果
edit.html改写
<table id="tb1_fruit">
<tr>
<th class="w20"><i>名称:</i></th>
<td><input type="text" name="fname" th:value="${fruit.fname}"/></td>
</tr>
<tr>
<table id="tb1_fruit" th:object="${fruit}">
<tr>
<th class="w20"><i>名称:</i></th>
<td><input type="text" name="fname" th:value="*{fname}"/></td>
</tr>
<tr>
表示在table标签内部所使用的属性都是来自于fruit对象中
④在edit.html页面修改后提交
修改BaseDAO的executeUpdate方法
BaseDAO修改前
//执行更新,返回影响行数
protected int executeUpdate(String sql , Object... params){
boolean insertFlag = false ;
insertFlag = sql.trim().toUpperCase().startsWith("INSERT");
try {
conn = getConn();
if(insertFlag){
psmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
}else {
psmt = conn.prepareStatement(sql);
}
setParams(psmt,params);
int count = psmt.executeUpdate() ;
rs = psmt.getGeneratedKeys();
if(rs.next()){
return ((Long)rs.getLong(1)).intValue();
}
return count ;
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(rs,psmt,conn);
}
return 0;
}
BaseDAO修改后
//执行更新,返回影响行数
protected int executeUpdate(String sql , Object... params){
boolean insertFlag = false ;
insertFlag = sql.trim().toUpperCase().startsWith("INSERT");
try {
conn = getConn();
if(insertFlag){
psmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
}else {
psmt = conn.prepareStatement(sql);
}
setParams(psmt,params);
int count = psmt.executeUpdate() ;
if(insertFlag){
rs = psmt.getGeneratedKeys();
if(rs.next()){
return ((Long)rs.getLong(1)).intValue();
}
}
return count ;
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(rs,psmt,conn);
}
return 0;
}
修改原因:只有insert操作时需要获取自增列,所以要在rs = psmt.getGeneratedKeys();前加判断
跟着视频敲完代码后报500错误,查看原因,看报错信息定位updateservlet第25行,参数写错了
原因
实现功能2的过程 (删除与添加)
①在index.html页面点击删除图标删除数据
在index.html\页面添加
<td><img src="imgs/delete.png" class="delImg" th:onclick="'delFruit('+${fruit.fid}+')'"/></td>
使用竖线自动识别thymeleaf表达式添加‘
<td><img src="imgs/delete.png" class="delImg" th:onclick="|delFruit(${fruit.fid})|"/></td>
添加js文件
function delFruit(fid){
if(confirm("是否确认删除")){
window.location.href='del.do?fid='+fid;
}
}
-
window-当前网页窗口
-
location-地址栏对象
-
地址栏对象的href属性附上del.do?fid
新建DelServlet
package com.fancy.fruit.servlets;
import com.fancy.fruit.dao.FruitDAO;
import com.fancy.fruit.dao.impl.FruitDAOImpl;
import com.fancy.myssm.basedao.myspringmvc.ViewBaseServlet;
import com.fancy.myssm.basedao.util.StringUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/del.do")
public class DelServlet extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取fid
String fidStr = req.getParameter("fid");
if(StringUtil.isNotEmpty(fidStr)){
int fid = Integer.parseInt(fidStr);
}
}
}
没有删掉,排错
delFruit方法写错了,应该调用父类的executeUpdate方法来进行数据库数据的删除操作
@Override
public void delFruit(Integer fid){
super.executeUpdate("delete from t_fruit where fid = ? ",fid) ;
}
}
成功删除了
②在index.html页面新增添加水果信息功能
在index页面上添加添加库存记录的页面链接
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>
sample
</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="imgs/css/index.css">
<script language="JavaScript" src="js/index.js"></script>
<base href="http://localhost:8080/pro10/"/><!--当前页面上所有的路径都已href为基础-->
</head>
<body>
<div id="div_containner">
<div id="div_fruit_list">
<p class="center f30">欢迎使用水果库存后台管理系统</p>
<div style="border:0px solid red;width:60%;margin-left:32%;text-align:right;">
<a th:href="@{/add.html}" style="border:0px solid blue;margin-bottom:4px">添加新库存记录</a>
</div>
<table id="tb1_fruit">
<tr>
<th class="w20"><i>名称</i></th>
<th class="w20">单价</th>
<th class="w20">库存</th>
<th>操作</th>
</tr>
<tr th:if="${#lists.isEmpty(session.fruitList)}">
<td colspan="4">sorry, is empty</td>
</tr>
<tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}">
<td> <a th:text="${fruit.fname}" th:href="@{/edit.do(fid=${fruit.fid})}">苹果</a></td>
<td th:text="${fruit.price}">5</td>
<td th:text="${fruit.fcount}">20</td>
<td><img src="imgs/delete.png" class="delImg" th:onclick="|delFruit(${fruit.fid})|"/></td>
</tr>
</table>
</div>
</div>
</body>
</html>
添加add.html页面
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>
sample
</title>
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="css/edit.css">
<base href="http://localhost:8080/pro10/"/><!--当前页面上所有的路径都已href为基础-->
</head>
<body>
<div id="div_containner">
<div id="div_fruit_list">
<p class="center f30">编辑库存信息</p>
<form th:action="@{/add.do}" method="post" th:object="${fruit}">
<!--隐藏域,它的值会随着表单一起发送给服务器,用户看不见 -->
<input type="hidden" name="fid" th:value="*{fid}"/>
<table id="tb1_fruit">
<tr>
<tr>
<th class="w20"><i>名称:</i></th>
<td><input type="text" name="fname"/></td>
</tr>
<tr>
<th class="w20">单价:</th>
<td><input type="text" name="price"/></td>
</tr>
<tr>
<th class="w20">库存:</th>
<td><input type="text" name="fcount"/></td>
</tr>
<tr>
<th class="w20">备注:</th>
<td><input type="text" name="remark"/></td>
</tr>
<tr>
<th th colspan="2">
<input type="submit" value="添加" />
</th>
</tr>
</table>
<form/>
</div>
</div>
</body>
</html>
新建添加功能的servlet组件
package com.fancy.fruit.servlets;
import com.fancy.fruit.dao.FruitDAO;
import com.fancy.fruit.dao.impl.FruitDAOImpl;
import com.fancy.fruit.pojo.Fruit;
import com.fancy.myssm.basedao.myspringmvc.ViewBaseServlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/add.do")
public class AddServlet extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("UTF-8");
//2.获取参数
String fidStr = req.getParameter("fid");
int fid = Integer.parseInt(fidStr);
String fname = req.getParameter("fname");
String priceStr = req.getParameter("price");
int price = Integer.parseInt(priceStr);
String fcountStr = req.getParameter("fcount");
Integer fcount = Integer.parseInt(fcountStr);
String remark = req.getParameter("remark");
Fruit fruit = new Fruit(fid, fname, price, fcount, remark);
fruitDAO.addFruit(fruit);
resp.sendRedirect("index");
}
}
为什么是doPost?因为input的是表单form
在FruitDAO接口添加新的方法addFruit
package com.fancy.fruit.dao;
import com.fancy.fruit.pojo.Fruit;
import java.util.List;
public interface FruitDAO {
//获取所有的库存列表信息
List<Fruit> getFruitList();
//根据fid获取特定的水果库存信息
Fruit getFruitByFid(Integer fid);
//修改指定的库存记录
void updateFruit(Fruit fruit);
//根据fid删除指定的库存记录
void delFruit(Integer fid);
//添加新库存记录
void addFruit(Fruit fruit);
}
在FruitDAOImpl实现该方法addFruit()
package com.fancy.fruit.dao.impl;
import com.fancy.fruit.dao.FruitDAO;
import com.fancy.fruit.pojo.Fruit;
import com.fancy.myssm.basedao.BaseDAO;
import java.util.List;
public class FruitDAOImpl extends BaseDAO<Fruit> implements FruitDAO {
@Override
public List<Fruit> getFruitList() {
return super.executeQuery("select * from t_fruit");
}
//根据fid获取特定的水果库存信息
@Override
public Fruit getFruitByFid(Integer fid){
return super.load("select * from t_fruit where fid= ? ",fid);
}
@Override
public void updateFruit(Fruit fruit) {
String sql = "update t_fruit set fname = ? , price = ? , fcount = ? , remark = ? where fid = ? " ;
super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark(),fruit.getFid());
}
@Override
public void delFruit(Integer fid){
super.executeUpdate("delete from t_fruit where fid = ? ",fid) ;
}
public void addFruit(Fruit fruit){
String sql = "insert into t_fruit values(0,?,?,?,?,?)";
super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark(),fruit.getFid());
}
}
问题,一直报错Uncaught ReferenceError: page is not defined at HTMLInputElement.onclick
,以下根据我跟着视频敲遗漏造成代码的问题的排错过程,仅供参考,最终解决方案请直接移步“视频36P问题最终解决方案”
没有添加进去?
排错一
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.processTemplate("add.html",req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.processTemplate("add",req,resp);
}
排错二
412-A specified precondition has failed for this request.为此请求指定的先决条件失败。
服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("UTF-8");
//2.获取参数
String fidStr = req.getParameter("fid");
int fid = Integer.parseInt(fidStr);
String fname = req.getParameter("fname");
String priceStr = req.getParameter("price");
int price = Integer.parseInt(priceStr);
String fcountStr = req.getParameter("fcount");
Integer fcount = Integer.parseInt(fcountStr);
String remark = req.getParameter("remark");
Fruit fruit = new Fruit(fid, fname, price, fcount, remark);
fruitDAO.addFruit(fruit);
resp.sendRedirect("index");
}
}
修改后
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("UTF-8");
//2.获取参数
String fname = req.getParameter("fname");
String priceStr = req.getParameter("price");
int price = Integer.parseInt(priceStr);
String fcountStr = req.getParameter("fcount");
Integer fcount = Integer.parseInt(fcountStr);
String remark = req.getParameter("remark");
Fruit fruit = new Fruit(0, fname, price, fcount, remark);
fruitDAO.addFruit(fruit);
resp.sendRedirect("index");
}
}
再次添加
还是412...
再次检查,FruitDAOImpl里的addFruit方法错了
修改前
public void addFruit(Fruit fruit){
String sql = "insert into t_fruit values(0,?,?,?,?,?)";
super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark(),fruit.getFid());
}
修改后
public void addFruit(Fruit fruit){
String sql = "insert into t_fruit values(0,?,?,?,?)";
super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark());
}
视频36P问题最终解决方案
最后还要改add.html,改成@{/adds.do}
<form th:action="@{/adds.do}" method="post">
在AddServlet里加一个doGet方法
public class AddServlet extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.processTemplate("adds",req,resp);
}
实现功能3的过程(添加分页)
实现分页切换功能
①获取指定页码上的库存列表信息,每页显示5条
public interface FruitDAO {
//获取指定页码上的库存列表信息,每页显示5条
List<Fruit> getFruitList(Integer pageNo);
public class FruitDAOImpl extends BaseDAO<Fruit> implements FruitDAO {
@Override
public List<Fruit> getFruitList(Integer pageNo) {
return super.executeQuery("select * from t_fruit limit ?,5",(pageNo-1)*5);
}
public class IndexServlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
FruitDAO fruitDAO = new FruitDAOImpl();
List<Fruit> fruitList = fruitDAO.getFruitList(1);
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>
sample
</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="imgs/css/index.css">
<script type="text/javaScript" src="js/index.js"></script>
<base href="http://localhost:8080/pro11/"/><!--当前页面上所有的路径都已href为基础-->
</head>
<body>
<div id="div_containner">
<div id="div_fruit_list">
<p class="center f30">欢迎使用水果库存后台管理系统</p>
<div style="border:0px solid red;width:60%;margin-left:32%;text-align:right;">
<a th:href="@{/adds.do}" style="border:0px solid blue;margin-bottom:4px;">添加新库存记录</a>
</div>
<table id="tb1_fruit">
<tr>
<th class="w20"><i>名称</i></th>
<th class="w20">单价</th>
<th class="w20">库存</th>
<th>操作</th>
</tr>
<tr th:if="${#lists.isEmpty(session.fruitList)}">
<td colspan="4">sorry, is empty</td>
</tr>
<tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}">
<td> <a th:text="${fruit.fname}" th:href="@{/edit.do(fid=${fruit.fid})}">苹果</a></td>
<td th:text="${fruit.price}">5</td>
<td th:text="${fruit.fcount}">20</td>
<td><img src="imgs/delete.png" class="delImg" th:onclick="|delFruit(${fruit.fid})|"/></td>
</tr>
</table>
<div style="width:60%;margin-left:10%;border:0px;" class="center">
<input type="button" value="首 页" class="btn" th:onclick="|page(1)|"/>
<input type="button" value="上一页" class="btn" th:onclick="|page(${session.pageNo - 1})|"/>
<input type="button" value="下一页" class="btn" th:onclick="|page(${session.pageNo+1})|"/>
<input type="button" value="尾 页" class="btn"/>
</div>
</div>
</div>
</body>
</html>
index.js
function delFruit(fid){
if(confirm("是否确认删除")){
window.location.href='del.do?fid='+fid;
}
}
function page(pageNo){
window.location.href="index?pageNo="+pageNo;
}
②实现尾页跳转效果
package com.fancy.fruit.servlets;
import com.fancy.fruit.dao.FruitDAO;
import com.fancy.fruit.dao.impl.FruitDAOImpl;
import com.fancy.fruit.pojo.Fruit;
import com.fancy.myssm.basedao.myspringmvc.ViewBaseServlet;
import com.fancy.myssm.basedao.util.StringUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
//Servlet从3.0版本开始支持注解方式的注册
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
@Override
public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
Integer pageNo = 1 ;
String pageNoStr = request.getParameter("pageNo");
if(StringUtil.isNotEmpty(pageNoStr)){
pageNo = Integer.parseInt(pageNoStr);
}
HttpSession session = request.getSession() ;
session.setAttribute("pageNo",pageNo);
FruitDAO fruitDAO = new FruitDAOImpl();
List<Fruit> fruitList = fruitDAO.getFruitList(pageNo);
session.setAttribute("fruitList",fruitList);
//总记录条数
int fruitCount = fruitDAO.getFruitCount();
//总页数
int pageCount = (fruitCount+5-1)/5 ;
/*
总记录条数 总页数
1 1
5 1
6 2
10 2
11 3
fruitCount (fruitCount+5-1)/5
*/
session.setAttribute("pageCount",pageCount);
//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称 : index
//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是: / index .html
super.processTemplate("index",request,response);
}
}
③设置首页、上一页、尾页无法点击
<div style="width:60%;margin-left:10%;border:0px;padding-top:5px;" class="center">
<input type="button" value="首 页" class="btn" th:onclick="|page(1)|" th:disabled="${session.pageNo==1}"/>
<input type="button" value="上一页" class="btn" th:onclick="|page(${session.pageNo - 1})|" th:disabled="${session.pageNo==1}" th:disabled="${session.pageNo==1}"/>
<input type="button" value="下一页" class="btn" th:onclick="|page(${session.pageNo+1})|" th:disabled="${session.pageNo==session.pageCount}"/>
<input type="button" value="尾 页" class="btn" th:onclick="|page(${session.pageCount})|" th:disabled="${session.pageNo==session.pageCount}"/>
</div>
实现功能4的过程(根据关键字查询)
在index添加form表单
</head>
<body>
<div id="div_containner">
<div id="div_fruit_list">
<p class="center f30">欢迎使用水果库存后台管理系统</p>
<div style="border:0px solid red;width:60%;margin-left:32%;text-align:right;">
<form th:action="@{search.do}" method="post">
请输入查询关键字:<input type="text" name="keyword"/>
<input type="submit" value="查询" class="btn">
</form>
<a th:href="@{/adds.do}" style="border:0px solid blue;margin-bottom:4px;">添加新库存记录</a>
</div>
①模糊查询(带分页效果)
添加一个隐藏的oper变量
将action改为向index页面发送数据单(action属性用于规定当提交表单时,向何处发送表单数据)
<form th:action="@{/index}" method="post" style="border:1px solid red;">
<input type="hidden" name="oper" value="search"/>
请输入查询关键字:<input type="text" name="keyword"/>
<input type="submit" value="查询" class="btn">
</form>
在IndexServlet添加相应判断条件
//Servlet从3.0版本开始支持注解方式的注册
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
@Override
public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
//添加关键词查询功能
request.setCharacterEncoding("UTF-8");
Integer pageNo = 1 ;
HttpSession session = request.getSession() ;
String oper = request.getParameter("oper");
//如果oper!=null 说明是通过表单的查询按钮点击过来的
//如果oper = null 说明不是通过表单的查询按钮点击过来的
String keyword = null;
if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
//说明是通过表单的查询按钮点击过来的
//此时pageNo应该还原为1,keyword应该从请求参数中获取
pageNo = 1;
keyword = request.getParameter("keyword");
if(StringUtil.isEmpty(keyword)){
keyword = "";
}
session.setAttribute("keyword",keyword);
}else {
//说明此处不是通过表单的查询按钮点击过来的,比如是点击上一页、下一页或直接在地址栏输入
//此时keyword应该从session作用域中获取
String pageNoStr = request.getParameter("pageNo");
if(StringUtil.isNotEmpty(pageNoStr)){
pageNo = Integer.parseInt(pageNoStr);
}
Object keywordObj =session.getAttribute("keyword");
if(keywordObj != null){
keyword = (String) keywordObj;
}else {
keyword = "" ;
}
}
因为index传递过来的是form表单(同之前的edit),这里在doPost方法里调用doGet,因为本次要实现的功能与之前doGet方法的功能差不多,只需要在查询列表时增加keyword关键词判断,所以只需在doGet里实现较为方便。
添加一个隐藏的oper变量,是为了判断keyword是否是通过表单的查询按钮点击过来的,
如果是,需要将pageNo还原为1,因为查询到的结果是从第一页开始显示的,然后我们就从请求参数中获取keyword;并且判断keyword是空的情况(有可能用户什么都没输入点了“查找”),将keyword赋值为空字符串,最后将keyword保存到session作用域中;
如果不是,首先从请求中获取pageNo,判断是否为空,不为空就转化为integer类型变量,再从session作用域中获取keyword对象,不为空则转化为String类型,为空则重新赋值为空字符串。
在FruitDAO接口增加相应方法
import com.fancy.fruit.pojo.Fruit;
import java.util.List;
public interface FruitDAO {
//获取指定页码上的根据关键词检索到的库存列表信息,每页显示5条
List<Fruit> getFruitList(String keyword,Integer pageNo);
//根据fid获取特定的水果库存信息
Fruit getFruitByFid(Integer fid);
//修改指定的库存记录
void updateFruit(Fruit fruit);
//根据fid删除指定的库存记录
void delFruit(Integer fid);
//添加新库存记录
void addFruit(Fruit fruit);
//查询根据关键词检索到的库存总记录条数
int getFruitCount(String keyword);
}
在FruitDAOImpl实现两个方法
public class FruitDAOImpl extends BaseDAO<Fruit> implements FruitDAO {
@Override
public List<Fruit> getFruitList(String keyword,Integer pageNo) {
return super.executeQuery("select * from t_fruit where fname like ? or remark like ? limit ? , 5","%"+keyword+"%","%"+keyword+"%",(pageNo-1)*5);
}
@Override
public int getFruitCount(String keyword) {
return ((Long)super.executeComplexQuery("select count(*) from t_fruit where fname like ? or remark like ?","%"+keyword+"%","%"+keyword+"%")[0]).intValue();
}
在 给方法添加keyword
List<Fruit> fruitList = fruitDAO.getFruitList(keyword,pageNo);
session.setAttribute("fruitList",fruitList);
//总记录条数
int fruitCount = fruitDAO.getFruitCount(keyword);
运行
搜索“果”,查询名称和备注带有果的水果信息
可实现翻页
②查询后关键字一直显示
在index页面加入th:value
<form th:action="@{/index}" method="post" style="border:1px solid red;">
<input type="hidden" name="oper" value="search"/>
请输入查询关键字:<input type="text" name="keyword" th:value="${session.keyword}" />
<input type="submit" value="查询" class="btn">
</form>
查询的关键字可一直显示在框内
以上内容是本人在学习尚硅谷2022新版Javaweb中34-38P的过程中的学习笔记,如有遗漏或错误的地方请私信我,一起交流、共同进步。后续还将跟视频进度同步更新更多内容。
转载本文内容请注明出处。