一、编辑和修改特定的信息
我们想达到的效果为:在页面点击一个水果,然后对这个水果进行编辑,之后更新页面。
第一步:
在水果名称这里增加一个超链接,点击可以跳转到编辑的页面中,
th:href="@{...}" 这样的操作会使得查找的路径从项目的根目录开始,而不是当前的目录下。
通过fid主键来查找数据库中对应的水果
@WebServlet("/edit.do")
public class EditServlet extends ViewBaseServlet {private FruitDAO fruitDAO = new FruitDAOImpl();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String fidStr = req.getParameter("fid");if(StringUtil.isNotEmpty(fidStr)){int fid = Integer.parseInt(fidStr);Fruit fruit = fruitDAO.getFruitByFid(fid);req.setAttribute("fruit",fruit);super.processTemplate("edit",req,resp);}}
}
最后一行是渲染edit.html页面,将查找到的水果信息渲染到edit.html页面中
第二步:修改
我们将这个table表放入表单中可以提交信息。
<p class="center f30">编辑库存信息</p><form th:action="@{/update.do}" method="post"><input type="hidden" name="fid" th:value="${fruit.fid}"/><table id="tbl_fruit" th:object="${fruit}"><tr><th class="w20">名称</th><td><input type="text" name="fname" th:value="*{fname}"/></td></tr><tr><th class="w20">单价</th><td><input type="text" name="price" th:value="*{price}"/></td></tr><tr><th class="w20">库存</th><td><input type="text" name="fcount" th:value="*{fcount}"/></td></tr><tr><th class="w20">备注</th><td><input type="text" name="remark" th:value="*{remark}"/></td></tr><tr><th colspan="2"><input type="submit" value="修改"/></th></tr></table></form>
当点击提交按钮时,会将form表单的数据以post的方式,提交给update.do这个组件
对于每一行中的 th:value=.... 是为了上一步的渲染,能将数据显示到页面上。
没有使用 ${fruit.fname}这样的格式而使用了 *{fname} 因为在table中增加了th:object="${fruit}"。
update.do
@WebServlet("/update.do")
public class UpdateServlet extends ViewBaseServlet {private FruitDAO fruitDAO = new FruitDAOImpl();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");String fidStr = req.getParameter("fid");Integer fid = Integer.parseInt(fidStr);String fname = req.getParameter("fname");String priceStr = req.getParameter("price");Integer price = Integer.parseInt(priceStr);String fcountStr = req.getParameter("fcount");Integer fcount = Integer.parseInt(fcountStr);String remark = req.getParameter("remark");fruitDAO.updateFruit(new Fruit(fid,fname,price,fcount,remark));//此处需要重新向index页面发送请求,将更改后的数据进行渲染。resp.sendRedirect("index");}
}
最后一行要再次向index组件发送请求,将更改后的数据进行渲染。
二、实现删除操作
在操作那一栏中有一个删除的图片,我们想要达到的效果是点击这个图片,会删除这一行的数据。
所以在index页面上
在thymeleaf中 | | 的作用是:将里面的字符串和thymeleaf表达式自动拼接起来
之后使用JS来处理删除操作:
function delFruit(fid){if(confirm('是否确认删除?')){window.location.href='del.do?fid='+fid;}
}
window.location.href 是在页面出现选框后 选确定就会跳转到del.do组件上,并且把fid的值也带着。
当然,我觉得在那里使用超链接到del.do也可以,只是没有一个确认的框框出现。
像这个:
三、实现添加功能
在index页面布置一个添加的地方,然后通过超链接来访问到add.html页面
<html xmlns:th="http://www.thymeleaf.org"><head><meta charset="utf-8"><link rel="stylesheet" href="css/add.css"></head><body><div id="div_container"><div id="div_fruit_list"><p class="center f30">编辑库存信息</p><form action="add.do" method="post"><table id="tbl_fruit"><tr><th class="w20">名称</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 colspan="2"><input type="submit" value="添加"/></th></tr></table></form></div></div></body>
</html>
然后就表单输入数据提交通过action的值来访问 add组件即可。
@WebServlet("/add.do")
public class AddServlet extends ViewBaseServlet {private FruitDAO fruitDAO = new FruitDAOImpl();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");String fname = req.getParameter("fname");String priceStr = req.getParameter("price");Integer price = Integer.parseInt(priceStr);String fcountStr = req.getParameter("fcount");Integer fcount = Integer.parseInt(fcountStr);String remark = req.getParameter("remark");fruitDAO.addFruit(new Fruit(0, fname, price, fcount, remark));resp.sendRedirect("index");}
}
四、页面的分页功能
在实现分页功能的时候,需要注意要获得数据库里的总记录个数,然后将其转换为对应的页数,每一页展示多少自己决定。
所以要理清这三个参数的数学关系。
在input中 按钮有一个属性为disabled:当满足后面的条件时,这个按钮不可用。
比如 第一个意思就是:当页面为1的时候,首页不能点。
Integer pageNo = 1 ;String pageNoStr = req.getParameter("pageNo");if(StringUtil.isNotEmpty(pageNoStr)){pageNo = Integer.parseInt(pageNoStr);}
在index组件上,定义了一个pageNo将所在的页的页数存入。当我们第一次访问index页面时候,pageNo 为1,当点击下一页的时候,pageNo = pageNo +1 ;当点击上一页的时候为 pageNo-1。
步骤:
1、首先控制页面显示的数量:
@Overridepublic List<Fruit> getFruitList(Integer pageNo) {return super.executeQuery("select * from t_fruit limit ?,5",(pageNo-1)*5);}
之前的方法没有参数,且查询的sql语句只是: select * from t_fruit 会显示所有数据,通过Limit限制即可。
2、确定共有多少页
@Overridepublic int getFruitCount() {return ((Long)super.executeComplexQuery("select count(*) from t_fruit")[0]).intValue();}
pageCount:总页数
根据之前编写的dao方法来处理。并且在index组件上把pageNo保存在session中,方便在页面上使用。
3、在页面上实现
<div style="width:60%;margin-left:20%;" 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}"/><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>
js文件中的page函数:
function page(pageNo){window.location.href="index?pageNo="+pageNo;
}
相当于在访问一次index组件,并且把更新的pageNo也带进去重新渲染。
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Integer pageNo = 1 ;String pageNoStr = req.getParameter("pageNo");if(StringUtil.isNotEmpty(pageNoStr)){pageNo = Integer.parseInt(pageNoStr);}HttpSession session = req.getSession();session.setAttribute("pageNo",pageNo);FruitDAO fruitDAO = new FruitDAOImpl();List<Fruit> fruitList = fruitDAO.getFruitList(pageNo);int fruitCount = fruitDAO.getFruitCount();int pageCount = (fruitCount+5-1)/5 ;//保存到session作用域session.setAttribute("fruitList",fruitList);session.setAttribute("pageCount",pageCount);super.processTemplate("index",req,resp);}
}
过程:一开始访问index组件的时候,pageNo为空,使用我们初始化的pageNo来显示。当点击下一页或者尾页这些操作的时候,会对应的改变pageNo的值,
之后通过js里的代码再次访问index组件,并且将新的pageNo的值传入,因此第二次的pageNo为request中所带的。然后在通过函数getFruitList(pageNo)来更新页面即可。
五、根据关键字查询
1、根据关键字查询在sql里面相当于是模糊查询。因此在dao来访问数据库的时候对应操作的sql语言也应该有关键字存在:
@Overridepublic 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);}
2、在index页面,查询部分用表单来发送关键字:
<form th:action="@{/index}" method="post"><input type="hidden" name="oper" value="search"/>请输入关键字:<input type="text" name="keyword"/><input type="submit" value="查询" class="btn"/></form>
3、在index组件中,需要判断发来的请求是通过点击查询的请求还是点击页面其他按钮的请求:
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");Integer pageNo = 1 ;HttpSession session = req.getSession();String oper = req.getParameter("oper");//如果oper为空,说明不是点击查询按钮来访问 /index 的String keyword = null;if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){//说明此时是点击 查询来进入index组件的,keyword可以从查询的表单中获取pageNo=1 ;keyword = req.getParameter("keyword");if(StringUtil.isEmpty(keyword)){keyword="";}session.setAttribute("keyword",keyword);}else {//说明此处不是通过点击查询来发送请求的,当点击下面的 页数的时候String pageNoStr = req.getParameter("pageNo");if(StringUtil.isNotEmpty(pageNoStr)){pageNo = Integer.parseInt(pageNoStr);}Object keywordObj = session.getAttribute("keyword");if(keywordObj!=null){keyword = (String)keywordObj;}else{keyword="";}}session.setAttribute("pageNo",pageNo);FruitDAO fruitDAO = new FruitDAOImpl();List<Fruit> fruitList = fruitDAO.getFruitList(keyword, pageNo);int fruitCount = fruitDAO.getFruitCount(keyword);int pageCount = (fruitCount+5-1)/5 ;//保存到session作用域session.setAttribute("fruitList",fruitList);session.setAttribute("pageCount",pageCount);super.processTemplate("index",req,resp);}
}
代码逻辑:当第一次访问index组件时候,没有点击查询操作,因此oper的值为空,所以会进入第一个else语句中,同时keyword的值也是初始化的值null且会话里也没有keyword的值,所以
这一段获得的值为null。因此keyword的值就赋值为空字符串,然后在模糊查询中 %keyword%,由于keyword为空就相当于全查询,所以页面就会显示所有数据。
当我们输入关键字并且点击查询之后,此时oper就有值了且为search,进入if语句中
之后获取到关键字的值。并且存入session中,方便之后使用。
输入关键字点击查询之后,页面展示的数据就是与关键字有关的数据,此时当点击下一页的时候,keyword的值还在session中保存着不变,改变的仅有pageNo。