M1(servlet优化)
1.核心思想
把所有功能的servlet合成一个servlet
通过获取前段页面的请求参数不同,来调用相应的功能方法
2.示意图
优化前:
优化后:
3.代码
A.重写service方法
public class FruitServlet extends ViewBaseServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
B.设置路径
@WebServlet("/fruit.do")
C.获取请求的网页对应的参数
// 设置编码,防止乱码问题
request.setCharacterEncoding("utf-8");
// 获取请求的网页对应的参数
String operate = request.getParameter("operate");
// 安全控制,没有参数则默认为index
if (Util.isEmpty(operate)) {
operate = "index";
}
B.switch调用不同的方法
switch (operate){
case "index":
index(request,response);
// 防止穿透!!!
break;
case "add":
add(request,response);
break;
case "del":
del(request,response);
break;
case "edit":
edit(request,response);
break;
case "update":
update(request,response);
break;
default:
throw new RuntimeException("operate参数非法!!!");
C.注意
注意:doGet方法和doPost方法同时存在,没有关系,都经过service方法!!!
可以使用request.getMethod()返回的String指明了客户端的提交方式
request.getMethod().equals("GET");
request.getMethod().equals("POST");
D.五大方法
index方法
- index方法
private void index(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取session作用域
HttpSession session = request.getSession();
// 获取请求的页码
int pageNo = 1;
// 搜索的关键字
String keyword = "";
// 每页显示五条记录
int pageSize = 5;
// 判断当前请求为正常请求,或是搜索请求
if ("search".equals(request.getParameter("oper"))) {
// 执行到这里,说明是点击了搜索按钮
//此时,pageNo应该还原为1(默认) , keyword应该从请求参数中获取
// 获取关键字,用关键字向数据库中搜索
// 关键字非法的话,设置为空串
if (!(Util.isEmpty(request.getParameter("keyword")))) {
keyword = request.getParameter("keyword");
}
}else {
Object keywordObj = session.getAttribute("keyword");
// 合法控制,为NULL就不保存,否则保存
if (keywordObj != null) {
// 强制类型转换,说明当前请求不是第一次,获取关键字来查询数据库,无论它是之前的搜索请求还是正常请求
keyword = (String) keywordObj;
}
// 获取当前页数,判断是否合法,不合法默认设置页码为首页
if (!(Util.isEmpty(request.getParameter("pageNo")))) {
pageNo = Integer.parseInt(request.getParameter("pageNo"));
}
}
// 从数据库中获取列表
List<Fruit> fruitList = fruitDAO.getFruitList(keyword,(pageNo-1)*pageSize,pageSize);
// 将水果放入请求的session作用域中
session.setAttribute("fruit",fruitList);
// 根据总条数,求出总页数
int count = fruitDAO.getFruitCount(keyword);
int pageCount = (count + pageSize - 1) / pageSize;
// 将当前页码和总页码,关键字keyword放入session作用域中
session.setAttribute("pageNo",pageNo);
session.setAttribute("pageCount",pageCount);
session.setAttribute("keyword",keyword);
// 将请求转发到视图上
super.processTemplate("index",request,response);
}
- index.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link rel="stylesheet" th:href="@{/css/index.css}">
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script th:src="@{/js/index.js}"></script>
</head>
<body>
<div id="div_container">
<div id="div_fruit_list">
<p class="center f30">欢迎使用水果库存后台管理系统</p>
<div style="border:0px solid red;width:60%;margin-left:20%;text-align:center;text-decoration: none">
<form th:action="@{/fruit.do(operate='index')}" method="post" style="float:left;width:60%;border:0px solid green">
<input type="hidden" name="oper" value="search"/>
请输入关键字:<input style="border:0px solid blue;margin-bottom:5px;" type="text" name="keyword" th:value="${session.keyword}"/>
<input type="submit" value="查询" class="btn"/>
</form>
<a th:href="@{/fruit.do(operate='add')}" style="border:0px solid blue;margin-bottom:4px;">添加新库存记录</a>
</div>
<table id="tbl_fruit">
<th class="w20">名称</th>
<th class="w20">单价</th>
<th class="w20">库存</th>
<th>操作</th>
</tr>
<!-- 如果链表为空-->
<tr th:if="${#lists.isEmpty(session.fruit)}">
<td colspan="4">对不起,库存为空!</td>
</tr>
<!-- 如果链表不为空,取出数据-->
<tr th:unless="${#lists.isEmpty(session.fruit)}" th:each="fruit : ${session.fruit}">
<td><a th:href="@{/fruit.do(fid=${fruit.getFid()},operate='edit')}" th:text="${fruit.getFname()}"></a></td>
<td th:text="${fruit.getFprice()}">5</td>
<td th:text="${fruit.getFstock()}">20</td>
<td><img th:src="@{/imgs/del.jpg} " class="delImg" th:name="${fruit.getFid()}"></td>
</tr>
</table>
<div style="width:60%;margin-left:20%;border:0px solid red;padding-top:4px;" class="center">
<input type="button" value="首 页" class="btn" pageNo="1" th:disabled="${session.pageNo == 1}"/>
<input type="button" value="上一页" class="btn" th:pageNo="${(session.pageNo)-1}" th:disabled="${session.pageNo == 1}"/>
<input type="button" value="下一页" class="btn" th:pageNo="${(session.pageNo)+1}" th:disabled="${session.pageNo == session.pageCount}"/>
<input type="button" value="尾 页" class="btn" th:pageNo="${session.pageCount}" th:disabled="${session.pageNo == session.pageCount}"/>
</div>
<div style="width:60%;margin-left:20%;border:0px solid red;padding-top:4px;" class="center"
th:text="${session.pageNo} +'/'+ ${session.pageCount}">
</div>
</div>
</div>
</body>
</html>
- index.js
$(function () {
$(document).on("click", "img", function () {
var fid = $(this).attr("name");
if (confirm("请问确认删除编号为" + fid + "的水果吗?")) {
$(window).attr("location", "fruit.do?operate=del&fid=" + fid)
}
});
$(document).on("click", "input:button", function () {
$(window).attr("location", "fruit.do?operate=index&pageNo=" + $(this).attr("pageNo"))
})
})
add方法
- add方法
private void add(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// GET请求执行的分支!!!
if (request.getMethod().equals("GET")) {
super.processTemplate("add",request,response);
return;
}
// 获取表单数据
String fname = request.getParameter("Fname");
String fprice = request.getParameter("Fprice");
String fstock = request.getParameter("Fstock");
if (Util.isEmpty(fname) || Util.isEmpty(fprice) || Util.isEmpty(fstock)) {
throw new RuntimeException("输入非法!!!");
}
// 创建对象
Fruit fruit = new Fruit(0, fname, Double.parseDouble(fprice),Integer.parseInt(fstock));
fruitDAO.addFruit(fruit);
// 重定向到index页面
response.sendRedirect("fruit.do?operate=index");
}
- add.html
...
<!-- 自定义变量-->
<!-- 注意:form无法使用?的发生发送参数,需要使用隐藏域!!!-->
<form method="post" th:action="@{/fruit.do}">
<!-- 隐藏作用域-->
<input type="hidden" operate="add">
...
del方法
private void del(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取发送的fid
String fid = request.getParameter("fid");
if (Util.isEmpty(fid)) {
throw new RuntimeException("请求非法!!!");
}
fruitDAO.delFruit(Integer.valueOf(fid));
// 客户端重定向
response.sendRedirect("fruit.do?operate=index");
}
edit方法
edit方法
private void edit(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取发送的信息
String fid = request.getParameter("fid");
// 判断字符串是否合法(使用工具类)
if (Util.isEmpty(fid)) {
throw new RuntimeException("字符串为空串!!!");
}
// 向DAO层获取水果信息,向下转型为数字
Fruit fruitByFid = fruitDAO.getFruitByFid(Integer.valueOf(fid));
// 放入作用域
request.setAttribute("fruit",fruitByFid);
// 将请求转发到edit视图上
super.processTemplate("edit",request,response);
}
edit.html
......
<form method="post" th:object="${fruit}" th:action="@{/fruit.do}">
<input type="hidden" name="operate" th:value="update">
......
update方法
private void update(HttpServletRequest request, HttpServletResponse response) throws IOException {
String fid = request.getParameter("Fid");
String fname = request.getParameter("Fname");
String fprice = request.getParameter("Fprice");
String fstock = request.getParameter("Fstock");
if (Util.isEmpty(fname)||Util.isEmpty(fprice)||Util.isEmpty(fstock)) {
throw new RuntimeException("输入非法!!!");
}
Fruit fruit = new Fruit(Integer.parseInt(fid), fname, Double.parseDouble(fprice), Integer.parseInt(fstock));
fruitDAO.updateFruit(fruit);
// 要求客户端重定向,更新数据!!!
response.sendRedirect("fruit.do?operate=index");
}
4.涉及代码
A.fruit.do组件
package servlets;
import DAO.FruitDAO;
import DAO.impl.FruitDAOImpl;
import pojo.Fruit;
import util.Util;
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 request, HttpServletResponse response)
throws ServletException, IOException {
// 设置编码,防止乱码问题
request.setCharacterEncoding("utf-8");
// 获取请求的网页对应的参数
String operate = request.getParameter("operate");
// 安全控制,没有参数则默认为index
if (Util.isEmpty(operate)) {
operate = "index";
}
switch (operate) {
case "index":
index(request, response);
// 防止穿透!!!
break;
case "add":
add(request, response);
break;
case "del":
del(request, response);
break;
case "edit":
edit(request, response);
break;
case "update":
update(request, response);
break;
default:
throw new RuntimeException("operate参数非法!!!");
}
}
private void index(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取session作用域
HttpSession session = request.getSession();
// 获取请求的页码
int pageNo = 1;
// 搜索的关键字
String keyword = "";
// 每页显示五条记录
int pageSize = 5;
// 判断当前请求为正常请求,或是搜索请求
if ("search".equals(request.getParameter("oper"))) {
// 执行到这里,说明是点击了搜索按钮
//此时,pageNo应该还原为1(默认) , keyword应该从请求参数中获取
// 获取关键字,用关键字向数据库中搜索
// 关键字非法的话,设置为空串
if (!(Util.isEmpty(request.getParameter("keyword")))) {
keyword = request.getParameter("keyword");
}
} else {
Object keywordObj = session.getAttribute("keyword");
// 合法控制,为NULL就不保存,否则保存
if (keywordObj != null) {
// 强制类型转换,说明当前请求不是第一次,获取关键字来查询数据库,无论它是之前的搜索请求还是正常请求
keyword = (String) keywordObj;
}
// 获取当前页数,判断是否合法,不合法默认设置页码为首页
if (!(Util.isEmpty(request.getParameter("pageNo")))) {
pageNo = Integer.parseInt(request.getParameter("pageNo"));
}
}
// 从数据库中获取列表
List<Fruit> fruitList = fruitDAO.getFruitList(keyword, (pageNo - 1) * pageSize, pageSize);
// 将水果放入请求的session作用域中
session.setAttribute("fruit", fruitList);
// 根据总条数,求出总页数
int count = fruitDAO.getFruitCount(keyword);
int pageCount = (count + pageSize - 1) / pageSize;
// 将当前页码和总页码,关键字keyword放入session作用域中
session.setAttribute("pageNo", pageNo);
session.setAttribute("pageCount", pageCount);
session.setAttribute("keyword", keyword);
// 将请求转发到视图上
super.processTemplate("index", request, response);
}
private void add(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (request.getMethod().equals("GET")) {
super.processTemplate("add",request,response);
return;
}
// 获取表单数据
String fname = request.getParameter("Fname");
String fprice = request.getParameter("Fprice");
String fstock = request.getParameter("Fstock");
if (Util.isEmpty(fname) || Util.isEmpty(fprice) || Util.isEmpty(fstock)) {
throw new RuntimeException("输入非法!!!");
}
// 创建对象
Fruit fruit = new Fruit(0, fname, Double.parseDouble(fprice), Integer.parseInt(fstock));
fruitDAO.addFruit(fruit);
// 重定向到index页面
response.sendRedirect("fruit.do?operate=index");
}
private void del(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取发送的fid
String fid = request.getParameter("fid");
if (Util.isEmpty(fid)) {
throw new RuntimeException("请求非法!!!");
}
fruitDAO.delFruit(Integer.valueOf(fid));
// 客户端重定向
response.sendRedirect("fruit.do?operate=index");
}
private void edit(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取发送的信息
String fid = request.getParameter("fid");
// 判断字符串是否合法(使用工具类)
if (Util.isEmpty(fid)) {
throw new RuntimeException("字符串为空串!!!");
}
// 向DAO层获取水果信息,向下转型为数字
Fruit fruitByFid = fruitDAO.getFruitByFid(Integer.valueOf(fid));
// 放入作用域
request.setAttribute("fruit",fruitByFid);
// 将请求转发到edit视图上
super.processTemplate("edit",request,response);
}
private void update(HttpServletRequest request, HttpServletResponse response) throws IOException {
String fid = request.getParameter("Fid");
String fname = request.getParameter("Fname");
String fprice = request.getParameter("Fprice");
String fstock = request.getParameter("Fstock");
if (Util.isEmpty(fname)||Util.isEmpty(fprice)||Util.isEmpty(fstock)) {
throw new RuntimeException("输入非法!!!");
}
Fruit fruit = new Fruit(Integer.parseInt(fid), fname, Double.parseDouble(fprice), Integer.parseInt(fstock));
fruitDAO.updateFruit(fruit);
// 要求客户端重定向,更新数据!!!
response.sendRedirect("fruit.do?operate=index");
}
}
B.add.html
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" th:href="@{/css/index.css}">
<script language="JavaScript" th:src="@{/js/index.js}"></script>
</head>
<body>
<div id="div_container">
<div id="div_fruit_list">
<p class="center f30">添加库存信息</p>
<!-- 自定义变量-->
<!-- 注意:form无法使用?的发生发送参数,需要使用隐藏域!!!-->
<form method="post" th:action="@{/fruit.do}">
<!-- 隐藏作用域-->
<input type="hidden" name = "operate" value="add">
<table id="tbl_fruit">
<tr>
<td class="w20">名称</td>
<td><input type="text" name="Fname"></td>
</tr>
<tr>
<td class="w20">单价</td>
<td><input type="text" name="Fprice"></td>
</tr>
<tr>
<td class="w20">库存</td>
<td><input type="text" name="Fstock"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="添加" /></td>
</tr>
</table>
</form>
</div>
</div>
</body>
</html>
C.edit.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link rel="stylesheet" th:href="@{/css/index.css}">
<script language="JavaScript" th:src="@{/js/index.js}"></script>
</head>
<body>
<div id="div_container">
<div id="div_fruit_list">
<p class="center f30">编辑库存信息</p>
<!-- 自定义变量-->
<form method="post" th:object="${fruit}" th:action="@{/fruit.do}">
<input type="hidden" name="operate" th:value="update">
<table id="tbl_fruit">
<!--编号--->
<!-- 隐藏域 : 功能类似于文本框 , 它的值会随着表单的发送也会发送给服务器,但是界面上用户看不到 -->
<input type="hidden" name="Fid" th:value="*{getFid()}">
<tr>
<td class="w20">名称</td>
<td><input type="text" name="Fname" th:value="*{getFname()}"></td>
</tr>
<tr>
<td class="w20">单价</td>
<td><input type="text" name="Fprice" th:value="*{getFprice()}"></td>
</tr>
<tr>
<td class="w20">库存</td>
<td><input type="text" name="Fstock" th:value="*{getFstock()}"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="修改" /></td>
</tr>
</table>
</form>
</div>
</div>
</body>
</html>
D.index.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<link rel="stylesheet" th:href="@{/css/index.css}">
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script th:src="@{/js/index.js}"></script>
</head>
<body>
<div id="div_container">
<div id="div_fruit_list">
<p class="center f30">欢迎使用水果库存后台管理系统</p>
<div style="border:0px solid red;width:60%;margin-left:20%;text-align:center;text-decoration: none">
<form th:action="@{/fruit.do(operate='index')}" method="post" style="float:left;width:60%;border:0px solid green">
<input type="hidden" name="oper" value="search"/>
请输入关键字:<input style="border:0px solid blue;margin-bottom:5px;" type="text" name="keyword" th:value="${session.keyword}"/>
<input type="submit" value="查询" class="btn"/>
</form>
<a th:href="@{/fruit.do(operate='add')}" style="border:0px solid blue;margin-bottom:4px;">添加新库存记录</a>
</div>
<table id="tbl_fruit">
<th class="w20">名称</th>
<th class="w20">单价</th>
<th class="w20">库存</th>
<th>操作</th>
</tr>
<!-- 如果链表为空-->
<tr th:if="${#lists.isEmpty(session.fruit)}">
<td colspan="4">对不起,库存为空!</td>
</tr>
<!-- 如果链表不为空,取出数据-->
<tr th:unless="${#lists.isEmpty(session.fruit)}" th:each="fruit : ${session.fruit}">
<td><a th:href="@{/fruit.do(fid=${fruit.getFid()},operate='edit')}" th:text="${fruit.getFname()}"></a></td>
<td th:text="${fruit.getFprice()}">5</td>
<td th:text="${fruit.getFstock()}">20</td>
<td><img th:src="@{/imgs/del.jpg} " class="delImg" th:name="${fruit.getFid()}"></td>
</tr>
</table>
<div style="width:60%;margin-left:20%;border:0px solid red;padding-top:4px;" class="center">
<input type="button" value="首 页" class="btn" pageNo="1" th:disabled="${session.pageNo == 1}"/>
<input type="button" value="上一页" class="btn" th:pageNo="${(session.pageNo)-1}" th:disabled="${session.pageNo == 1}"/>
<input type="button" value="下一页" class="btn" th:pageNo="${(session.pageNo)+1}" th:disabled="${session.pageNo == session.pageCount}"/>
<input type="button" value="尾 页" class="btn" th:pageNo="${session.pageCount}" th:disabled="${session.pageNo == session.pageCount}"/>
</div>
<div style="width:60%;margin-left:20%;border:0px solid red;padding-top:4px;" class="center"
th:text="${session.pageNo} +'/'+ ${session.pageCount}">
</div>
</div>
</div>
</body>
</html>
E.index.js
$(function () {
$(document).on("click", "img", function () {
var fid = $(this).attr("name");
if (confirm("请问确认删除编号为" + fid + "的水果吗?")) {
$(window).attr("location", "fruit.do?operate=del&fid=" + fid)
}
});
$(document).on("click", "input:button", function () {
$(window).attr("location", "fruit.do?operate=index&pageNo=" + $(this).attr("pageNo"))
})
})