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

news2024/11/15 12:18:29

家居购项目

  • 🐇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();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected 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 {
    
    @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);
        }
    }
}

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对应BigDecimal
    
    private 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
     */
    @Override
    public 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();
    @Test
    public 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
     */
    @Override
    public 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();

    @Test
    public 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 {
    @Override
    public 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();
    @Test
    public 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();

    @Override
    public 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();

    @Test
    public 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) {//用户存在DB
            System.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");
    }

4.修改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.点击取消, 返回false
            var 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.coloradmin.cn/o/2097237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是网络安全,如果做好安全

随着互联网技术的迅猛发展&#xff0c;我们的生活和工作日益依赖于网络。然而&#xff0c;这也使得网络安全问题愈发重要。网络安全不仅关乎个人隐私的保护&#xff0c;还直接影响到企业的运营安全乃至国家的信息安全。今天我们就来了解下关于网络安全&#xff0c;当前存在哪些…

初识 Embedding,为何大家都基于它搭建私人智能客服?

随着 AI 技术的发展&#xff0c;大家在日常使用过程中经常会碰到一些目前 GPT4 也无法解决的问题&#xff1a; 无法获取个人私有数据信息&#xff0c;进行智能问答无法获取最新信息&#xff0c;LLM 模型训练都是都是有截止日期的无法定制化私有的专属模型&#xff0c;从而在某…

网站开发:HTML+CSS - 表格与表单

1. 前言​​​​​​​​​​​​​​ 表格与表单在网页开发中非常重要。表格使得用户可以更简洁清晰的去浏览信息。 表单提供了一种在客户端&#xff08;浏览器&#xff09;和服务器之间进行数据交互的方式。 以下为其主要作用&#xff1a; 用户交互和数据输入&#xff1a;表…

【射频模块的基本组成以及工作原理-3D动画演示】How RF Module works?

一. 模块简介 RF是射频&#xff0c;是高频交流变化电磁波的简称。通常指的是振荡频率从30KHz到300GHz之间的电磁波。而射频模块就指的是工作在射频频率之间的模块。 二. 基本组成 RF模块指的是一组RF发射器和RF接收器。工作频率为433MHz。 1. RF transmitter RF发射器接受串…

苹果手机丢了怎么找回?3个追踪法,30秒迅速定位

苹果手机已经成为了我们生活中交流、出行、工作的重要工具&#xff0c;如果不小心把手机弄丢了&#xff0c;则会给我们的衣食住行都带来很大的不便之处。对此&#xff0c;如果苹果手机丢了怎么找回呢&#xff1f; 本文将介绍3种追踪丢失手机的方法&#xff0c;帮助你快速定位丢…

关于Embedding的两种实现方式

目录 言简意赅方式一方式二以DNN为例两种方式全部demo代码 言简意赅 假设现在有一段话&#xff1a;“我爱你中国”&#xff0c;在训练入模的时候&#xff0c;常用的方法分别有&#xff1a;onehot、embedding、hash&#xff0c;如果词表很大、特征很多&#xff0c;那么onehot之…

macos 使用port查询并安装python2, python3多版本, 设置默认python版本方法

不管是新版macos还是旧版本的macos都可以使用macport这个包管理工具简单方便的在mac上面安装并存多个版本的python, 还可以利用port select --set python python3 来设置默认的python版本等. port search查询可用python安装包 命令 port search --name --line --regex ^pytho…

判断二分图

题目链接 判断二分图 题目描述 注意点 graph.length n不存在自环&#xff08;graph[u] 不包含 u&#xff09;不存在平行边&#xff08;graph[u] 不包含重复值&#xff09;如果 v 在 graph[u] 内&#xff0c;那么 u 也应该在 graph[v] 内&#xff08;该图是无向图&#xff0…

深度解析C++中函数重载与引用

&#x1f308;个人主页&#xff1a;Yui_ &#x1f308;Linux专栏&#xff1a;Linux &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;数据结构专栏&#xff1a;数据结构 &#x1f308;C专栏&#xff1a;C 文章目录 1. 函数重载1.1 函数重载概念1.2 C支持函数重载…

前端Flex布局常见的几个问题

1. 如何设置Flex布局的排列方向&#xff1f; 要设置Flex布局的排列方向&#xff0c;你可以使用CSS的flex-direction属性。该属性有四个值可以选择&#xff1a;row&#xff08;默认值&#xff0c;水平排列&#xff09;、row-reverse&#xff08;反向水平排列&#xff09;、colu…

零信任赋予安全牙齿,AI促使它更锋利

距离上次写关于安全的文字已经过去了很久很久&#xff0c;久到上次看到的AI还停留在TTS、ASR等最初的语音交互搜索类似的各种智能音箱以及通过关键字匹配的基于知识库的聊天的机器人。之后的几年各种视觉识别遍地开花&#xff0c;AI四小龙在人脸识别上成熟应用&#xff0c;再然…

Java:数字验证

Java中的有效数字验证&#xff1a;从混乱到清晰 引言问题背景初始尝试&#xff1a;一段令人困惑的代码解决方案&#xff1a;简化与重构 结语 引言 在计算机科学领域&#xff0c;确保输入数据的有效性至关重要。 尤其在处理用户提交的数据或解析文本文件时&#xff0c;确认数据…

第二证券:大洗牌!头部券商营收、净利集体下滑

前十券商营收团体下滑&#xff0c;银河证券跌幅最小 新股IPO数量锐减129家至44家&#xff0c;国内证券市场股票基金交易量日均规划 同比下降 6.83%……关于证券公司而言&#xff0c;本年上半年可谓多重要素叠加冲击&#xff0c;成果下滑难以避免。于大多数证券公司而言&#x…

金融行业选择数据安全交换系统三定律,你遵从了没?

金融行业对我国的重要性不言而喻&#xff0c;它作为国民经济的血脉&#xff0c;是国家核心竞争力的重要组成部分。金融行业是数据密集型行业&#xff0c;数据是金融行业的重要资产。数据在金融行业内部及内外部流动时&#xff0c;其价值才得以发挥&#xff0c;金融行业的业务以…

在麒麟系统安装php7.4中遇到的问题

一、安装过程 下载相关php安装包&#xff0c;进行解压&#xff0c;进入安装包&#xff0c;进行编译安装&#xff0c;编译 ./configure --prefix/soft/php74 --with-config-file-path/soft/php74/etc --with-libdir/usr/lib64 --with-freetype/usr/include/freetype2/free…

Zynq7000系列FPGA中的DDRC纠错码(ECC)

仅在半总线宽度&#xff08;16位&#xff09;数据宽度配置中提供可选的ECC支持。这种配置下&#xff0c;外部DRAM DDR设备需要26位&#xff0c;其中16位用于数据&#xff0c;10位用于ECC。每个数据字节使用独立的5位ECC字段&#xff0c;这种模式提供了单错误纠正和双错误检测的…

【C++】vector迭代器失效问题

本文是对vector迭代器失效问题的分析&#xff0c;需要对vector有一定了解&#xff0c;若还不了解的可以看这篇文章进行学习&#xff1a;【C】容器vector常用接口详解-CSDN博客 目录 一.什么是迭代器失效&#xff1f; 二.迭代器失效的典型案例 1.引起底层空间改变 2.指定位置…

Docker 在 Windows 上的使用指南

Docker 在 Windows 上的使用指南 Docker 是一种强大的容器化平台&#xff0c;广泛应用于开发和生产环境。本文将介绍如何在 Windows 系统上使用 Docker&#xff0c;包括容器的启动、常见问题的排查&#xff0c;以及网络问题的解决方法。 1. Docker 安装与配置 在开始使用 Do…

大模型书单指南:如何快速找到最适合你的那一本书?别找了就是这本!

大模型的书这么多&#xff0c;该怎么选呢&#xff1f; 本期书单就来教大家怎么快速地从众多大模型书中选到你想要的那一本&#xff01; 大模型基础 大模型入门不可错过的一本书&#xff0c;就是这本大模型界的经典畅销书**《大规模语言模型》**&#xff01;系统性强&#xf…

如何从 Mac 上清空的垃圾箱中恢复误删除的文件

在 Mac 上删除的文件将被移至垃圾箱并保留 30 天&#xff0c;然后才会被永久删除。但是&#xff0c;许多 Mac 用户可能会意外清空垃圾箱而没有意识到其中包含了重要文件。本指南包含从清空的垃圾箱中恢复 Mac 上已删除文件的所有有效方法。 当您意识到自己意外清空了 Mac 上的…