前置知识
前置准备
知识准备
已掌握JavaSE/MySQL/JDBC+HTML/CSS/JavaScript基础
并已完成了Javaweb前置知识的学习
01-JavaWeb-HTML初识
02-JavaWeb-CSS初识
03-JavaWeb-JavaScript初识
04-JavaScript基础应用-鼠标悬浮/离开表格格式变化
05-JavaWeb-Tomcat8安装、Servlet初识
06-JavaWeb-Servlet方法/生命周期、HTTP/会话session
07-JavaWeb-视图模板技术Thymeleaf的使用
08-JavaWeb-Servlet保存作用域
09-JavaWeb-阶段性项目1:最简单的后台库存管理系统
资源准备
教学资源
https://pan.baidu.com/s/1TS7QJ_a2vHHmXkggAs8RMQ
提取码:yyds
理解项目1的过程
服务端-thymeleaf渲染-servlet-FruitDAO-数据库
可以看出servlet根据业务的增多会不断增加,大量servlet组件很难维护、也很复杂,所以需要进行优化。
servlet优化的过程1
将所有servlet放在一个FruitServlet组件中,该组件包含各个功能,根据前端发过来的请求可以调用不同的方法实现不同功能。
这里是模板方法设计模式,模板方法设计模式在实际开发中是一种使用非常广泛的设计模式,也是一种非常重要的思想。其核心内容为:通过定义一个模板类,在模板类中规定其整体的骨架并确定哪些方法是允许子类去重写,哪些不允许子类重写或者哪些必须子类重写,其目的是保证其核心算法不被破坏。定义完模板类后,写出具体的子类去继承模板类并按规定好的框架来完成子类的定义。
增加FruitServlet组件
将所有servlet放在一个FruitServlet组件中,该组件包含各个功能
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;
@WebServlet("/fruit.do")
public class FruitServlet extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String operate = req.getParameter("operate");
if(StringUtil.isEmpty(operate)){
operate = "index";
}
switch (operate){
case "index":
index(req, resp);
break;
case "add":
add(req, resp);
break;
case "del":
del(req, resp);
break;
case "edit":
edit(req, resp);
break;
case "update":
update(req, resp);
break;
}
}
private void update(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");
//3.执行更新
fruitDAO.updateFruit(new Fruit(fid,fname,price,fcount,remark));
//4.资源跳转
//super.processTemplate("index",req,resp);
//此处需要重定向,目的是重新给IndexServlet发请求,然后覆盖到session中,这样index页面上显示的数据才是最新的
resp.sendRedirect("index");//重定向,重新给index,给session重新给fruit更改后的数据
}
private void edit(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);
}
}
private void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
//获取fid
String fidStr = req.getParameter("fid");
if(StringUtil.isNotEmpty(fidStr)){
int fid = Integer.parseInt(fidStr);
fruitDAO.delFruit(fid);
resp.sendRedirect("index");
}
}
private void add(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");
}
private void index(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
//添加关键词查询功能
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 = "" ;
}
}
session.setAttribute("pageNo",pageNo);
FruitDAO fruitDAO = new FruitDAOImpl();
List<Fruit> fruitList = fruitDAO.getFruitList(keyword,pageNo);
session.setAttribute("fruitList",fruitList);
//总记录条数
int fruitCount = fruitDAO.getFruitCount(keyword);
//总页数
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);
}
}
此时servlet响应的功能与operate值绑定
把所有功能的servlet合成一个fruitservlet通过获取前段页面的请求参数不同,来调用相应的功能方法
改index页面
<p class="center f30">欢迎使用水果库存后台管理系统</p>
<div style="border:0px solid red;width:60%;margin-left:32%;text-align:right;">
<form th:action="@{/fruit.do}" method="post" style="border:1px solid red;">
<td> <a th:text="${fruit.fname}" th:href='@{/fruit.do(fid=${fruit.fid},operate="edit")}'>苹果</a></td>
改index.js文件
function delFruit(fid){
if(confirm("是否确认删除")){
window.location.href='fruit.do?fid='+fid+'&operate=del';
}
}
function page(pageNo){
window.location.href="fruit.do?pageNo="+pageNo;
}
改FruitServlet中的del方法
重定向给fruit.do
private void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
//获取fid
String fidStr = req.getParameter("fid");
if(StringUtil.isNotEmpty(fidStr)){
int fid = Integer.parseInt(fidStr);
fruitDAO.delFruit(fid);
resp.sendRedirect("fruit.do");
}
}
改add.html页面
<form th:action="@{/fruit.do}" method="post">
在下方增加一个隐藏的input,将operate赋值为add,进行添加操作
<input type="hidden" name="operate" value="add"/>
同理FruitServlet中的del方法也要重定向给fruit.do。resp.sendRedirect("fruit.do");
改edit.html页面
<input type="hidden" name="operate" value="update"/>
运行
访问http://localhost:8080/pro13/fruit.do
如果报500错误请确认跟着视频敲的代码是否正确,projectstructure是否配置正确
正常出现页面但是数据没有出来,说明thymeleaf有问题
看报错信息
Could not parse as expression: "@{/fruit.do(fid=${fruit.fid},
改index.html
<td> <a th:text="${fruit.fname}" th:href='@{/fruit.do(fid=${fruit.fid},operate="edit")}'>苹果</a></td>
<td> <a th:text="${fruit.fname}" th:href="@{/fruit.do(fid=${fruit.fid},operate='edit')}">苹果</a></td>
经过了以上改动,servlet数量大大缩减