🐇servlet合并
增加隐藏域
合并到MemberServlet
🍎反射+模板设计模式+动态代理
新建BasicServlet类, 继承HttpServlet
java
public class BasicServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
try {
//1.得到子类对应的class对象
Class<? extends BasicServlet> aClass = this.getClass();
//2.创建对象
Object o = aClass.newInstance();
//3.得到action方法对象
Method declaredMethod = this.getClass()
.getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
declaredMethod.invoke(o, req, resp);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
子类中没有doGet, doPost方法, 会调用父类的doGet, doPost.
🌳显示家居
需求分析
给后台管理提供独立登陆页面 manage_login.jsp(已提供)
管理员(admin表)登陆成功后, 显示管理菜单页面
管理员点击家居管理, 显示所有家居信息
程序框架图
页面准备
新建admin表 👉 参考member表
新建furn表
新建Admin实体类
新建Furn实体类(无参构造器与set方法底层反射用, get方法前端EL表达式用)
书写AdminDAO, AdminDAOImpl, 并测试; 书写AdminService, AdminServiceImpl, 并测试 👉 参考Member
书写FurnDAO, FurnDAOImpl 👉 并测试书写FurnService, FurnServiceImpl 👉 并测试
- 接通web层
管理员登录Servlet
java
public class AdminServlet extends BasicServlet {
private AdminService adminService = new AdminServiceImpl();
protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
Admin admin = new Admin(null, username, password, null);
if (adminService.login(admin)) {
//管理员登录成功
request.getRequestDispatcher("/views/manage/manage_menu.jsp")
.forward(request, response);
} else {
System.out.println("登陆失败, 返回登陆页面");
request.setAttribute("username", username);
request.setAttribute("msg", "用户名或密码不正确");
request.getRequestDispatcher("/views/manage/manage_login.jsp")
.forward(request, response);
}
}
}
家居显示Servlet
xml
<servlet>
<servlet-name>FurnServlet</servlet-name>
<servlet-class>com.zzw.furn.web.FurnServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FurnServlet</servlet-name>
<url-pattern>/manage/furnServlet</url-pattern>
</servlet-mapping>
java
public class FurnServlet extends BasicServlet {
private FurnService furnService = new FurnServiceImpl();
protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Furn> furns = furnService.queryFurn();
//将结果保存到request域
request.setAttribute("furns", furns);
//请求转发到管理家具页面
request.getRequestDispatcher("/views/manage/furn_manage.jsp")
.forward(request, response);
}
}
- 前端页面
manage_login.jsp, 管理员登录页面
html
<span class="errorMsg"
style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;">${msg}</span>
<%--管理员登陆--%>
<form action="adminServlet" method="post">
<input type="hidden" name="action" value="login"/>
<input type="text" name="username" value="${username}" placeholder="Username"/>
<input type="password" name="password" placeholder="Password"/>
<div class="button-box">
<div class="login-toggle-btn">
<input type="checkbox"/>
<a class="flote-none" href="javascript:void(0)">Remember me</a>
<a href="#">Forgot Password?</a>
</div>
<button type="submit"><span>Login</span></button>
</div>
</form>
manage_menu.jsp, 家居菜单页面
furn_manage.jsp, 家居显示页面
<c:forEach items="${requestScope.furns}" var="furn"> items里用EL表达式括起来, var里不用EL表达式
🌳添加家居
思路分析
- 请求添加家居, 请求FurnServlet的add方法, 将前端提交的数据封装到Furn对象
- 调用FurnService.add(Furn furn)方法
- 跳转到显示家居的页面
程序框架图
- FurnDAO
- FurnService
- web层
FurnServlet
java
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String business = req.getParameter("business");
BigDecimal price = new BigDecimal(req.getParameter("price"));
int saleNum = DataUtils.parseInt(req.getParameter("saleNum"), 0);
int inventory = DataUtils.parseInt(req.getParameter("inventory"), 0);
Furn furn = new Furn(null, name,
business, price, saleNum, inventory, "...");
if (furnService.add(furn) > 0) {
System.out.println("添加成功, 请求转发到list");
//req.getRequestDispatcher("/manage/furnServlet?action=list")
// .forward(req, resp);
resp.sendRedirect(req.getContextPath() + "//manage/furnServlet?action=list");
} else {
System.out.println("添加失败, 返回到添加页面");
req.getRequestDispatcher("views/manage/furn_add.jsp")
.forward(req, resp);
}
}
解决中文乱码问题
- 前端: furn_manage跳转到添加家居页面
html
<!-- Single Wedge Start -->
<div class="header-bottom-set dropdown">
<a href="views/manage/furn_add.jsp">添加家居</a>
</div>
html
<!--添加在tr标签的下一行-->
<span class="errorMsg"
style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;"></span>
🍉解决重复添加
请求转发, 当用户刷新页面时, 会重新发出第一次的请求, 造成数据重复提交
解决方案: 使用重定向
🍉后端数据校验说明
后端方案一
后端方案二
前端数据校验
js
$(":submit").click(function () {
var price = $("input[name='price']").val();
var saleNum = $("input[name='saleNum']").val();
var inventory = $("input[name='inventory']").val();
//价格 非零开头最多两位小数
var priceRegExp = /^[1-9]\d*(\.\d{1,2})?$/;
if (!priceRegExp.test(price)) {
$("span.errorMsg").text("价格格式不对");
return false;
}
//销量 非零开头正整数
var saleNumRegExp = /^0$|^[1-9]\d*$/;
if (!saleNumRegExp.test(saleNum)) {
$("span.errorMsg").text("销量格式不对");
return false;
}
//库存 非零开头正整数
var inventoryRegExp = /^0$|^[1-9]\d*$/;
if (!inventoryRegExp.test(inventory)) {
$("span.errorMsg").text("库存格式不对");
return false;
}
})
🍉BeanUtils自动封装Bean
引入: commons-logging-1.1.1.jar, commons-beanutils-1.8.0.jar
- 使用BeanUtils自动封装javabean
java
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//这里我们使用第二种方式, 将前端提交的数据, 自动封装成Furn的Javabean对象
//使用beanUtils完成javabean对象的自动封装
Furn furn =
DataUtils.copyParamToBean(req.getParameterMap(), new Furn());
if (furnService.addFurn(furn)) {
String pageNo = req.getParameter("pageNo");
System.out.println("添加成功..");
//req.getRequestDispatcher("/manage/furnServlet?action=list").forward(req, resp);
resp.sendRedirect(req.getContextPath() + "/manage/furnServlet?action=list");
} else {
System.out.println("添加失败");
req.setAttribute("errorMsg", "添加失败");
req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);
}
}
debug小技巧👉
- 报错
原因: 由于前端没有传imagePath的字段, 所以后端在构建furn对象的时候, imagePath属性位null
解决方案 👇
- 将 把数据自动封装成JavaBean的功能封装到工具类
javapublic class DataUtils { //将方法, 封装到静态方法, 方便使用 public static <T> T copyParamToBean(Map value, T bean) { try { BeanUtils.populate(bean, value); } catch (Exception e) { throw new RuntimeException(e); } return bean; } }
调用
🌳删除家居
需求分析
- 管理员进入到家居管理页面
- 点击删除家居链接, 弹出确认窗口, 确认-删除, 取消-放弃
程序框架图
- FurnDAO
- FurnService
- web层 - FurnServlet
java
protected void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = DataUtils.parseInt(req.getParameter("id"), 0);
if (furnService.deleteFurnById(id) > 0) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
resp.sendRedirect(req.getContextPath() + "/manage/furnServlet?action=list");
}
- furn_manage.jsp页面
html
<a furnName="${furn.name}" href="manage/furnServlet?action=del&id=${furn.id}">
<i class="icon-close"></i>
</a>
jQuery操作父元素, 兄弟元素, 子元素, 请移步👉
js弹框请移步👉
js
$("a[furnName]").click(function () {
var furnName = $(this).attr("furnName");
//js弹框
//1.window.confirm 方法会弹出一个确认窗口
//2.点击确定, 返回true
//3.点击取消, 返回false
var b = window.confirm("你确认要删除 " + furnName+ " 家居信息吗?");
if (!b) {
return false;
}
//简便写法
return window.confirm("你确认要删除 " + furnName+ " 家居信息吗?");
//最终写法
return confirm("你确定要删除 " + furnName + " 家居信息嘛?");
});
🌳修改家具
思路分析
- 管理员进入家居管理页面furn_manage.jsp
- 点击修改家居链接, 回显该家居信息 furn_update.jsp
- 填写新的信息, 点击修改家居按钮
- 修改成功后, 显示刷新后的家居列表
程序框架图
- FurnDAO
- FurnService
- web层 - FurnServlet
java
protected void display(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = DataUtils.parseInt(req.getParameter("id"), 0);
Furn furn = furnService.queryFurnById(id);
if (furn != null) {
//将furn对象放入request域
req.setAttribute("furn", furn);
req.getRequestDispatcher("/views/manage/furn_update.jsp")
.forward(req, resp);
} else {
System.out.println("查询不到该信息");
req.getRequestDispatcher("/views/manage/furn_manage.jsp")
.forward(req, resp);
}
}
java
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Furn furn =
DataUtils.copyParamToBean(req.getParameterMap(), new Furn());
if (furnService.updateFurn(furn) > 0) {
System.out.println("更新成功");
resp.sendRedirect(req.getContextPath() + "/manage/furnServlet?action=list");
} else {
req.setAttribute("msg", "更新失败");
req.getRequestDispatcher("/manage/furnServlet?action=display")
.forward(req, resp);
}
}
- 前端
furn_manage.jsp 点击修改,发出请求
html
<a href="manage/furnServlet?action=display&id=${furn.id}">
<i class="icon-pencil"></i>
</a>
在tr标签下面添加span标签
html
<span class="errorMsg"
style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;">${msg}</span>
furn_update.jsp 数据校验
js
$(":submit").click(function () {
var price = $("input[name='price']").val();
var saleNum = $("input[name='saleNum']").val();
var inventory = $("input[name='inventory']").val();
//价格 非零开头最多两位小数
var priceRegExp = /^[1-9]\d*(\.\d{1,2})?$/;
if (!priceRegExp.test(price)) {
$("span.errorMsg").text("价格格式不对");
return false;
}
//销量 非零开头正整数
var saleNumRegExp = /^0$|^[1-9]\d*$/;
if (!saleNumRegExp.test(saleNum)) {
$("span.errorMsg").text("销量格式不对");
return false;
}
//库存 非零开头正整数
var inventoryRegExp = /^0$|^[1-9]\d*$/;
if (!inventoryRegExp.test(inventory)) {
$("span.errorMsg").text("库存格式不对");
return false;
}
})
修改数据,点击提交