项目实战系列三: 家居购项目 第二部分

2024-09-06 06:12

本文主要是介绍项目实战系列三: 家居购项目 第二部分,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

家居购项目

  • 🐇servlet合并
    • 🍎方案一: 隐藏域
    • 🍎方案二: 反射+模板设计模式+动态代理
  • 🌳显示家居
  • 🌳添加家居
    • 🍉解决重复添加
    • 🍉后端数据校验说明
    • 🍉BeanUtils自动封装Bean
  • 🌳删除家居
  • 🌳修改家具

在这里插入图片描述

🐇servlet合并

需求
1.如果处理一个请求, 就对应一个Servlet, 会造成Servlet文件太多, 不利于管理.
2.在项目开发中, 同一个业务(模块), 一般对应一个Servlet即可, 比如LoginServlet, RegisterServlet, 都是在处理和会员相关的业务, 应当合并.

🍎方案一: 隐藏域

1.给login和register表单增加hidden元素, 区分登录和注册.
2但信息提交到MemberServlet后, 获取action参数值
3.分发请求.

代码实现
1.修改web/views/member/login.jsp, 增加隐藏域, 修改请求url为memberServlet

在这里插入图片描述

2.新建src/com/zzw/furns/web/MemberServlet.java, 合并到MemberServlet

public class MemberServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String action = request.getParameter("action");if ("login".equals(action)) {login(request, response);} else if ("register".equals(action)) {register(request, response);} else {response.setContentType("text/html;charset=UTF-8");response.getWriter().write("<h1>404</h1>");}}protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");Member member = new Member(null, username, password, null);if (member != null) {System.out.println("登录成功");request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request, response);} else {System.out.println("登录失败");request.setAttribute("msg", "用户名或密码错误,请重新登录");request.setAttribute("username", username);request.getRequestDispatcher(request.getHeader("Referer")).forward(request, response);}}protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");String email = request.getParameter("email");Member member = new Member(null, username, password, email);if (!memberService.isExistsByUsername(username)) {//用户名可用if (memberService.registerMember(member)) {//注册成功System.out.println("注册成功,请登录");request.getRequestDispatcher("/views/member/register_ok.jsp").forward(request, response);} else {//注册失败System.out.println("注册失败,请重新注册");request.getRequestDispatcher("/views/member/register_fail.jsp").forward(request, response);}} else {request.setCharacterEncoding("UTF-8");request.setAttribute("msg", "用户名已存在,请重新注册");request.setAttribute("username", username);request.setAttribute("active", "register_tab");request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);}}
}

3.测试…

🍎方案二: 反射+模板设计模式+动态代理

在这里插入图片描述

1.新建BasicServlet类, 继承HttpServlet

public class BasicServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected 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);}}
}

2.子类中没有doGet, doPost方法, 会调用父类的doGet, doPost.

在这里插入图片描述

🌳显示家居

需求分析
1.给后台管理提供独立登陆页面 [manage_login.jsp(已提供)
2.管理员(admin表)登陆成功后, 显示管理菜单页面
3.管理员点击家居管理, 显示所有家居信息

程序框架图
在这里插入图片描述

1.页面准备

在这里插入图片描述

2.新建admin表 👉 参考member表

-- 创建会员表
CREATE TABLE admin (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(32) NOT NULL DEFAULT '' UNIQUE,`password` VARCHAR(32) NOT NULL,email VARCHAR(64)
)CHARSET utf8 ENGINE INNODB;-- 插入数据
INSERT INTO admin VALUES(NULL, 'admin', MD5('admin'), '978964140@qq.com');
INSERT INTO admin VALUES(NULL, 'zhaozhiwei', MD5('zhaozhiwei'), '978964140@qq.com');
INSERT INTO admin(id, username, `password`, email) VALUES(NULL, 'tom', MD5('tom'), 'tom@sohu.com');-- 查询
SELECT * FROM admin;
SELECT id, username, `password`, email FROM admin WHERE username = 'admine'
SELECT id, username, `password`, email FROM admin WHERE username = 'admin123' AND `password` = MD5('123456');UPDATE admin SET `password`=MD5('admin') WHERE username='admin';

3.新建furn表

-- 创建家居网购需要的数据库和表
-- 删除数据库
DROP DATABASE IF EXISTS home_furnishing;-- 删除表
DROP TABLE furn;-- 创建数据库
CREATE DATABASE home_furnishing;-- 切换
USE home_furnishing;-- id int(11) 11表示的是宽度
-- id int(2)  2表示的也是宽度
-- 66360 -> int(11)  00000066360
-- 66360 -> int(2)   66360
-- unsigned 无符号类型,表示的范围大一些-- 创建家居表
CREATE TABLE furn (id INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT, -- id编号`name` VARCHAR(32) NOT NULL,-- 家居名business VARCHAR(32) NOT NULL,-- 商家price DECIMAL(10, 2) NOT NULL,-- 价格saleNum INT UNSIGNED NOT NULL,-- 销量inventory INT UNSIGNED NOT NULL,-- 库存image_path VARCHAR(256) NOT NULL -- 图片
)CHARSET utf8 ENGINE INNODB;-- 插入数据
insert into `furn` (`id`, `name`, `business`, `price`, `saleNum`, `inventory`, `image_path`) values('1','小台灯','南极人','35.50','3002','6998','assets/images/product-image/default.jpg');
insert into `furn` (`id`, `name`, `business`, `price`, `saleNum`, `inventory`, `image_path`) values('2','黑丝袜','南极人','25.50','4002','5998','assets/images/product-image/default.jpg');
insert into `furn` (`id`, `name`, `business`, `price`, `saleNum`, `inventory`, `image_path`) values('3','胸罩','南极人','45.50','5002','4998','assets/images/product-image/default.jpg');-- 查询数据
SELECT id, `name`, business, price, saleNum, inventory, image_path FROM furn WHERE `name` = '小台灯' LIMIT 1, 3;
SELECT id, `name`, business, price, saleNum, inventory, image_path FROM furn
SELECT COUNT(*) FROM furn WHERE `name` LIKE '%台%';-- 删除数据
DELETE FROM furn WHERE id = 32;-- 修改数据
UPDATE furn SET image_path = 'assets/images/product-image/default.jpg';
UPDATE furn SET `name`='手机', business='小米', price=3000, saleNum=9000, inventory=9000, image_path='zzw' WHERE id=37
UPDATE furn SET `name`='笔记本', business='戴尔', price=6000.00, saleNum=6500, inventory=5500 WHERE id=75;

4.新建Admin实体类 src/com/zzw/furns/entity/Admin.java

public class Admin {private Integer id;private String username;private String password;private String email;public Admin() {}
}

5.新建Furn实体类(无参构造器与set方法底层反射用, get方法前端EL表达式用) src/com/zzw/furns/entity/Furn.java

public class Furn {private String name;private String business;private BigDecimal price;//Decimal对应BigDecimalprivate Integer saleNum;private Integer inventory;private String imagePath;public Furn() {}
}

6.新建src/com/zzw/furns/dao/AdminDao.java

public interface AdminDAO {//根据用户名和密码查询数据库中有无对应的Admin对象public Admin queryAdminByUsernameAndPassword(String username, String password);
}

7.新建src/com/zzw/furns/dao/impl/AdminDaoImpl.java

public class AdminDAOImpl extends BasicDAO<Admin> implements AdminDAO {/*** 根据用户名和密码查询对应的Admin对象* @param username 用户名* @param password 密码* @return 对应的Admin对象, 如果没有 则返回null*/@Overridepublic Admin queryAdminByUsernameAndPassword(String username, String password) {String sql = "SELECT id, username, `password`, email FROM admin WHERE username = ? AND `password` = MD5(?)";Admin admin = querySingle(sql, Admin.class, username, password);return admin;}
}

8.测试, 新建src/com/zzw/furns/test/AdminDAOTest.java

public class AdminDAOTest {private AdminDAO adminDAO = new AdminDAOImpl();@Testpublic void queryAdminByUsernameAndPassword() {String username = "zhaozhiwei";String password = "123123";Admin admin = adminDAO.queryAdminByUsernameAndPassword(username, password);System.out.println(admin);}
}

9.新建src/com/zzw/furns/service/AdminService.java

public interface AdminService {/*** 根据传入的admin信息, 返回对应在DB中的admin对象* @param admin 是根据用户登录构建一个admin* @return 返回的是对应的DB中的admin对象, 如果不存在返回null*/public Admin login(Admin admin);
}

10.新建src/com/zzw/furns/service/AdminServiceImpl.java

public class AdminServiceImpl implements AdminService {private AdminDAO adminDAO = new AdminDAOImpl();/*** 判断用户名和密码是否存在* @param username 用户名* @param password 密码* @return*/@Overridepublic Admin login(Admin admin) {//返回一个对象return adminDAO.queryAdminByUsernameAndPassword(admin.getUsername(), admin.getPassword());}
}

11.测试, 新建src/com/zzw/furns/test/AdminServiceTest.java

public class AdminServiceTest {private AdminService adminService = new AdminServiceImpl();@Testpublic void login() {Admin admin = new Admin(null, "zhaozhiwei", "123123", null);Admin login = adminService.login(admin);System.out.println("login = " + login);}
}

12.新建src/com/zzw/furns/dao/FurnDao.java

public interface FurnDAO {//返回所有Furn对象public List<Furn> list();
}

13.新建src/com/zzw/furns/dao/impl/FurnDaoImpl.java
给字段起别名, 对应实体类的某一个属性

public class FurnDAOImpl extends BasicDAO<Furn> implements FurnDAO {@Overridepublic List<Furn> listAll() {String sql = "SELECT id, `name`, business, price, saleNum, inventory, image_path as imagePath FROM furn";List<Furn> furns = queryMany(sql, Furn.class);return furns;}
}

14.测试, 新建src/com/zzw/furns/test/FurnDaoTest.java

public class FurnDAOTest {private FurnDAO furnDAO = new FurnDAOImpl();@Testpublic void listAll() {List<Furn> furns = furnDAO.listAll();for (Furn furn : furns) {System.out.println(furn);}}
}

15.新建src/com/zzw/furns/service/FurnService.java

public interface FurnService {//显示家居public List<Furn> queryFurn();
}

16.新建src/com/zzw/furns/service/AdminServiceImpl.java

public class FurnServiceImpl implements FurnService {private FurnDAO furnDAO = new FurnDAOImpl();@Overridepublic List<Furn> queryFurn() {List<Furn> furns = furnDAO.listAll();return furns;}
}

17.测试, 新建src/com/zzw/furns/test/AdminServiceTest.java

public class FurnServiceTest {private FurnService furnService = new FurnServiceImpl();@Testpublic void queryFurn() {List<Furn> furns =  furnService.queryFurn();for (int i = 0; i < furns.size(); i++) {System.out.println(furns.get(i));}}
}

18.接通web层, 创建src/com/zzw/furns/web/AdminServlet.java, 管理员登录Servlet

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);admin = adminService.login(admin);if (admin != null) {//用户存在DBSystem.out.println("管理员登陆成功...");request.getRequestDispatcher("/views/manage/manage_menu.jsp").forward(request, response);} else {//用户不存在System.out.println("该管理员用户不存在, 登陆失败");request.setAttribute("username", username);request.setAttribute("errorMsg", "用户名或密码不正确");request.getRequestDispatcher("/views/manage/manage_login.jsp").forward(request, response);}}
}

配置web.xml

<servlet><servlet-name>AdminServlet</servlet-name><servlet-class>com.zzw.furns.web.AdminServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>AdminServlet</servlet-name><url-pattern>/adminServlet</url-pattern>
</servlet-mapping>

19.创建src/com/zzw/furns/web/FurnServlet.java, 家居显示Servlet

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);}
}

配置web.xml

<servlet><servlet-name>FurnServlet</servlet-name><servlet-class>com.zzw.furns.web.FurnServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>FurnServlet</servlet-name><url-pattern>/manage/furnServlet</url-pattern>
</servlet-mapping>

20.前端页面, web/views/manage/manage_login.jsp, 管理员登录页面

<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>

21.修改manage_menu.jsp, 家居菜单页面
在这里插入图片描述

22.修改furn_manage.jsp, 家居显示页面

<thead>
<tr><th>家居名</th><th>商家</th><th>价格</th><th>销量</th><th>库存</th><th>图片</th><th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${furns}" var="furn"><tr><td class="product-thumbnail"><a href="#"><img class="img-responsive ml-3"src="assets/images/product-image/1.jpg"alt=""/></a></td><td class="product-name"><a href="#">${furn.name}</a></td><td class="product-name"><a href="#">${furn.business}</a></td><td class="product-price-cart"><span class="amount">${furn.price}</span></td><td class="product-quantity">${furn.saleNum}</td><td class="product-quantity">${furn.inventory}</td><td class="product-remove"><a href="#"><i class="icon-pencil"></i></a><a href="#"><i class="icon-close"></i></a></td></tr>
</c:forEach>
</tbody>

23.测试

1)管理员登录

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

🌳添加家居

思路分析
1.请求添加家居, 请求FurnServlet的add方法, 将前端提交的数据封装到Furn对象
2.调用FurnService.add(Furn furn)方法
3.跳转到显示家居的页面

程序框架图
在这里插入图片描述

1.修改com.zzw.furns.FurnDAO

//添加Furn对象
public boolean add(Furn furn);

2.修改com.zzw.furns.impl.FurnDaoImpl

@Override
public boolean add(Furn furn) {String sql = "INSERT INTO furn(id, `name`, business, price, saleNum, inventory, image_path) " +"VALUES(NULL, ?, ?, ?, ?, ?, ?)";int updateRows = update(sql, furn.getName(), furn.getBusiness(), furn.getPrice(),furn.getSaleNum(), furn.getInventory(), furn.getImagePath());return updateRows > 0;
}

3.测试, 修改FurnDaoTest

@Test
public void add() {BigDecimal price = new BigDecimal(32.2);String imagePath = "assets/images/product-image/4.jpg";Furn furn =new Furn(null, "桌子", "南极人", price, 4500, 8000, imagePath);System.out.println(furnDAO.add(furn) ? "添加成功" : "添加失败");
}

4.修改com.zzw.furns.FurnService

//添加家居
public boolean addFurn(Furn furn);
/*** 添加家居** @param furn 前端传来的Furn对象* @return 返回布尔值*/
@Override
public boolean addFurn(Furn furn) {return furnDAO.add(furn);
}

5.修改com.zzw.furns.impl.FurnServiceImpl

/*** 添加家居** @param furn 前端传来的Furn对象* @return 返回布尔值*/
@Override
public boolean addFurn(Furn furn) {return furnDAO.add(furn);
}

6.测试,修改com.zzw.furns.impl.FurnServiceTest

/*** 添加家居** @param furn 前端传来的Furn对象* @return 返回布尔值*/
@Override
public boolean addFurn(Furn furn) {return furnDAO.add(furn);
}

7.工具类src/com/zzw/furns/utils/DataUtils.java

public class DataUtils {public static int parseInt(String str, Integer defaultValue) {try {int num = Integer.parseInt(str);return num;} catch (NumberFormatException e) {return defaultValue;}}
}

8.web层, 修改FurnServlet, 添加方法add

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, "assets/images/product-image/default.jpg");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);}
}

9.解决中文乱码问题
在BasicServlet中设置utf-8.

10.前端: furn_manage跳转到添加家居页面

<!-- Single Wedge Start -->
<div class="header-bottom-set dropdown"><a href="views/manage/furn_add.jsp">添加家居</a>
</div>

11.添加furn_add.jsp

<!--添加到table标签的下一行-->
<span class="errorMsg"style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;"></span>

在这里插入图片描述
在这里插入图片描述

12.测试

在这里插入图片描述在这里插入图片描述

🍉解决重复添加

1.请求转发设置成重定向
在这里插入图片描述

🍉后端数据校验说明

后端方案一: 修改FurnServlet.java

String name = req.getParameter("name");
if (StringUtils.isEmpty(name)) {req.setAttribute("msg", "商品名不能为空");req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);return;
}String business = req.getParameter("business");
if (StringUtils.isEmpty(business)) {req.setAttribute("msg", "商家不能为空");req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);return;
}String saleNumTemp = req.getParameter("saleNum");
//不能为空
if (StringUtils.isEmpty(saleNumTemp)) {req.setAttribute("msg", "销量不能为空");req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);return;
}String inventoryTemp = req.getParameter("inventory");
if (StringUtils.isEmpty(inventoryTemp)) {req.setAttribute("msg", "库存不能为空");req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);return;
}String priceTemp = req.getParameter("price");
if (StringUtils.isEmpty(priceTemp)) {req.setAttribute("msg", "价格不能为空");req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);return;
}Integer saleNum = null;
try {saleNum = Integer.parseInt(saleNumTemp);
} catch (NumberFormatException e) {req.setAttribute("msg", "销量格式错误");req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);return;
}Integer inventory = null;
try {inventory = Integer.parseInt(inventoryTemp);
} catch (NumberFormatException e) {req.setAttribute("msg", "库存格式错误");req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);return;
}BigDecimal price = null;
try {price = new BigDecimal(priceTemp);
} catch (NumberFormatException e) {req.setAttribute("msg", "价格格式错误");req.getRequestDispatcher("/views/manage/furn_add.jsp").forward(req, resp);return;
}

前端数据校验, 修改web/views/manage/furn_add.jsp

<script src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">window.onload = function () {$("input[type='submit']")[0].onclick = function () {if ($("input[name='name']").val() == "" || $("input[name='name']").val() == null) {alert("请输入家居名");return false;} else if ($("input[name='business']").val() == "" || $("input[name='business']").val() == null) {alert("请输入商家名");return false;} else if ($("input[name='price']").val() == "" || $("input[name='price']").val() == null) {alert("请输入价格");return false;} else if ($("input[name='saleNum']").val() == "" || $("input[name='saleNum']").val() == null) {alert("请输入销量");return false;} else if ($("input[name='inventory']").val() == "" || $("input[name='inventory']").val() == null) {alert("请输入库存");return false;}else if (!/^\d+(\.\d+)?$/.test($("input[name='price']").val())) {alert("价格格式不对");return false;} else if (!/^\d+$/.test($("input[name='saleNum']").val())) {alert("销量格式不对");return false;} else if (!/^\d+$/.test($("input[name='inventory']").val())) {alert("库存格式不对");return false;}}}
</script>

🍉BeanUtils自动封装Bean

1.引入jar包

2.修改src/com/zzw/furns/utils/DataUtils.java, 增加方法

//将方法, 封装到静态方法, 方便使用
public static <T> T copyParamToBean(Map value, T bean) {try {//req.getParameterMap() 将数据封装到furn对象// 底层使用反射封装数据// 前端的name属性值需要和javabean的属性名一致BeanUtils.populate(bean, value);} catch (Exception e) {throw new RuntimeException(e);}return bean;
}

3.修改src/com/zzw/furns/web/FurnServlet.javaadd方法, 使用BeanUtils自动封装javabean

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小技巧👉
在这里插入图片描述
2.报错
原因: 由于前端没有传imagePath的字段, 所以后端在构建furn对象的时候, imagePath属性位null
解决方案👇
在这里插入图片描述

🌳删除家居

需求分析
1.管理员进入到家居管理页面
2.点击删除家居链接, 弹出确认窗口, 确认-删除, 取消-放弃

程序框架图

在这里插入图片描述

1.修改com.zzw.furns.FurnDAO

//根据id删除对应的furn对象
public boolean deleteFurnById(int id);

2.修改com.zzw.furns.impl.FurnDaoImpl

@Override
public boolean deleteFurnById(int id) {String sql = "DELETE FROM furn WHERE id = ?";int updateRows = update(sql, id);return updateRows > 0;
}

3.测试, 修改FurnDaoTest

@Test
public void deleteFurnById() {int id = 30;System.out.println("执行结果= " + furnDAO.deleteFurnById(id));
}

4.修改com.zzw.furns.FurnService

//根据id删除家居
public boolean deleteFurnById(int id);

5.修改com.zzw.furns.impl.FurnServiceImpl

@Override
public boolean deleteFurnById(int id) {return furnDAO.deleteFurnById(id);
}

6.测试,修改com.zzw.furns.impl.FurnServiceTest

@Test
public void deleteFurnById() {int id = 31;System.out.println("执行结果= " + furnService.deleteFurnById(id));
}

6.web层 - 修改src/com/zzw/furns/web/FurnServlet.java, 增加del方法

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("删除失败");req.setAttribute("msg", "删除失败");}resp.sendRedirect(req.getContextPath() + "/manage/furnServlet?action=list");}

7.修改web/views/manage/furn_manage.jsp页面

<a furnName="${furn.name}" href="manage/furnServlet?action=del&id=${furn.id}"><i class="icon-close"></i>
</a>

jQuery操作父元素, 兄弟元素, 子元素, 请移步👉
js弹框请移步👉

<script src="scripts/jquery-3.6.0.js"></script>
<script type="text/javascript">window.onload = function () {$("a[furnName]").click(function () {var furnName = $(this).attr("furnName");//js弹框//1.window.confirm 方法会弹出一个确认窗口//2.点击确定, 返回true//3.点击取消, 返回falsevar b = window.confirm("你确认要删除 " + furnName+ " 家居信息吗?");if (!b) {return false;}//简便写法return window.confirm("你确认要删除 " + furnName+ " 家居信息吗?");//最终写法return confirm("你确定要删除 " + furnName + " 家居信息嘛?");});}
</script>

🌳修改家具

思路分析
1.管理员进入家居管理页面furn_manage.jsp
2.点击修改家居链接, 回显该家居信息 furn_update.jsp
3.填写新的信息, 点击修改家居按钮
4.修改成功后, 显示刷新后的家居列表

程序框架图

在这里插入图片描述

1.修改com.zzw.furns.FurnDAO

//根据id查询furn对象
public Furn queryFurnById(int id);//将传入的furn对象, 更新到数据库
public boolean updateFurn(Furn furn);

2.修改com.zzw.furns.impl.FurnDaoImpl

/*** 根据传来的id查询对应的Furn对象** @param id 参数* @return 返回查询到的Furn对象*/
@Override
public Furn queryFurnById(int id) {String sql = "SELECT id, `name`, business, price, saleNum, inventory, " +"image_path as imagePath FROM furn WHERE id = ?";Furn furn = querySingle(sql, Furn.class, id);return furn;
}/*** 根据id修改furn表对应的记录* @param furn 要修改的内容* @return 返回true或false*/
@Override
public boolean updateFurn(Furn furn) {String sql = "UPDATE furn SET `name`=?, business=?, price=?, saleNum=?, inventory=?, image_path=? WHERE id=?";int updateRows =update(sql, furn.getName(), furn.getBusiness(), furn.getPrice(), furn.getSaleNum(),furn.getInventory(), furn.getImagePath(), furn.getId());return updateRows > 0;
}

3.测试, 修改FurnDaoTest

@Test
public void queryFurnById() {int id = 75;Furn furn = furnDAO.queryFurnById(id);System.out.println(furn);
}@Test
public void updateFurn() {Furn furn = new Furn(5, "手机", "小米", new BigDecimal(3000), 6000, 9000, "zzw");furnDAO.updateFurn(furn);System.out.println();
}

4.修改com.zzw.furns.FurnService

//根据id查询家居
public Furn queryFurnById(int id);//根据id修改家居信息
public boolean updateFurn(Furn furn);

5.修改com.zzw.furns.impl.FurnServiceImpl

/*** 根据前端传来的id查询家居** @param id 参数* @return 返回查询到的家居*/
@Override
public Furn queryFurnById(int id) {Furn furn = furnDAO.queryFurnById(id);return furn;
}/*** 根据id修改家居信息** @param furn 要修改的内容* @return 返回true或false*/
@Override
public boolean updateFurn(Furn furn) {return furnDAO.updateFurn(furn);
}

6.测试,修改com.zzw.furns.impl.FurnServiceTest

@Test
public void queryFurnById() {int id = 75;Furn furn = furnService.queryFurnById(id);System.out.println(furn);
}@Test
public void updateFurn() {Furn furn = new Furn(75, "耳麦", "苹果", new BigDecimal(500),5000, 7000, "");System.out.println(furnService.updateFurn(furn));
}

7.web层 - 修改src/com/zzw/furns/web/FurnServlet.java, 增加display方法和update方法

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("/manage/furnServlet?action=list").forward(req, resp);}
}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&id=" + furn.getId()).forward(req, resp);}
}

8.前端, 修改web/views/manage/furn_manage.jsp页面, 点击修改,发出请求

<a href="manage/furnServlet?action=display&id=${furn.id}"><i class="icon-pencil"></i>
</a>

9.添加web/views/manage/furn_update.jsp页面, 在tr标签下面添加span标签

<span class="errorMsg"style="float: right; font-weight: bold; color: lightgray; font-size: 20pt; margin-left: 10px;">${msg}</span>

在这里插入图片描述
在这里插入图片描述

10.修改web/views/manage/furn_update.jsp页面, 数据校验

<script src="script/jquery-3.6.0.min.js"></script>
<script type="text/javascript">window.onload = function () {$("input[type='submit']")[0].onclick = function () {if ($("input[name='name']").val() == "" || $("input[name='name']").val() == null) {alert("请输入家居名");return false;} else if ($("input[name='business']").val() == "" || $("input[name='business']").val() == null) {alert("请输入商家名");return false;} else if ($("input[name='price']").val() == "" || $("input[name='price']").val() == null) {alert("请输入价格");return false;} else if ($("input[name='saleNum']").val() == "" || $("input[name='saleNum']").val() == null) {alert("请输入销量");return false;} else if ($("input[name='inventory']").val() == "" || $("input[name='inventory']").val() == null) {alert("请输入库存");return false;}else if (!/^\d+(\.\d+)?$/.test($("input[name='price']").val())) {alert("价格格式不对");return false;} else if (!/^\d+$/.test($("input[name='saleNum']").val())) {alert("销量格式不对");return false;} else if (!/^\d+$/.test($("input[name='inventory']").val())) {alert("库存格式不对");return false;}}}
</script>

11.测试,修改数据,点击提交

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

这篇关于项目实战系列三: 家居购项目 第二部分的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141227

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

闲置电脑也能活出第二春?鲁大师AiNAS让你动动手指就能轻松部署

对于大多数人而言,在这个“数据爆炸”的时代或多或少都遇到过存储告急的情况,这使得“存储焦虑”不再是个别现象,而将会是随着软件的不断臃肿而越来越普遍的情况。从不少手机厂商都开始将存储上限提升至1TB可以见得,我们似乎正处在互联网信息飞速增长的阶段,对于存储的需求也将会不断扩大。对于苹果用户而言,这一问题愈发严峻,毕竟512GB和1TB版本的iPhone可不是人人都消费得起的,因此成熟的外置存储方案开

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言